From 7845bd3f60c718ef893fd4efc314b195827b696d Mon Sep 17 00:00:00 2001 From: Official-Husko Date: Tue, 25 Jun 2024 16:08:55 +0200 Subject: [PATCH] sync latest changes --- .github/ISSUE_TEMPLATE/bug_report.md | 75 +- .github/ISSUE_TEMPLATE/feature_request.md | 40 +- .github/ISSUE_TEMPLATE/site-information.md | 20 +- .../ISSUE_TEMPLATE/site-support-request.md | 44 +- .github/workflows/build_windows.yml | 43 + .github/workflows/code_analysis.yml | 330 ++++---- .gitignore | 53 +- .vscode/launch.json | 38 +- Build Releases.bat | 1 - LICENSE | 746 +++++++++--------- README.md | 648 +++++++-------- enable_env.bat | 1 - main.py | 254 +++++- modules/auto_update.py | 178 ++--- modules/availability_checker.py | 172 ++-- modules/config_manager.py | 304 +++---- modules/deprecated/README.md | 10 +- modules/deprecated/anonfiles.py | 108 +-- modules/deprecated/anonfilesme.py | 128 +-- modules/deprecated/anonymfile-api.py | 132 ++-- modules/deprecated/anyfile.py | 128 +-- modules/deprecated/bayfiles.py | 108 +-- modules/deprecated/bayfilesio.py | 128 +-- modules/deprecated/bunkrr.py | 402 +++++----- modules/deprecated/filechan.py | 108 +-- modules/deprecated/filemail.py | 118 +-- modules/deprecated/filestore.py | 176 ++--- modules/deprecated/filetransfer.py | 340 ++++---- modules/deprecated/gofilecc.py | 128 +-- modules/deprecated/hotfile.py | 108 +-- modules/deprecated/krakenfiles_api.py | 140 ++-- modules/deprecated/letsupload.py | 108 +-- modules/deprecated/lolabits.py | 108 +-- modules/deprecated/megaupload.py | 108 +-- modules/deprecated/myfile.py | 108 +-- modules/deprecated/nitrofile.py | 128 +-- modules/deprecated/openload.py | 106 +-- modules/deprecated/rapidshare.py | 108 +-- modules/deprecated/shareonline.py | 108 +-- modules/deprecated/udrop.py | 234 +++--- modules/deprecated/up2share.py | 258 +++--- modules/deprecated/upvid.py | 108 +-- modules/deprecated/vshare.py | 108 +-- modules/deprecated/wetransfer.py | 376 ++++----- modules/deprecated/yourfilestore.py | 168 ++-- modules/old_scripts/anontransfer.py | 208 ++--- modules/old_scripts/anonymfile.py | 154 ++-- modules/old_scripts/bowfile.py | 154 ++-- modules/old_scripts/catbox.py | 154 ++-- modules/old_scripts/clicknupload.py | 180 ++--- modules/old_scripts/cyberfile.py | 200 ++--- modules/old_scripts/delafil.py | 92 +-- modules/old_scripts/doodrive.py | 272 +++---- modules/old_scripts/downloadgg.py | 142 ++-- modules/old_scripts/easyupload.py | 286 +++---- modules/old_scripts/fastupload.py | 252 +++--- modules/old_scripts/filebin.py | 90 +-- modules/old_scripts/fileio.py | 184 ++--- modules/old_scripts/files_dp_ua.py | 112 +-- modules/old_scripts/filesadmin.py | 202 ++--- modules/old_scripts/filesfm.py | 124 +-- modules/old_scripts/filesi.py | 94 +-- modules/old_scripts/fileupload.py | 160 ++-- modules/old_scripts/gofile.py | 100 +-- modules/old_scripts/hexupload.py | 196 ++--- modules/old_scripts/keep.py | 140 ++-- modules/old_scripts/krakenfiles.py | 140 ++-- modules/old_scripts/litterbox.py | 156 ++-- modules/old_scripts/mixdrop.py | 122 +-- modules/old_scripts/onecloudfile.py | 212 ++--- modules/old_scripts/onefichier.py | 118 +-- modules/old_scripts/oshi.py | 92 +-- modules/old_scripts/pixeldrain.py | 88 +-- modules/old_scripts/rapidgator.py | 290 +++---- modules/old_scripts/tempsend.py | 148 ++-- modules/old_scripts/tmpfiles.py | 98 +-- modules/old_scripts/transfer.py | 94 +-- modules/old_scripts/ufile.py | 248 +++--- modules/old_scripts/usercloud.py | 184 ++--- modules/old_scripts/usersdrive.py | 154 ++-- modules/old_scripts/wdho.py | 200 ++--- modules/preset_manager.py | 56 +- modules/pretty_print.py | 20 +- modules/proxy_scraper.py | 100 +-- modules/setup.py | 224 ------ modules/site_data.py | 308 -------- modules/{ => sites}/buzzheavier.py | 119 ++- modules/{ => utils}/file_hash_calculator.py | 76 +- modules/{ => utils}/file_size_calculator.py | 120 +-- modules/{ => utils}/logger.py | 198 ++--- modules/{ => utils}/storage.py | 16 +- presets/cs-rin-ru.json | 66 +- presets/f95.json | 56 +- presets/template.json5 | 56 +- requirements.txt | 42 +- test.png | Bin 957832 -> 0 bytes update_modules.py | 36 - 97 files changed, 7198 insertions(+), 7478 deletions(-) create mode 100644 .github/workflows/build_windows.yml delete mode 100644 Build Releases.bat delete mode 100644 enable_env.bat delete mode 100644 modules/setup.py delete mode 100644 modules/site_data.py rename modules/{ => sites}/buzzheavier.py (93%) rename modules/{ => utils}/file_hash_calculator.py (90%) rename modules/{ => utils}/file_size_calculator.py (97%) rename modules/{ => utils}/logger.py (96%) rename modules/{ => utils}/storage.py (97%) delete mode 100644 test.png delete mode 100644 update_modules.py diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index efe0f68..73e8e01 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,38 +1,37 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: Official-Husko - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. +--- +name: Bug report +about: Create a report to help me improve Mul-Tor +title: '[BUG] ' +labels: bug +assignees: Official-Husko + +--- + +**Describe the bug**\ +A clear and concise description of what the bug is. + +**To Reproduce**\ +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior**\ +A clear and concise description of what you expected to happen. + +**Screenshots**\ +If applicable, add screenshots to help explain your problem. + +**Setup (please complete the following information):** + - OS: [e.g. Windows 11] + - Tool Version: [e.g. 1.5.2] + - Filename/s: [e.g. Vacation Images.7z, Birthday Images.7z] + - File Size/s: [e.g. 2.5 MB, 2 GB] + - Selected Hosts: [e.g. Pixeldrain, Gofile] + +**Additional info**\ +Add any other info about the problem here. + +> [!CAUTION] +> Please always attach the runtime.log file. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 11fc491..ee51195 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,20 +1,20 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. +--- +name: Feature request +about: Suggest an idea for this project +title: '[REQ] ' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.**\ +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like**\ +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered**\ +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context**\ +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/site-information.md b/.github/ISSUE_TEMPLATE/site-information.md index fb2b3e1..8164b7f 100644 --- a/.github/ISSUE_TEMPLATE/site-information.md +++ b/.github/ISSUE_TEMPLATE/site-information.md @@ -1,10 +1,10 @@ ---- -name: Site information -about: 'This is used to show known website issues ' -title: "[INFO]" -labels: info -assignees: Official-Husko - ---- - - +--- +name: Site information +about: 'This is used to show known website issues' +title: "[INFO] " +labels: info +assignees: Official-Husko + +--- + + diff --git a/.github/ISSUE_TEMPLATE/site-support-request.md b/.github/ISSUE_TEMPLATE/site-support-request.md index 4df8289..59be2aa 100644 --- a/.github/ISSUE_TEMPLATE/site-support-request.md +++ b/.github/ISSUE_TEMPLATE/site-support-request.md @@ -1,22 +1,22 @@ ---- -name: Site Support Request -about: Suggest a new site to be supported -title: "[SITE REQ]" -labels: enhancement, site request -assignees: Official-Husko - ---- - -**Please give me the links that apply below** -Main Website: https://example.com -API URL: https://api.example.com - -**Please fill out the information below:** - -- [ ] This site has an API -- [ ] This site requires an account -- [ ] This site is requires a subscription -- [ ] I would be willing to give a premium account to add the site - -**Is there anything else you would like to add that might help me?** -This can be anything you want. +--- +name: Site Support Request +about: Suggest a new site to be supported +title: "[SITE REQ] " +labels: enhancement, site request +assignees: Official-Husko + +--- + +**Please give me the links that apply below**\ +Main Website: https://example.com +API URL: https://api.example.com + +**Please fill out the information below:**\ + +- [ ] This site has an API +- [ ] This site requires an account +- [ ] This site is requires a subscription +- [ ] I would be willing to give a premium account to add the site + +**Is there anything else you would like to add that might help me?**\ +This can be anything you want. diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml new file mode 100644 index 0000000..26a23da --- /dev/null +++ b/.github/workflows/build_windows.yml @@ -0,0 +1,43 @@ +name: Build Windows Executable + +on: + push: + branches: + - development # Adjust branch name as needed + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12.4 # Specify the Python version you need + + - name: Create virtual environment and build + shell: bash + run: | + python -m venv .env + source .env/Scripts/activate + python -m pip install --upgrade pip + pip install pyinstaller + pip install -r requirements.txt # Replace with your requirements file if exists + + pyinstaller --paths .env/Lib/site-packages \ + --hidden-import plyer.platforms.win.filechooser \ + --add-data=".env/Lib/site-packages/grapheme/data/*;grapheme/data/" \ + --onefile \ + --icon "icon.ico" \ + --console \ + --name "Mul-Tor" \ + main.py + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: mul-tor-windows + path: dist/Mul-Tor.exe # Adjust the path to your executable relative to the root of the repository diff --git a/.github/workflows/code_analysis.yml b/.github/workflows/code_analysis.yml index 07ea0b9..32bb8ea 100644 --- a/.github/workflows/code_analysis.yml +++ b/.github/workflows/code_analysis.yml @@ -1,166 +1,166 @@ -name: Code Analysis - -on: - push: - branches: [ "*" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "*" ] - schedule: - - cron: '33 2 * * 5' - -jobs: - PyLint: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.11"] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install Application Dependencies - run: | - pip install -r requirements.txt - - name: Install dependencies - run: | - pip install pylint - - name: Analysing the code with pylint - run: | - pylint $(git ls-files '*.py') - - Bandit: - permissions: - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Bandit Scan - uses: shundor/python-bandit-scan@9cc5aa4a006482b8a7f91134412df6772dbda22c - with: # optional arguments - # exit with 0, even with results found - exit_zero: true # optional, default is DEFAULT - # Github token of the repository (automatically created by Github) - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information. - # File or directory to run bandit on - # path: # optional, default is . - # Report only issues of a given severity level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) - # level: # optional, default is UNDEFINED - # Report only issues of a given confidence level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) - # confidence: # optional, default is UNDEFINED - # comma-separated list of paths (glob patterns supported) to exclude from scan (note that these are in addition to the excluded paths provided in the config file) (default: .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg) - # excluded_paths: # optional, default is DEFAULT - # comma-separated list of test IDs to skip - # skips: # optional, default is DEFAULT - # path to a .bandit file that supplies command line arguments - # ini_path: # optional, default is DEFAULT - - CodeQL: - name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: python - build-mode: none - # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" - - Codacy-Security-Scan: - permissions: - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - name: Codacy Security Scan - runs-on: ubuntu-latest - steps: - # Checkout the repository to the GitHub Actions runner - - name: Checkout code - uses: actions/checkout@v4 - - # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis - - name: Run Codacy Analysis CLI - uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b - with: - # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository - # You can also omit the token and run the tools that support default configurations - project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} - verbose: true - output: results.sarif - format: sarif - # Adjust severity of non-security issues - gh-code-scanning-compat: true - # Force 0 exit code to allow SARIF file generation - # This will handover control about PR rejection to the GitHub side - max-allowed-issues: 2147483647 - - # Upload the SARIF file generated in the previous step - - name: Upload SARIF results file - uses: github/codeql-action/upload-sarif@v2 - with: +name: Code Analysis + +on: + push: + branches: [ "*" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "*" ] + schedule: + - cron: '33 2 * * 5' + +jobs: + PyLint: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.11"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install Application Dependencies + run: | + pip install -r requirements.txt + - name: Install dependencies + run: | + pip install pylint + - name: Analysing the code with pylint + run: | + pylint $(git ls-files '*.py') + + Bandit: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Bandit Scan + uses: shundor/python-bandit-scan@9cc5aa4a006482b8a7f91134412df6772dbda22c + with: # optional arguments + # exit with 0, even with results found + exit_zero: true # optional, default is DEFAULT + # Github token of the repository (automatically created by Github) + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information. + # File or directory to run bandit on + # path: # optional, default is . + # Report only issues of a given severity level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) + # level: # optional, default is UNDEFINED + # Report only issues of a given confidence level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) + # confidence: # optional, default is UNDEFINED + # comma-separated list of paths (glob patterns supported) to exclude from scan (note that these are in addition to the excluded paths provided in the config file) (default: .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg) + # excluded_paths: # optional, default is DEFAULT + # comma-separated list of test IDs to skip + # skips: # optional, default is DEFAULT + # path to a .bandit file that supplies command line arguments + # ini_path: # optional, default is DEFAULT + + CodeQL: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" + + Codacy-Security-Scan: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + name: Codacy Security Scan + runs-on: ubuntu-latest + steps: + # Checkout the repository to the GitHub Actions runner + - name: Checkout code + uses: actions/checkout@v4 + + # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis + - name: Run Codacy Analysis CLI + uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b + with: + # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository + # You can also omit the token and run the tools that support default configurations + project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} + verbose: true + output: results.sarif + format: sarif + # Adjust severity of non-security issues + gh-code-scanning-compat: true + # Force 0 exit code to allow SARIF file generation + # This will handover control about PR rejection to the GitHub side + max-allowed-issues: 2147483647 + + # Upload the SARIF file generated in the previous step + - name: Upload SARIF results file + uses: github/codeql-action/upload-sarif@v2 + with: sarif_file: results.sarif \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c030c3..d575715 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,28 @@ -/.env -/config.json -/runtime.log -/user_agents.json -/__pycache__ -modules/__pycache__ -git_message_rules -file_links.txt -/dist -developer_accounts.json -outdated -art/Icon.ai -art/site_banners.ai -file_links_formatted.txt -config_old.json -run.bat -build -Mul-Tor.spec -Build Releases.bat -presets/readme.txt -possible_sites.txt -preset_sorter.py -preset_sorter.json -.DEBUG -/test_files +/.env +/config.json +/runtime.log +/user_agents.json +/__pycache__ +modules/__pycache__ +git_message_rules +file_links.txt +/dist +developer_accounts.json +outdated +art/Icon.ai +art/site_banners.ai +file_links_formatted.txt +config_old.json +run.bat +build +Mul-Tor.spec +Build Releases.bat +presets/readme.txt +possible_sites.txt +preset_sorter.py +preset_sorter.json +.DEBUG +/test_files +*.zstd +/modules/old_scripts/ +/modules/deprecated/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 0c2aacc..4045906 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,16 +1,24 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}\\main.py", - "console": "integratedTerminal", - "justMyCode": true - } - ] +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Main File", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}\\main.py", + "console": "integratedTerminal", + "justMyCode": true + }, + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + } + ] } \ No newline at end of file diff --git a/Build Releases.bat b/Build Releases.bat deleted file mode 100644 index 7106db7..0000000 --- a/Build Releases.bat +++ /dev/null @@ -1 +0,0 @@ -conda activate ".\.env" && pyinstaller --hidden-import "plyer.platforms.win.filechooser" --onefile --icon "icon.ico" --console --name "Mul-Tor" --upx-dir "Z:\Projects\Python\### UPX ###" --add-data="Z:\Projects\Python\mul-tor\.env\Lib\site-packages\grapheme\data\*;grapheme/data/" main.py \ No newline at end of file diff --git a/LICENSE b/LICENSE index a612ad9..76a17d7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,373 +1,373 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/README.md b/README.md index ae7c9db..27752b9 100644 --- a/README.md +++ b/README.md @@ -1,325 +1,325 @@ -# Mul-Tor -## Your tool for easy file uploading and sharing. - -#### As mentioned above the goal of this tool is to help people upload files fast to multiple hosters while also helping in the process of sharing these links. - -
- -### Preview - -![preview](https://github.com/Official-Husko/mul-tor/blob/master/media/preview.gif) - -
- -[**Download it here**](https://github.com/Official-Husko/mul-tor/releases/latest) - -
- -### Features: - -* Proxies -* Random User Agent -* Check Website Availability -* Progress Bar -* Auto Updater -* Site Presets -* Over 35+ Sites Supported - -
- -### Currently supported sites: -Site | API | API Key Required | Max File Size ---- | --- | --- | --- -[Gofile][7] | [Yes][8] | No | ∞ -[Pixeldrain][1] | [Yes][2] | No | 20 GB -[BowFile][17] | [Yes][18] | [Yes][19] | 5 GB -[Doodrive][36] | [Yes][37] | [Yes][38] | 5 GB -[Download.gg][102] | No | No | 25 GB -[Filebin][92] | No | No | ∞ -[Delafil][107] | No | No | 6 GB -[Files.dp.ua][108] | No | No | 100 GB -[Files.fm][45] | No | No | 5 GB -[Krakenfiles][124] | No | No | 1 GB -[Transfer_sh.sh][98] | No | No | ∞ -[/tmp/files][117] | [Yes][118] | No | 100 MB -[Mixdrop][29] | [Yes][30] | [Yes][30] | ∞ -[1Fichier][31] | [Yes][32] | No | 300 GB -[Oshi][9] | No | No | 5 GB -[File.io][70] | No | No | 2 GB -[EasyUpload][72] | No | No | 10 GB -[AnonTransfer][127] | No | No | 5 GB -[Anonymfile][134] | [Yes][135] | No | 7 GB -[File.si][145] | [Yes][146] | No | 7 GB -[1CloudFile][133] | No | No | 5 GB -[ClicknUpload][160] | No | No | 2 GB -[FileUpload][161] | No | No | 5 GB -[HexUpload][21] | No | No | 2 GB -[UserCloud][161] | No | No | 5 GB -[UFile][68] | [Yes][69] | No | 5 GB -[Catbox][168] | [Yes][169] | No | 200 MB -[LitterBox][170] | [Yes][171] | No | 1 GB -[Keep.sh][172] | No | No | 500 MB -[TempSend][173] | No | No | 2 GB -[UsersDrive][100] | No | No | 2 GB -[Rapidgator][174] | [Yes][174] | [Yes][175] | ? -[WDHO][180] | No | No | 5 GB -[Filesadmin][181] | No | No | 3 GB -[CyberFile][182] | No | No | 10 GB -[Buzzheavier][183] | [Yes][184] | No | ∞ - -
- -### Planned Sites: -Site | API | API Key Required | Max File Size ---- | --- | --- | --- -None Currently :) - -
- -### Rejected Sites: -
- - Site | API | API Key Required | Max File Size | Reason - --- | --- | --- | --- | --- - [DropMeFiles][106] | No | No | 50 GB | Terrible Uploading System - [Up2Share][120] | No | No | 1 GB | Terrible Uploading System - [WeTransfer][121] | No | No | 2 GB | When do the terrible uploading systems end? - [Filemail][42] | [Yes][43] | [No/Yes*²][44] | 5 GB | Garbage Limit of 2 Uploads a Day (Sucks regarding coding and testing) - [MEGA][109] | [Yes][110] | No | 20 GB | Uses complicated Encrypting & Decrypting - [Google Drive][111] | [Yes][112] | No | 15 GB | I see no reason to add this - [Mediafire][113] | [Yes][114] | No | 10 GB | I see no reason to add this - [UploadHaven][115] | No | No | 50 GB | Paid/Invite Only - [Terminal][116] | No | No | ? | Invite Only - [UpToBox][33] | [Yes][34] | [Yes][35] | 200 GB | Raided by the Feds/ACE & Down - [SendGB][119] | No | No | 5 GB | [Discussion 10](https://github.com/Official-Husko/mul-tor/discussions/10) - [WorkUpload][122] | No | No | 2 GB | Gives a 200 response with a link but the file is not available. - [Qiwi.gg][126] | No | No | ? | Really Complicated system - [CyberFiles][128] | No | No | 19 GB | sometimes throws account missing errors and sometimes it uploads fine - [SendSpace][130] | No | No | 300 MB | SSL issues and terrible upload system - [BeeFiles][144] | No | No | 20 GB | Requires a Phone Number and shows "no plans available" after registering. Possibly a scam - [SwissTransfer][147] | No | No | 20 GB | Captchas Required & could possibly leak the IP of the uploader - [UploadBuzz][148] | No | No | ? | Website is down - [pCloud][149] | [Yes][150] | No | 10 GB | Paid - [Wormhole][151] | No | No | 10 GB | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) - [SendVis][152] | No | No | 2.5 GB | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) - [Instant.io][153] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) - [SendTresorit][154] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) - [Sharrr][155] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) - [SendZcyph][129] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) - [TransferXL][156] | No | No | 5 GB | Captchas Required - [WeSendIt][157] | No | No | 2 GB | Can't figure out the upload system - [Yandex Disk][158] | No | No | 5 GB | I see no reason to add this - [Archive.org][159] | No | No | ∞ | I see no reason to add this - [TransferNow][163] | No | No | 5 GB | Not worth the hassle - [Bunkrr][178] | [Yes][179] | [Yes][179] | 2GB | [Discussion 13](https://github.com/Official-Husko/mul-tor/discussions/13) - -
- -
- -### FAQ -
- Open FAQ - Q: Where did the site X go? - - A: Check the [Deprecated Sites][164] list. - - Q: Are there any presets?\ - A: Yes, simply check [this folder](https://github.com/Official-Husko/mul-tor/tree/master/presets) here and download the ones you wish to use. - - Q: Can I make my own presets?\ - A: Yes you can, for that read [this wiki page](https://github.com/Official-Husko/mul-tor/wiki/Preset-Configuration). - - Q: How can I get help?\ - A: Check the [Wiki][166] for any information that might help you. If you can't find the answer there check out the [issues page][4] and if there is none [open one up][167]. - - Q: How do I get the API key?\ - A: Click on the blue yes in the Api Key Required row for the site you wish to get a key for. - - Q: I want to request a site.\ - A: Please first check the [rejected sites][3] and [issues page][4] to ensure it hasn't been previously mentioned. If not, feel free to [open a new issue][167]. - - Q: What about rejected sites?\ - A: I will check the sites every once in a while to see if the issues I mentioned have been resolved. If you know the issue has been resolved or why I encountered an issue feel free to [open a new issue][167]. - - Q: Why is it called Mul-Tor?\ - A: I have no idea. - - Q: What if I need one of the rejected sites?\ - A: This project is open to contributions. Maybe somebody else can add it. You may [open a new issue][167] if there isn't one already so that I can check it again. - - Q: Certain sites offer an API but you didn't use it. Why?\ - A: Because this makes it easier for users and it doesn't need any accounts and sign-ups. I plan to add API functions to these for users who want to use it. - - Q: Somebody else already has the issue I'm having. What do I do?\ - A: Simply upvote the issue. If you have additional data you think could help me solve said issue feel free to comment it. -
- -
- -### Contributors -[**kianmeng**](https://github.com/kianmeng), -[**SillyBilly0069**](https://github.com/SillyBilly0069) - -
- -[comment]: # (Below are all links to the sites) -[0]: # -[1]: https://pixeldrain.com/ -[2]: https://pixeldrain.com/api -[3]: https://github.com/Official-Husko/mul-tor#rejected-sites -[4]: https://github.com/Official-Husko/mul-tor/issues -[7]: https://gofile.io/ -[8]: https://gofile.io/api -[9]: https://oshi.at/ -[17]: https://bowfile.com/ -[18]: https://bowfile.com/api -[19]: https://bowfile.com/account/edit#api -[20]: https://1cloudfile.com/ -[21]: https://1cloudfile.com/api -[22]: https://1cloudfile.com/account/edit#api -[23]: https://hexupload.net/ -[24]: https://hexupload.docs.apiary.io/# -[25]: https://hexupload.net/?op=my_account -[26]: https://sendspace.com/ -[27]: https://sendspace.com/dev_method.html -[28]: https://sendspace.com/dev_apikeys.html -[29]: https://Mixdrop.ag/ -[30]: https://Mixdrop.ag/api/ -[31]: https://1fichier.com/ -[32]: https://1fichier.com/api.html -[33]: https://uptobox.com/ -[34]: https://docs.uptobox.com/ -[35]: https://uptobox.com/my_account -[36]: https://doodrive.com/ -[37]: https://doodrive.com/dashboard/api -[38]: https://doodrive.com/dashboard/settings#settings_api -[39]: https://transfernow.net/ -[40]: https://developers.transfernow.net/ -[41]: https://transfernow.net/dashboard/admin/api -[42]: https://filemail.com/ -[43]: https://filemail.com/apidoc -[44]: https://filemail.com/apidoc/ApiKey.aspx -[45]: https://files.fm/ -[46]: https://files.fm/api.php -[67]: https://fastupload.io/ -[68]: https://ufile.io/ -[69]: https://ufile.io/blog/?filter=api -[70]: https://file.io/ -[72]: https://easyupload.io/ -[73]: https://filepost.io/ -[74]: https://file-upload.net/ -[75]: https://transferxl.com/ -[76]: https://filetransfer.io/ -[77]: https://transfernow.net/ -[78]: https://quicklyupload.com/ -[79]: https://tmpfiles.org/ -[80]: https://send.vis.ee/ -[81]: https://wormhole.app/ -[82]: https://swisstransfer.com/en-us -[83]: https://4shared.com/ -[84]: https://instant.io/ -[85]: https://send.tresorit.com/ -[86]: https://sharrr.com/ -[87]: https://blackhole.run/ -[88]: https://filedropper.com/ -[89]: https://myairbridge.com/en/#!/settings -[90]: https://sendgb.com/ -[91]: https://ulozto.net/ -[92]: https://filebin.net/ -[93]: https://send.cm/ -[94]: https://filewhopper.com/ -[95]: https://transferfile.io/#/ -[96]: https://hotdropp.com/#/ -[97]: https://cyberdrop.me/ -[98]: https://transfer.sh/ -[99]: https://k2s.cc/ -[100]: https://usersdrive.com/ -[101]: https://1fichier.com/ -[102]: https://download.gg/ -[103]: https://torrentfreak.com/file-hosting-icon-anonfiles-throws-in-the-towel-domain-for-sale-230817/ -[104]: https://anonfiles.me/ -[105]: https://anonfiles.me/docs/api -[106]: https://dropmefiles.com/ -[107]: https://delafil.se/ -[108]: https://files.dp.ua/ -[109]: https://mega.nz/ -[110]: https://mega.io/developers -[111]: https://google.com/drive/ -[112]: https://developers.google.com/drive/api/guides/about-sdk -[113]: https://mediafire.com/ -[114]: https://mediafire.com/developers/core_api/1.5/getting_started/ -[115]: https://uploadhaven.com/ -[116]: https://terminal.lc/ -[117]: https://tmpfiles.org/ -[118]: https://tmpfiles.org/api -[119]: https://sendgb.com/ -[120]: https://up2sha.re/ -[121]: https://wetransfer.com/ -[122]: https://workupload.com/ -[123]: http://yourfilestore.com/ -[124]: https://krakenfiles.com/ -[126]: https://qiwi.gg/ -[127]: https://anontransfer.com/ -[128]: https://cyberfile.me/ -[129]: https://send.zcyph.cc/ -[130]: https://sendspace.com/ -[131]: https://anonfiles.me/ -[132]: https://anonfiles.me/docs/api -[133]: https://1cloudfile.com/ -[134]: https://anonymfile.com/ -[135]: https://anonymfile.com/docs/api -[136]: https://nitrofile.cc/ -[137]: https://nitrofile.cc/docs/api -[138]: https://gofile.cc/ -[139]: https://gofile.cc/docs/api -[140]: https://anyfile.co/ -[141]: https://anyfile.co/docs/api -[142]: https://bayfiles.io/ -[143]: https://bayfiles.io/docs/api -[144]: https://beefiles.io/ -[145]: https://file.si/ -[146]: https://file.si/docs/api -[147]: https://swisstransfer.com/ -[148]: https://uploadbuzz.cc/ -[149]: https://pcloud.com/ -[150]: https://docs.pcloud.com/ -[151]: https://wormhole.app/ -[152]: https://send.vis.ee/ -[153]: https://instant.io/ -[154]: https://send.tresorit.com/ -[155]: https://sharrr.com/ -[156]: https://transferxl.com/ -[157]: https://wesendit.com/ -[158]: https://Yandex.Disk/ -[159]: https://archive.org/ -[160]: https://clicknupload.click -[161]: https://file-upload.net/ -[162]: https://usercloud.com/ -[163]: https://transfernow.net/ -[164]: https://github.com/Official-Husko/mul-tor/blob/master/modules/deprecated/README.md -[165]: https://udrop.com/ -[166]: https://github.com/Official-Husko/mul-tor/wiki -[167]: https://github.com/Official-Husko/mul-tor/issues/new/choose -[168]: https://catbox.moe/ -[169]: https://catbox.moe/tools.php -[170]: https://litterbox.catbox.moe/ -[171]: https://litterbox.catbox.moe/tools.php -[172]: https://keep.sh/ -[173]: https://tempsend.com/ -[174]: https://rapidgator.net/ -[175]: https://rapidgator.net/article/api/ -[176]: https://filestore.me/ -[177]: https://filestore.me/account/ -[178]: https://app.bunkrr.su/ -[179]: https://app.bunkrr.su/dashboard -[180]: https://wdho.ru/ -[181]: https://filesadmin.com/ -[182]: https://cyberfile.me/ -[183]: https://buzzheavier.com/ -[184]: https://buzzheavier.com/api.html - -
- -#### Disclaimer +# Mul-Tor +## Your tool for easy file uploading and sharing. + +#### As mentioned above the goal of this tool is to help people upload files fast to multiple hosters while also helping in the process of sharing these links. + +
+ +### Preview + +![preview](https://github.com/Official-Husko/mul-tor/blob/master/media/preview.gif) + +
+ +[**Download it here**](https://github.com/Official-Husko/mul-tor/releases/latest) + +
+ +### Features: + +* Proxies +* Random User Agent +* Check Website Availability +* Progress Bar +* Auto Updater +* Site Presets +* Over 35+ Sites Supported + +
+ +### Currently supported sites: +Site | API | API Key Required | Max File Size +--- | --- | --- | --- +[Gofile][7] | [Yes][8] | No | ∞ +[Pixeldrain][1] | [Yes][2] | No | 20 GB +[BowFile][17] | [Yes][18] | [Yes][19] | 5 GB +[Doodrive][36] | [Yes][37] | [Yes][38] | 5 GB +[Download.gg][102] | No | No | 25 GB +[Filebin][92] | No | No | ∞ +[Delafil][107] | No | No | 6 GB +[Files.dp.ua][108] | No | No | 100 GB +[Files.fm][45] | No | No | 5 GB +[Krakenfiles][124] | No | No | 1 GB +[Transfer_sh.sh][98] | No | No | ∞ +[/tmp/files][117] | [Yes][118] | No | 100 MB +[Mixdrop][29] | [Yes][30] | [Yes][30] | ∞ +[1Fichier][31] | [Yes][32] | No | 300 GB +[Oshi][9] | No | No | 5 GB +[File.io][70] | No | No | 2 GB +[EasyUpload][72] | No | No | 10 GB +[AnonTransfer][127] | No | No | 5 GB +[Anonymfile][134] | [Yes][135] | No | 7 GB +[File.si][145] | [Yes][146] | No | 7 GB +[1CloudFile][133] | No | No | 5 GB +[ClicknUpload][160] | No | No | 2 GB +[FileUpload][161] | No | No | 5 GB +[HexUpload][21] | No | No | 2 GB +[UserCloud][161] | No | No | 5 GB +[UFile][68] | [Yes][69] | No | 5 GB +[Catbox][168] | [Yes][169] | No | 200 MB +[LitterBox][170] | [Yes][171] | No | 1 GB +[Keep.sh][172] | No | No | 500 MB +[TempSend][173] | No | No | 2 GB +[UsersDrive][100] | No | No | 2 GB +[Rapidgator][174] | [Yes][174] | [Yes][175] | ? +[WDHO][180] | No | No | 5 GB +[Filesadmin][181] | No | No | 3 GB +[CyberFile][182] | No | No | 10 GB +[Buzzheavier][183] | [Yes][184] | No | ∞ + +
+ +### Planned Sites: +Site | API | API Key Required | Max File Size +--- | --- | --- | --- +None Currently :) + +
+ +### Rejected Sites: +
+ + Site | API | API Key Required | Max File Size | Reason + --- | --- | --- | --- | --- + [DropMeFiles][106] | No | No | 50 GB | Terrible Uploading System + [Up2Share][120] | No | No | 1 GB | Terrible Uploading System + [WeTransfer][121] | No | No | 2 GB | When do the terrible uploading systems end? + [Filemail][42] | [Yes][43] | [No/Yes*²][44] | 5 GB | Garbage Limit of 2 Uploads a Day (Sucks regarding coding and testing) + [MEGA][109] | [Yes][110] | No | 20 GB | Uses complicated Encrypting & Decrypting + [Google Drive][111] | [Yes][112] | No | 15 GB | I see no reason to add this + [Mediafire][113] | [Yes][114] | No | 10 GB | I see no reason to add this + [UploadHaven][115] | No | No | 50 GB | Paid/Invite Only + [Terminal][116] | No | No | ? | Invite Only + [UpToBox][33] | [Yes][34] | [Yes][35] | 200 GB | Raided by the Feds/ACE & Down + [SendGB][119] | No | No | 5 GB | [Discussion 10](https://github.com/Official-Husko/mul-tor/discussions/10) + [WorkUpload][122] | No | No | 2 GB | Gives a 200 response with a link but the file is not available. + [Qiwi.gg][126] | No | No | ? | Really Complicated system + [CyberFiles][128] | No | No | 19 GB | sometimes throws account missing errors and sometimes it uploads fine + [SendSpace][130] | No | No | 300 MB | SSL issues and terrible upload system + [BeeFiles][144] | No | No | 20 GB | Requires a Phone Number and shows "no plans available" after registering. Possibly a scam + [SwissTransfer][147] | No | No | 20 GB | Captchas Required & could possibly leak the IP of the uploader + [UploadBuzz][148] | No | No | ? | Website is down + [pCloud][149] | [Yes][150] | No | 10 GB | Paid + [Wormhole][151] | No | No | 10 GB | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) + [SendVis][152] | No | No | 2.5 GB | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) + [Instant.io][153] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) + [SendTresorit][154] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) + [Sharrr][155] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) + [SendZcyph][129] | No | No | ? | [Discussion 12](https://github.com/Official-Husko/mul-tor/discussions/12) + [TransferXL][156] | No | No | 5 GB | Captchas Required + [WeSendIt][157] | No | No | 2 GB | Can't figure out the upload system + [Yandex Disk][158] | No | No | 5 GB | I see no reason to add this + [Archive.org][159] | No | No | ∞ | I see no reason to add this + [TransferNow][163] | No | No | 5 GB | Not worth the hassle + [Bunkrr][178] | [Yes][179] | [Yes][179] | 2GB | [Discussion 13](https://github.com/Official-Husko/mul-tor/discussions/13) + +
+ +
+ +### FAQ +
+ Open FAQ + Q: Where did the site X go? + + A: Check the [Deprecated Sites][164] list. + + Q: Are there any presets?\ + A: Yes, simply check [this folder](https://github.com/Official-Husko/mul-tor/tree/master/presets) here and download the ones you wish to use. + + Q: Can I make my own presets?\ + A: Yes you can, for that read [this wiki page](https://github.com/Official-Husko/mul-tor/wiki/Preset-Configuration). + + Q: How can I get help?\ + A: Check the [Wiki][166] for any information that might help you. If you can't find the answer there check out the [issues page][4] and if there is none [open one up][167]. + + Q: How do I get the API key?\ + A: Click on the blue yes in the Api Key Required row for the site you wish to get a key for. + + Q: I want to request a site.\ + A: Please first check the [rejected sites][3] and [issues page][4] to ensure it hasn't been previously mentioned. If not, feel free to [open a new issue][167]. + + Q: What about rejected sites?\ + A: I will check the sites every once in a while to see if the issues I mentioned have been resolved. If you know the issue has been resolved or why I encountered an issue feel free to [open a new issue][167]. + + Q: Why is it called Mul-Tor?\ + A: I have no idea. + + Q: What if I need one of the rejected sites?\ + A: This project is open to contributions. Maybe somebody else can add it. You may [open a new issue][167] if there isn't one already so that I can check it again. + + Q: Certain sites offer an API but you didn't use it. Why?\ + A: Because this makes it easier for users and it doesn't need any accounts and sign-ups. I plan to add API functions to these for users who want to use it. + + Q: Somebody else already has the issue I'm having. What do I do?\ + A: Simply upvote the issue. If you have additional data you think could help me solve said issue feel free to comment it. +
+ +
+ +### Contributors +[**kianmeng**](https://github.com/kianmeng), +[**SillyBilly0069**](https://github.com/SillyBilly0069) + +
+ +[comment]: # (Below are all links to the sites) +[0]: # +[1]: https://pixeldrain.com/ +[2]: https://pixeldrain.com/api +[3]: https://github.com/Official-Husko/mul-tor#rejected-sites +[4]: https://github.com/Official-Husko/mul-tor/issues +[7]: https://gofile.io/ +[8]: https://gofile.io/api +[9]: https://oshi.at/ +[17]: https://bowfile.com/ +[18]: https://bowfile.com/api +[19]: https://bowfile.com/account/edit#api +[20]: https://1cloudfile.com/ +[21]: https://1cloudfile.com/api +[22]: https://1cloudfile.com/account/edit#api +[23]: https://hexupload.net/ +[24]: https://hexupload.docs.apiary.io/# +[25]: https://hexupload.net/?op=my_account +[26]: https://sendspace.com/ +[27]: https://sendspace.com/dev_method.html +[28]: https://sendspace.com/dev_apikeys.html +[29]: https://Mixdrop.ag/ +[30]: https://Mixdrop.ag/api/ +[31]: https://1fichier.com/ +[32]: https://1fichier.com/api.html +[33]: https://uptobox.com/ +[34]: https://docs.uptobox.com/ +[35]: https://uptobox.com/my_account +[36]: https://doodrive.com/ +[37]: https://doodrive.com/dashboard/api +[38]: https://doodrive.com/dashboard/settings#settings_api +[39]: https://transfernow.net/ +[40]: https://developers.transfernow.net/ +[41]: https://transfernow.net/dashboard/admin/api +[42]: https://filemail.com/ +[43]: https://filemail.com/apidoc +[44]: https://filemail.com/apidoc/ApiKey.aspx +[45]: https://files.fm/ +[46]: https://files.fm/api.php +[67]: https://fastupload.io/ +[68]: https://ufile.io/ +[69]: https://ufile.io/blog/?filter=api +[70]: https://file.io/ +[72]: https://easyupload.io/ +[73]: https://filepost.io/ +[74]: https://file-upload.net/ +[75]: https://transferxl.com/ +[76]: https://filetransfer.io/ +[77]: https://transfernow.net/ +[78]: https://quicklyupload.com/ +[79]: https://tmpfiles.org/ +[80]: https://send.vis.ee/ +[81]: https://wormhole.app/ +[82]: https://swisstransfer.com/en-us +[83]: https://4shared.com/ +[84]: https://instant.io/ +[85]: https://send.tresorit.com/ +[86]: https://sharrr.com/ +[87]: https://blackhole.run/ +[88]: https://filedropper.com/ +[89]: https://myairbridge.com/en/#!/settings +[90]: https://sendgb.com/ +[91]: https://ulozto.net/ +[92]: https://filebin.net/ +[93]: https://send.cm/ +[94]: https://filewhopper.com/ +[95]: https://transferfile.io/#/ +[96]: https://hotdropp.com/#/ +[97]: https://cyberdrop.me/ +[98]: https://transfer.sh/ +[99]: https://k2s.cc/ +[100]: https://usersdrive.com/ +[101]: https://1fichier.com/ +[102]: https://download.gg/ +[103]: https://torrentfreak.com/file-hosting-icon-anonfiles-throws-in-the-towel-domain-for-sale-230817/ +[104]: https://anonfiles.me/ +[105]: https://anonfiles.me/docs/api +[106]: https://dropmefiles.com/ +[107]: https://delafil.se/ +[108]: https://files.dp.ua/ +[109]: https://mega.nz/ +[110]: https://mega.io/developers +[111]: https://google.com/drive/ +[112]: https://developers.google.com/drive/api/guides/about-sdk +[113]: https://mediafire.com/ +[114]: https://mediafire.com/developers/core_api/1.5/getting_started/ +[115]: https://uploadhaven.com/ +[116]: https://terminal.lc/ +[117]: https://tmpfiles.org/ +[118]: https://tmpfiles.org/api +[119]: https://sendgb.com/ +[120]: https://up2sha.re/ +[121]: https://wetransfer.com/ +[122]: https://workupload.com/ +[123]: http://yourfilestore.com/ +[124]: https://krakenfiles.com/ +[126]: https://qiwi.gg/ +[127]: https://anontransfer.com/ +[128]: https://cyberfile.me/ +[129]: https://send.zcyph.cc/ +[130]: https://sendspace.com/ +[131]: https://anonfiles.me/ +[132]: https://anonfiles.me/docs/api +[133]: https://1cloudfile.com/ +[134]: https://anonymfile.com/ +[135]: https://anonymfile.com/docs/api +[136]: https://nitrofile.cc/ +[137]: https://nitrofile.cc/docs/api +[138]: https://gofile.cc/ +[139]: https://gofile.cc/docs/api +[140]: https://anyfile.co/ +[141]: https://anyfile.co/docs/api +[142]: https://bayfiles.io/ +[143]: https://bayfiles.io/docs/api +[144]: https://beefiles.io/ +[145]: https://file.si/ +[146]: https://file.si/docs/api +[147]: https://swisstransfer.com/ +[148]: https://uploadbuzz.cc/ +[149]: https://pcloud.com/ +[150]: https://docs.pcloud.com/ +[151]: https://wormhole.app/ +[152]: https://send.vis.ee/ +[153]: https://instant.io/ +[154]: https://send.tresorit.com/ +[155]: https://sharrr.com/ +[156]: https://transferxl.com/ +[157]: https://wesendit.com/ +[158]: https://Yandex.Disk/ +[159]: https://archive.org/ +[160]: https://clicknupload.click +[161]: https://file-upload.net/ +[162]: https://usercloud.com/ +[163]: https://transfernow.net/ +[164]: https://github.com/Official-Husko/mul-tor/blob/master/modules/deprecated/README.md +[165]: https://udrop.com/ +[166]: https://github.com/Official-Husko/mul-tor/wiki +[167]: https://github.com/Official-Husko/mul-tor/issues/new/choose +[168]: https://catbox.moe/ +[169]: https://catbox.moe/tools.php +[170]: https://litterbox.catbox.moe/ +[171]: https://litterbox.catbox.moe/tools.php +[172]: https://keep.sh/ +[173]: https://tempsend.com/ +[174]: https://rapidgator.net/ +[175]: https://rapidgator.net/article/api/ +[176]: https://filestore.me/ +[177]: https://filestore.me/account/ +[178]: https://app.bunkrr.su/ +[179]: https://app.bunkrr.su/dashboard +[180]: https://wdho.ru/ +[181]: https://filesadmin.com/ +[182]: https://cyberfile.me/ +[183]: https://buzzheavier.com/ +[184]: https://buzzheavier.com/api.html + +
+ +#### Disclaimer *I am not in any way affiliated with or working with these sites. ***This is an unofficial project***. I am not responsible and or liable for the content that is uploaded with this tool.* \ No newline at end of file diff --git a/enable_env.bat b/enable_env.bat deleted file mode 100644 index 898e15a..0000000 --- a/enable_env.bat +++ /dev/null @@ -1 +0,0 @@ -conda activate ".\.env" \ No newline at end of file diff --git a/main.py b/main.py index fdef922..56cde8a 100644 --- a/main.py +++ b/main.py @@ -1,13 +1,241 @@ -from time import sleep - -if __name__ == '__main__': - try: - startup = Main.startup() - while True: - Main.selection(config=startup[0], available=startup[1], user_agents_list=startup[3], proxy_list=startup[2]) - print("") - print("") - except KeyboardInterrupt: - print("User Cancelled") - sleep(3) - exit(0) +# Import Standard Libraries +from time import sleep +import os +import sys +from datetime import datetime + +# Import Third-Party Libraries +import inquirer +from termcolor import colored +import plyer +from alive_progress import alive_bar + +# Import Local Libraries +from modules.config_manager import ConfigManager +from modules.auto_update import AutoUpdate +from modules.proxy_scraper import ProxyScraper +from modules.logger import Logger +from modules.pretty_print import PrettyPrint +from modules.availability_checker import AvailabilityChecker +from modules.storage import __dev_debug__ as DEBUG +from modules.storage import __user_agent__ as USER_AGENT +from modules.storage import __version__ as VERSION + + +class Main: + + def __init__(self): + self.owd = os.getcwd() + self.platform = sys.platform + self.config = None + self.current_working_directory: str = os.getcwd() + + self.logo = f""" + {colored(f''' + .88b d88. db db db d888888b .d88b. d8888b. + 88'YbdP`88 88 88 88 `~~88~~' .8P Y8. 88 `8D + 88 88 88 88 88 88 88 88 88 88oobY' + 88 88 88 88 88 88 C8888D 88 88 88 88`8b + 88 88 88 88b d88 88booo. 88 `8b d8' 88 `88. + YP YP YP ~Y8888P' Y88888P YP `Y88P' 88 YD + {colored(f"v{VERSION}", "cyan")} | by {colored("Official-Husko", "yellow")}''', "red")} + """ + + def _check_read_write_permissions(self) -> bool: + return os.access(self.current_working_directory, os.W_OK) and os.access(self.current_working_directory, os.R_OK) + + def _file_selection(self) -> list: + amount_question = [ + inquirer.List('selection', + message=colored("What file/s do you want to upload?", "green"), + choices=["Single", "Multiple"], + ), + ] + amount_answers = inquirer.prompt(amount_question) + print("") + sites = amount_answers.get("selection") + + + files_list = [] + while len(files_list) == 0 or files_list == [[]]: + files_list = [] # Reset it + if amount_answers.get("selection") == "Single": + files_list = plyer.filechooser.open_file() + elif amount_answers.get("selection") == "Multiple": + fn = plyer.filechooser.choose_dir() + fn = fn[0] + files_in_folder = os.listdir(fn) + for found_file in files_in_folder: + if os.path.isdir(f"{fn}\\{found_file}") != True: + files_list.append(f"{fn}\\{found_file}") + else: + print(colored("Something fucked up! Please report this on github. Selection_Error", "red")) + sleep(5) + + def _preset_selection(self): + pass + + def _config_handler(self): + pass + + def _proxy_handler(self): + pass + + def _check_available_sites(self): + pass + + def _upload_handler(self): + with alive_bar(len(files_list), calibrate=1, dual_line=True, title='Uploading', enrich_print=False, stats=False, receipt=False, receipt_text=False) as list_bar: + for file in files_list: + for site in sites: + bar_file_name = os.path.basename(file) + list_bar.title = f'-> Uploading {colored(bar_file_name, "light_blue")} to {colored(site, "yellow")}, please wait...' + output = { + "status": "", + "file_name": "", + "file_url": "", + "exception": "", + "size_limit": "", + "extra": "" + } + + uploader_classes = { + "Buzzheavier": Buzzheavier + } + + if site in uploader_classes: + api_key = config.get("api_keys", {}).get(site, None) if sites_data_dict.get(site, "").get("apiKey") == True else None + + site_instance = uploader_classes.get(site, "No_Site")(file, proxy_list, user_agents_list, api_key) + output = site_instance.Uploader() + + + print(output) + + # output = uploader_classes.get(site, "No_Site").Uploader(file, proxy_list, user_agents_list, api_key) + + status = output.get("status", "404 status not found") + file_name = output.get("file_name", "oopsie_daisie.fish") + file_url = output.get("file_url", "url be doing the hidy hole") + exception_str = output.get("exception", "Fuck me there was no exception.") + size_limit = output.get("size_limit", "-3 GB") + extra = output.get("extra", "Monkey stole the bananas") + + os.chdir(owd) + if status == "ok": + print(f"{ok} {colored(file_name, 'light_blue')} {colored('successfully uploaded to', 'green')} {colored(site, 'yellow')}{colored('! URL:', 'green')} {colored(file_url, 'light_blue')}") + with open("file_links.txt", "a") as file_links: + file_links.writelines(f"{datetime.now()} | {site} | {file_name} - {file_url}\n") + file_links.close() + if auto_load_preset == True and link_format != "" and DEBUG == False: + with open("file_links_formatted.txt", "a") as formatted_links_file: + formatted_links_file.writelines(f"{link_format.format(status=status, file_name=file_name, file_url=file_url, site_name=site, date_and_time=datetime.now())}\n") + formatted_links_file.close() + else: + touch_grass = False + feel_woman_touch = False + pass + + list_bar() + os.chdir(owd) # reset to default working dir + + def runner(self): + if self.platform == "win32": + os.system("cls") + print(self.logo) + + if DEBUG: + print(f"{colored('Platform:', 'green')} {self.platform}") + print("") + + # Run config system + config_instance = ConfigManager + + proxies_enabled = config.get("useProxies", False) + check_for_updates_enabled = config.get("checkForUpdates", True) + + if check_for_updates_enabled: + os.system("cls") + print(self.logo) + print("") + print(colored("Checking for Updates...", "yellow"), end='\r') + AutoUpdate.Checker() + os.system("cls") + print(self.logo) + print("") + + # Check if the user wants to use proxies and get them + if proxies_enabled: + print(colored("Fetching Fresh Proxies...", "yellow"), end='\r') + proxy_list = ProxyScraper.Scraper() + print(f"{colored('Fetched', 'green')} {colored(len(proxy_list), 'yellow')} {colored('Proxies. ', 'green')}") + print("") + else: + proxy_list = [] + + available = AvailabilityChecker.Evaluate(config, proxy_list) + if DEBUG: + print(available) + + if not os.path.exists("presets"): + os.mkdir("presets") + if not os.path.exists("presets/readme.txt"): + with open("presets\\readme.txt", "a", encoding="utf-8") as readme: + text = "To create your own preset visit the wiki here: https://github.com/Official-Husko/mul-tor/wiki/Preset-Configuration" + readme.write(text) + + return config, available, proxy_list, ua_list + + def selection(config, available, user_agents_list, proxy_list=""): + + auto_load_preset = config.get("presetSystem", {}).get("autoLoadPreset", False) + enable_preset_selection = config.get("presetSystem", {}).get("enablePresetSelection", False) + preset_name = config.get("presetSystem", {}).get("presetName", "") + + if auto_load_preset == True and not os.path.exists(f"presets/{preset_name}"): + print(colored(f"Error: Preset {preset_name} does not exist. Continuing without preset!", "red")) + print("") + auto_load_preset = False + + if auto_load_preset == True and DEBUG == False: + auto_load_data = Preset_Manager.loader(available, preset_name) + available = auto_load_data[0] + link_format = auto_load_data[1] + else: + link_format = "" + + if DEBUG == True and use_test_file == True: + if test_small_file == True: + files_list = [f"{owd}\\test.png"] + elif test_large_file == True: + files_list = [f"{owd}\\big_game.zip"] + elif test_very_large_file == True: + files_list = [f"{owd}\\very_big_game.7z"] + else: + print(colored("Something fucked up! Please report this on github. Test_File_Error", "red")) + + if available == []: + print(colored("No sites are available. Please double check your config (and preset if used). If you think this is an error please report it on github.", "red")) + sleep(10) + exit(0) + + questions = [ + inquirer.Checkbox('selections', + message=f"{colored('What sites do you want to upload too?', 'green')} {colored(f'{len(available)} available', 'yellow')}", + choices=available, + ), + ] + answers = inquirer.prompt(questions) + print("") + + sites = answers.get("selections") + + +if __name__ == '__main__': + main_instance = Main() + try: + while True: + main_instance.runner() + except KeyboardInterrupt: + print("User Cancelled! Exiting...") + exit(0) diff --git a/modules/auto_update.py b/modules/auto_update.py index b3c9ad2..3f76ca0 100644 --- a/modules/auto_update.py +++ b/modules/auto_update.py @@ -1,90 +1,90 @@ -# Import Standard Libraries -import os -from time import sleep - -# Import Third-Party Libraries -import requests -from termcolor import colored -import inquirer -from alive_progress import alive_bar - -# Import Local Libraries -from main import version -from .logger import Logger -from .pretty_print import error, ok - -class AutoUpdate: - - def __init__(self): - self.repository_url: str = "https://api.github.com/repos/Official-Husko/mul-tor/releases/latest" - - def _checker(self): - try: - - headers = { - "User-Agent":f"mul-tor/{version} (by Official Husko on GitHub)", - "Accept": "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28" - } - - req = requests.get(self.repository_url, headers=headers).json() - repo_version = req.get("tag_name").replace("v", "") - download_link = req["assets"][0]["browser_download_url"] - - if str(version) < repo_version: - print(colored("UPDATE AVAILABLE! ", "red", attrs=["blink"])) - - body = req.get("body") - name = req.get("name") - date = req.get("published_at").replace("T", " ").replace("Z", "") - - print("") - print(f"Latest release is {colored(name, 'light_blue')} released on {colored(date, 'yellow')}") - print("") - print(body) - print("") - amount_question = [ - inquirer.List('selection', - message=colored("Do you want to download the update?", "green"), - choices=["Yes", "No"], - ), - ] - amount_answers = inquirer.prompt(amount_question) - print("") - decision = amount_answers.get("selection") - if decision == "Yes": - r = requests.get(download_link, headers={"User-Agent":f"mul-tor/{version} (by Official Husko on GitHub)"}, timeout=60, stream=True) - with alive_bar(int(int(r.headers.get('content-length')) / 1024 + 1)) as progress_bar: - progress_bar.text = f'-> Downloading Update {repo_version}, please wait...' - file = open(f"mul-tor-{repo_version}.exe", 'wb') - for chunk in r.iter_content(chunk_size=1024): - if chunk: - file.write(chunk) - file.flush() - progress_bar() - print(f"{ok} Update successfully downloaded! The program will now close and delete the old exe.") - if os.path.exists("delete-exe.bat"): - os.remove("delete-exe.bat") - with open("delete-exe.bat", "a", encoding="utf-8") as bat_creator: - bat_content = f'TASKKILL -F /IM Mul-Tor.exe\ntimeout 3\nDEL .\\Mul-Tor.exe\nren .\\mul-tor-{repo_version}.exe Mul-Tor.exe\nDEL .\\delete-exe.bat' - bat_creator.write(bat_content) - bat_creator.close() - os.startfile(r".\\delete-exe.bat") - sleep(5) - exit(0) - elif decision == "No": - if not os.path.exists("outdated"): - with open("outdated", "a", encoding="utf-8") as mark_outdated: - mark_outdated.close() - elif str(version) >= repo_version: - try: - os.remove("outdated") - except Exception: - pass - - except Exception as e: - # Construct and print the error - error_str = f"An error occurred while checking for updates! Please report this. Exception: {e}" - print(f"{error} {error_str}") - Logger.log_event(error_str, req) +# Import Standard Libraries +import os +from time import sleep + +# Import Third-Party Libraries +import requests +from termcolor import colored +import inquirer +from alive_progress import alive_bar + +# Import Local Libraries +from main import version +from .logger import Logger +from .pretty_print import error, ok + +class AutoUpdate: + + def __init__(self): + self.repository_url: str = "https://api.github.com/repos/Official-Husko/mul-tor/releases/latest" + + def _checker(self): + try: + + headers = { + "User-Agent":f"mul-tor/{version} (by Official Husko on GitHub)", + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28" + } + + req = requests.get(self.repository_url, headers=headers).json() + repo_version = req.get("tag_name").replace("v", "") + download_link = req["assets"][0]["browser_download_url"] + + if str(version) < repo_version: + print(colored("UPDATE AVAILABLE! ", "red", attrs=["blink"])) + + body = req.get("body") + name = req.get("name") + date = req.get("published_at").replace("T", " ").replace("Z", "") + + print("") + print(f"Latest release is {colored(name, 'light_blue')} released on {colored(date, 'yellow')}") + print("") + print(body) + print("") + amount_question = [ + inquirer.List('selection', + message=colored("Do you want to download the update?", "green"), + choices=["Yes", "No"], + ), + ] + amount_answers = inquirer.prompt(amount_question) + print("") + decision = amount_answers.get("selection") + if decision == "Yes": + r = requests.get(download_link, headers={"User-Agent":f"mul-tor/{version} (by Official Husko on GitHub)"}, timeout=60, stream=True) + with alive_bar(int(int(r.headers.get('content-length')) / 1024 + 1)) as progress_bar: + progress_bar.text = f'-> Downloading Update {repo_version}, please wait...' + file = open(f"mul-tor-{repo_version}.exe", 'wb') + for chunk in r.iter_content(chunk_size=1024): + if chunk: + file.write(chunk) + file.flush() + progress_bar() + print(f"{ok} Update successfully downloaded! The program will now close and delete the old exe.") + if os.path.exists("delete-exe.bat"): + os.remove("delete-exe.bat") + with open("delete-exe.bat", "a", encoding="utf-8") as bat_creator: + bat_content = f'TASKKILL -F /IM Mul-Tor.exe\ntimeout 3\nDEL .\\Mul-Tor.exe\nren .\\mul-tor-{repo_version}.exe Mul-Tor.exe\nDEL .\\delete-exe.bat' + bat_creator.write(bat_content) + bat_creator.close() + os.startfile(r".\\delete-exe.bat") + sleep(5) + exit(0) + elif decision == "No": + if not os.path.exists("outdated"): + with open("outdated", "a", encoding="utf-8") as mark_outdated: + mark_outdated.close() + elif str(version) >= repo_version: + try: + os.remove("outdated") + except Exception: + pass + + except Exception as e: + # Construct and print the error + error_str = f"An error occurred while checking for updates! Please report this. Exception: {e}" + print(f"{error} {error_str}") + Logger.log_event(error_str, req) sleep(7) \ No newline at end of file diff --git a/modules/availability_checker.py b/modules/availability_checker.py index 30c98ef..a6b672f 100644 --- a/modules/availability_checker.py +++ b/modules/availability_checker.py @@ -1,81 +1,91 @@ -# Import Standard Libraries -from time import sleep -import random -import json - -# Import Third-Party Libraries -import requests -from termcolor import colored - -# Import Local Libraries -from .setup import USER_AGENT -from .site_data import sites_data_dict -from .logger import Logger -from .pretty_print import error - - -class AvailabilityChecker: - - def __init__(self, config, proxy_list): - self.config = json.loads(config) - self.proxy_list = proxy_list - self.available_sites: list[str] = [] - self.ping_sites: list[str] = [] - - def _blacklist_check(self): - pass - - def _check(self): - blacklist = [] - for blacklisted_site in self.config.get("blacklist", []): - blacklist.append(blacklisted_site.lower()) - for site in sites_data_dict: - if DEBUG: - print(f"{colored('Checking:', 'green')} {site}") - if not site.lower() in blacklist: - ping_sites.append(site) - else: - pass - print(f"{colored('Checking', 'green')} {colored(len(ping_sites), 'yellow')} {colored('supported sites...', 'green')}", end='\r') - - for site in ping_sites: - try: - url = sites_data_dict[site]["api_url"] - proxies = random.choice(self.proxy_list) if self.proxy_list else None - - if DEBUG and SKIP_SITE_CHECK: - available_sites.append(site) - else: - ping = requests.get(url, headers={"User-Agent": USER_AGENT}, proxies=proxies, timeout=5) - - if ping.status_code == 200: - available_sites.append(site) - else: - # Construct and save low level error - error_str = f"Site ping for {site} Failed! Error Code {ping.status_code}" - Logger.log_event(error_str, extra=str(ping)) - - except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: - # Construct the error - error_str = f"An error occurred while checking {site}! Please report this. Exception: {e}" - Logger.log_event(error_str, extra=str(ping)) - sleep(5) - except Exception as e: - # Construct and print the error - error_str = f"An error occurred while checking {site}! Please report this. Exception: {e}" - print(colored(f"{error} {error_str}")) - Logger.log_event(error_str, extra=str(ping)) - sleep(5) - - if available_sites == []: - # Construct and print the error - error_str = f"Available sites is empty. This should not be happening! Please report this." - print(colored(f"{error} {error_str}")) - Logger.log_event(error_str) - sleep(5) - - print(f"{colored(len(available_sites), 'yellow')} {colored('Available Sites ', 'green')}") - - print("") - - return available_sites +# Import Standard Libraries +from time import sleep +import random +import json + +# Import Third-Party Libraries +import requests +from termcolor import colored + +# Import Local Libraries +from .site_data import sites_data_dict +from .logger import Logger +from .pretty_print import PrettyPrint +from .storage import __dev_debug__ as DEBUG +from .storage import __user_agent__ as USER_AGENT + + + +class AvailabilityChecker: + + def __init__(self, config, proxy_list): + self.config = json.loads(config) + self.proxy_list = proxy_list + self.available_sites: list[str] = [] + self.ping_sites: list[str] = [] + + self.pretty_print_instance = PrettyPrint() + + def _check_skip_site_config(self) -> bool: + return self.config.get("skip_site_check", False) + + def _blacklist_check(self, site: str): + # return bool if site is in available sites. this is to filter out blacklisted sites. + return site in self.available_sites + + def _check(self): + + + blacklist = [] + for blacklisted_site in self.config.get("blacklist", []): + blacklist.append(blacklisted_site.lower()) + for site in sites_data_dict: + if DEBUG: + print(f"{colored('Checking:', 'green')} {site}") + if not site.lower() in blacklist: + self.ping_sites.append(site) + else: + pass + print(f"{colored('Checking', 'green')} {colored(len(self.ping_sites), 'yellow')} {colored('supported sites...', 'green')}", end='\r') + + for site in self.ping_sites: + try: + url = sites_data_dict[site]["api_url"] + proxies = random.choice(self.proxy_list) if self.proxy_list else None + + if DEBUG and SKIP_SITE_CHECK: + available_sites.append(site) + else: + ping = requests.get(url, headers={"User-Agent": USER_AGENT}, proxies=proxies, timeout=5) + + if ping.status_code == 200: + available_sites.append(site) + else: + # Construct and save low level error + error_str = f"Site ping for {site} Failed! Error Code {ping.status_code}" + Logger.log_event(error_str, extra=str(ping)) + + except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: + # Construct the error + error_str = f"An error occurred while checking {site}! Please report this. Exception: {e}" + Logger.log_event(error_str, extra=str(ping)) + sleep(5) + except Exception as e: + # Construct and print the error + error_str = f"An error occurred while checking {site}! Please report this. Exception: {e}" + print(colored(f"{error} {error_str}")) + Logger.log_event(error_str, extra=str(ping)) + sleep(5) + + if available_sites == []: + # Construct and print the error + error_str = f"Available sites is empty. This should not be happening! Please report this." + print(colored(f"{error} {error_str}")) + Logger.log_event(error_str) + sleep(5) + + print(f"{colored(len(available_sites), 'yellow')} {colored('Available Sites ', 'green')}") + + print("") + + return available_sites diff --git a/modules/config_manager.py b/modules/config_manager.py index 62049b5..c6607f8 100644 --- a/modules/config_manager.py +++ b/modules/config_manager.py @@ -1,152 +1,152 @@ -# Import Standard Libraries -import json -from time import sleep -import os - -# Import Third-Party Libraries -from termcolor import colored - -# Import Local Libraries -from .pretty_print import PrettyPrint -from .logger import Logger - -# TODO: probably should use jsonc instead of normal jsons: pip install jsonc-parser https://pypi.org/project/jsonc-parser/ - -class ConfigManager: - """ - A class to manage configuration settings for an application. - - Attributes: - filename (str): The name of the configuration file. - latest_config_version (float): The latest version of the configuration. - default_config (dict): The default configuration settings. - config (dict): The current configuration settings. - """ - - def __init__(self) -> None: - """ - Initializes the ConfigManager object. - """ - self.filename = "app_config.json" - self.latest_config_version = 2.0 - self.default_config = self._default_config() - self.config = self._load_config() - - self.pretty_print_instance = PrettyPrint() - - def _load_config(self) -> dict: - """ - Loads the configuration from the file, handles versioning, and migration if needed. - - Returns: - dict: The loaded or default configuration. - """ - if os.path.exists(self.filename): - with open(self.filename, "r", encoding="utf-8") as cfg_file: - config = json.load(cfg_file) - - config_version = config.get("version", "0.0.0") - - if config_version < self.latest_config_version: - print(colored(f"{self.pretty_print_instance.info} You are using an outdated config version! Trying to migrate config to new version.", "green")) - try: - self._migrate_config() - except Exception as e: - error_str = f"An error occurred during the migration of the config! Please report this. Exception: {e}" - print(colored(f"{self.pretty_print_instance.error} {error_str}", 'red')) - Logger.log_event(error_str) - sleep(5) - print(colored(f"{self.pretty_print_instance.info} Old one will be backed up and new one will be created.", "red")) - config = self._create_default_config() - else: - return config - else: - self._save_config() - print(colored(f"{self.pretty_print_instance.info} New config file generated! Configure it and restart the program or wait 5 seconds and the program will continue with the default values."), "green") - print("") - sleep(5) - return self._default_config() - - def _default_config(self) -> dict: - """ - Returns the default configuration settings. - - Returns: - dict: The default configuration. - """ - return { - "configHelpPage": "https://github.com/Official-Husko/mul-tor/wiki/Configuration", - "version": self.latest_config_version, - "checkForUpdates": True, - "useProxies": False, - "saveLinksToFile": True, - "presetSystem": { - "enablePresetSelection": False, - "autoLoadPreset": False, - "presetName": "preset.json" - }, - "api_keys": { - "BowFile": { - "apiKey1": "", - "apiKey2": "" - }, - "DooDrive": { - "apiKey": "", - "apiToken": "" - }, - "Mixdrop": { - "email": "", - "apiKey": "" - }, - "Rapidgator": { - "email": "", - "password": "" - } - }, - "blacklist": [ - "SomeSiteName", - "CheapGoFileCopy", - "HotSinglesInYourArea" - ], - "proxySources": { - "http": [ - "https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/http.txt", - "https://raw.githubusercontent.com/ShiftyTR/Proxy-List/master/http.txt", - "https://raw.githubusercontent.com/mmpx12/proxy-list/master/http.txt", - "https://raw.githubusercontent.com/Volodichev/proxy-list/main/http.txt", - "https://raw.githubusercontent.com/monosans/proxy-list/main/proxies/http.txt", - "https://raw.githubusercontent.com/roma8ok/proxy-list/main/proxy-list-http.txt" - ], - "https": [], - "socks4": [], - "socks5": [] - } - } - - def _save_config(self) -> str: - """ - Saves the default configuration to the file. - - Returns: - str: Status message indicating success or failure. - """ - try: - with open(self.filename, "w", encoding="utf-8") as cfg_file: - json.dump(self._default_config(), cfg_file, indent=4) - return "OK" - except Exception as e: - return f"An error occurred during the writing of the config file! Please report this. Exception: {e}" - - def _migrate_config(self) -> dict: - """ - Migrates the config to the latest version by adding any missing keys. - - Returns: - dict: The migrated configuration. - """ - for key, value in self.default_config.items(): - if key not in self.config: - self.config[key] = value - - self._save_config() - return self.config +# Import Standard Libraries +import json +from time import sleep +import os + +# Import Third-Party Libraries +from termcolor import colored + +# Import Local Libraries +from .pretty_print import PrettyPrint +from .logger import Logger + +# TODO: probably should use jsonc instead of normal jsons: pip install jsonc-parser https://pypi.org/project/jsonc-parser/ + +class ConfigManager: + """ + A class to manage configuration settings for an application. + + Attributes: + filename (str): The name of the configuration file. + latest_config_version (float): The latest version of the configuration. + default_config (dict): The default configuration settings. + config (dict): The current configuration settings. + """ + + def __init__(self) -> None: + """ + Initializes the ConfigManager object. + """ + self.filename = "app_config.json" + self.latest_config_version = 2.0 + self.default_config = self._default_config() + self.config = self._load_config() + + self.pretty_print_instance = PrettyPrint() + + def _load_config(self) -> dict: + """ + Loads the configuration from the file, handles versioning, and migration if needed. + + Returns: + dict: The loaded or default configuration. + """ + if os.path.exists(self.filename): + with open(self.filename, "r", encoding="utf-8") as cfg_file: + config = json.load(cfg_file) + + config_version = config.get("version", "0.0.0") + + if config_version < self.latest_config_version: + print(colored(f"{self.pretty_print_instance.info} You are using an outdated config version! Trying to migrate config to new version.", "green")) + try: + self._migrate_config() + except Exception as e: + error_str = f"An error occurred during the migration of the config! Please report this. Exception: {e}" + print(colored(f"{self.pretty_print_instance.error} {error_str}", 'red')) + Logger.log_event(error_str) + sleep(5) + print(colored(f"{self.pretty_print_instance.info} Old one will be backed up and new one will be created.", "red")) + config = self._create_default_config() + else: + return config + else: + self._save_config() + print(colored(f"{self.pretty_print_instance.info} New config file generated! Configure it and restart the program or wait 5 seconds and the program will continue with the default values."), "green") + print("") + sleep(5) + return self._default_config() + + def _default_config(self) -> dict: + """ + Returns the default configuration settings. + + Returns: + dict: The default configuration. + """ + return { + "configHelpPage": "https://github.com/Official-Husko/mul-tor/wiki/Configuration", + "version": self.latest_config_version, + "checkForUpdates": True, + "useProxies": False, + "saveLinksToFile": True, + "presetSystem": { + "enablePresetSelection": False, + "autoLoadPreset": False, + "presetName": "preset.json" + }, + "api_keys": { + "BowFile": { + "apiKey1": "", + "apiKey2": "" + }, + "DooDrive": { + "apiKey": "", + "apiToken": "" + }, + "Mixdrop": { + "email": "", + "apiKey": "" + }, + "Rapidgator": { + "email": "", + "password": "" + } + }, + "blacklist": [ + "SomeSiteName", + "CheapGoFileCopy", + "HotSinglesInYourArea" + ], + "proxySources": { + "http": [ + "https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/http.txt", + "https://raw.githubusercontent.com/ShiftyTR/Proxy-List/master/http.txt", + "https://raw.githubusercontent.com/mmpx12/proxy-list/master/http.txt", + "https://raw.githubusercontent.com/Volodichev/proxy-list/main/http.txt", + "https://raw.githubusercontent.com/monosans/proxy-list/main/proxies/http.txt", + "https://raw.githubusercontent.com/roma8ok/proxy-list/main/proxy-list-http.txt" + ], + "https": [], + "socks4": [], + "socks5": [] + } + } + + def _save_config(self) -> str: + """ + Saves the default configuration to the file. + + Returns: + str: Status message indicating success or failure. + """ + try: + with open(self.filename, "w", encoding="utf-8") as cfg_file: + json.dump(self._default_config(), cfg_file, indent=4) + return "OK" + except Exception as e: + return f"An error occurred during the writing of the config file! Please report this. Exception: {e}" + + def _migrate_config(self) -> dict: + """ + Migrates the config to the latest version by adding any missing keys. + + Returns: + dict: The migrated configuration. + """ + for key, value in self.default_config.items(): + if key not in self.config: + self.config[key] = value + + self._save_config() + return self.config diff --git a/modules/deprecated/README.md b/modules/deprecated/README.md index 4987a53..127c802 100644 --- a/modules/deprecated/README.md +++ b/modules/deprecated/README.md @@ -1,6 +1,6 @@ -# Deprecated site scripts. - -All site scripts in this folder are deprecated for one or more reasons. Most of the site scripts will be here due to Website Takedowns. They are stored here for preservation templates reasons, to be fixed and added again or if needed for anything else. - - +# Deprecated site scripts. + +All site scripts in this folder are deprecated for one or more reasons. Most of the site scripts will be here due to Website Takedowns. They are stored here for preservation templates reasons, to be fixed and added again or if needed for anything else. + + Some scripts are here because I can't get them to work but they will most likely have most of the code complete to make it work and require minimal tweaking to make them work completely. \ No newline at end of file diff --git a/modules/deprecated/anonfiles.py b/modules/deprecated/anonfiles.py index e02204e..9aedd03 100644 --- a/modules/deprecated/anonfiles.py +++ b/modules/deprecated/anonfiles.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -""" -Last Checked 24/03/2024 -""" - -""" - -"AnonFiles": { - "apiKey": False, - "url": "https://api.anonfiles.com/upload", - "api_url": "https://api.anonfiles.com/", - "download_url_base": "https://anonfiles.com/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -} - -""" - -site = "AnonFiles" - -class AnonFiles: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +""" +Last Checked 24/03/2024 +""" + +""" + +"AnonFiles": { + "apiKey": False, + "url": "https://api.anonfiles.com/upload", + "api_url": "https://api.anonfiles.com/", + "download_url_base": "https://anonfiles.com/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +} + +""" + +site = "AnonFiles" + +class AnonFiles: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/anonfilesme.py b/modules/deprecated/anonfilesme.py index 4374484..b182477 100644 --- a/modules/deprecated/anonfilesme.py +++ b/modules/deprecated/anonfilesme.py @@ -1,64 +1,64 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "AnonFilesMe" - -""" -Last Checked 24/03/2024 -""" - -""" - -"AnonFilesMe": { - "apiKey": False, - "url": "https://anonfiles.me/api/v1/upload", - "api_url": "https://anonfiles.me/", - "download_url_base": "https://anonfiles.me/", - "size_limit": 7, - "size_unit": "GB" -}, - -""" - -class AnonFilesMe: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "AnonFilesMe" + +""" +Last Checked 24/03/2024 +""" + +""" + +"AnonFilesMe": { + "apiKey": False, + "url": "https://anonfiles.me/api/v1/upload", + "api_url": "https://anonfiles.me/", + "download_url_base": "https://anonfiles.me/", + "size_limit": 7, + "size_unit": "GB" +}, + +""" + +class AnonFilesMe: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/anonymfile-api.py b/modules/deprecated/anonymfile-api.py index ecb5b20..41ede30 100644 --- a/modules/deprecated/anonymfile-api.py +++ b/modules/deprecated/anonymfile-api.py @@ -1,66 +1,66 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Anonymfile" - -""" -Last Checked 24/03/2024 -This is the API version of Anonymfile. They broke the API a while ago so i replaced it with the non-api variant for now. - -""" - -""" - - "Anonymfile": { - "apiKey": False, - "url": "https://anonymfile.com/api/v1/upload", - "api_url": "https://anonymfile.com/", - "download_url_base": "https://anonymfile.com/", - "size_limit": 7, - "size_unit": "GB" - }, - -""" - -class Anonymfile: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Anonymfile" + +""" +Last Checked 24/03/2024 +This is the API version of Anonymfile. They broke the API a while ago so i replaced it with the non-api variant for now. + +""" + +""" + + "Anonymfile": { + "apiKey": False, + "url": "https://anonymfile.com/api/v1/upload", + "api_url": "https://anonymfile.com/", + "download_url_base": "https://anonymfile.com/", + "size_limit": 7, + "size_unit": "GB" + }, + +""" + +class Anonymfile: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/anyfile.py b/modules/deprecated/anyfile.py index d05c04a..9632339 100644 --- a/modules/deprecated/anyfile.py +++ b/modules/deprecated/anyfile.py @@ -1,64 +1,64 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "AnyFile" - -""" -Last Checked 24/03/2024 -""" - -""" - -"AnyFile": { - "apiKey": False, - "url": "https://anyfile.co/api/v1/upload", - "api_url": "https://anyfile.co/", - "download_url_base": "https://anyfile.co/", - "size_limit": 7, - "size_unit": "GB" -}, - -""" - -class AnyFile: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "AnyFile" + +""" +Last Checked 24/03/2024 +""" + +""" + +"AnyFile": { + "apiKey": False, + "url": "https://anyfile.co/api/v1/upload", + "api_url": "https://anyfile.co/", + "download_url_base": "https://anyfile.co/", + "size_limit": 7, + "size_unit": "GB" +}, + +""" + +class AnyFile: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/bayfiles.py b/modules/deprecated/bayfiles.py index c4672d8..6efcbd5 100644 --- a/modules/deprecated/bayfiles.py +++ b/modules/deprecated/bayfiles.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "BayFiles" - -""" -Last Checked 24/03/2024 -""" - -""" - -"BayFiles": { - "apiKey": False, - "url": "https://api.bayfiles.com/upload", - "api_url": "https://api.bayfiles.com/", - "download_url_base": "https://bayfiles.com/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -} - -""" - -class BayFiles: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "BayFiles" + +""" +Last Checked 24/03/2024 +""" + +""" + +"BayFiles": { + "apiKey": False, + "url": "https://api.bayfiles.com/upload", + "api_url": "https://api.bayfiles.com/", + "download_url_base": "https://bayfiles.com/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +} + +""" + +class BayFiles: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/bayfilesio.py b/modules/deprecated/bayfilesio.py index a12b1d9..8430058 100644 --- a/modules/deprecated/bayfilesio.py +++ b/modules/deprecated/bayfilesio.py @@ -1,64 +1,64 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "BayFilesIo" - -""" -Last Checked 24/03/2024 -""" - -""" - -"BayFilesIo": { - "apiKey": False, - "url": "https://bayfiles.io/api/v1/upload", - "api_url": "https://bayfiles.io/", - "download_url_base": "https://bayfiles.io/", - "size_limit": 7, - "size_unit": "GB" -}, - -""" - -class BayFilesIo: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "BayFilesIo" + +""" +Last Checked 24/03/2024 +""" + +""" + +"BayFilesIo": { + "apiKey": False, + "url": "https://bayfiles.io/api/v1/upload", + "api_url": "https://bayfiles.io/", + "download_url_base": "https://bayfiles.io/", + "size_limit": 7, + "size_unit": "GB" +}, + +""" + +class BayFilesIo: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/bunkrr.py b/modules/deprecated/bunkrr.py index fe79d6d..85f1556 100644 --- a/modules/deprecated/bunkrr.py +++ b/modules/deprecated/bunkrr.py @@ -1,202 +1,202 @@ -import requests -import os -import random -import uuid -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Bunkrr" - -""" -Last Checked 24/03/2024 -""" - -# https://github.com/Official-Husko/mul-tor/discussions/13 - -""" - -"Bunkrr": { - "apiKey": True, - "url": "{server}", - "api_url": "https://app.bunkrr.su/", - "download_url_base": "https://bunkrr.ru/d/", - "server_url": "https://app.bunkrr.su/api/node", - "options_url": "https://app.bunkrr.su/api/check", - "finalize_url": "{server}/finishchunks" -}, - -""" - - -class Bunkrr: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - download_url_base = sites_data_dict[site]["download_url_base"] - # Select a random user agent - ua = random.choice(user_agents) - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - api_token = api_keys.get("token", False) - - if api_token in (False, ""): - raise Exception("Missing API Credentials?") - - options_url = sites_data_dict[site]["options_url"] - - headers = { - "User-Agent": ua, - "Accept": "application/json", - } - - raw_req = requests.get(url=options_url, headers=headers, proxies=proxies, timeout=300) - raw_req = raw_req.json() - - max_file_size = raw_req.get("maxSize", "0B") - chunk_size = raw_req.get("chunkSize", {}).get("max", "0B") - file_blacklist = raw_req.get("stripTags", {}).get("blacklistExtensions", []) - - if max_file_size == "0B" or chunk_size == "0B": - raise Exception("Invalid max file size or chunk size") - - # TODO: check if either one is 0 and abort - - units_to_calc = [max_file_size, chunk_size] - units_calculated = [] - - for unit in units_to_calc: - size_str = unit.lower() - unit_multiplier = {'b': 1, 'kb': 1024, 'mb': 1024 ** 2, 'gb': 1024 ** 3, 'tb': 1024 ** 4} - match = re.match(r'^(\d+)([a-z]+)$', size_str) - - if match: - value, unit = match.groups() - bytes_size = int(value) * unit_multiplier.get(unit, 1) - units_calculated.append(bytes_size) - else: - raise ValueError("Invalid input format") - - max_file_size = units_calculated[0] - chunk_size = units_calculated[1] - - file_uuid = str(uuid.uuid4()) - - _, file_extension = os.path.splitext(file_name) - - if file_size <= max_file_size: - if file_extension in file_blacklist: - raise Exception(f"File is blacklisted! {file_blacklist}") - - # Get server URL - server_url = sites_data_dict[site]["server_url"] - - headers = { - "User-Agent": ua, - "Accept": "application/json", - "token": api_token - } - - raw_req = requests.get(url=server_url, headers=headers, proxies=proxies, timeout=300) - - try: - raw_req = raw_req.json() - if not raw_req.get("success", False) == True: - raise Exception("Failed to get server URL. Error: Success was somehow false? Report this!") - upload_url = raw_req.get("url", "") - - except Exception as e: - raise Exception(f"Failed to get server URL. Error: {e}") - - chunk_size = 25000000 - total_chunks = (file_size + chunk_size - 1) // chunk_size - chunk_index = 0 - dzchunkbyteoffset = 0 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - upload_data = { - "dzuuid": file_uuid, - "dzchunkindex": chunk_index, - "dztotalfilesize": file_size, - "dzchunksize": chunk_size, - "dztotalchunkcount": total_chunks, - "dzchunkbyteoffset": dzchunkbyteoffset - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300) - - raw_req = raw_req.json() - - if not raw_req.get("success", False) == True: - raise Exception("Upload failed somehow? Please Report this!") - - chunk_index += 1 - dzchunkbyteoffset += chunk_size - - # final request to get the data - upload_data = { - "files": [ - { - "uuid": file_uuid, - "original": file_name, - "type": "application/octet-stream", - "albumid": "", - "filelength": "", - "age": "" - } - ] - } - - finalize_url = sites_data_dict[site]["finalize_url"].format(server=upload_url) - - raw_req = requests.post(url=finalize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) - - json_req = raw_req.json() - - if json_req.get("success", False) == True: - file_url = json_req["files"][0]["url"] - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": file_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random +import uuid +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Bunkrr" + +""" +Last Checked 24/03/2024 +""" + +# https://github.com/Official-Husko/mul-tor/discussions/13 + +""" + +"Bunkrr": { + "apiKey": True, + "url": "{server}", + "api_url": "https://app.bunkrr.su/", + "download_url_base": "https://bunkrr.ru/d/", + "server_url": "https://app.bunkrr.su/api/node", + "options_url": "https://app.bunkrr.su/api/check", + "finalize_url": "{server}/finishchunks" +}, + +""" + + +class Bunkrr: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + download_url_base = sites_data_dict[site]["download_url_base"] + # Select a random user agent + ua = random.choice(user_agents) + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + api_token = api_keys.get("token", False) + + if api_token in (False, ""): + raise Exception("Missing API Credentials?") + + options_url = sites_data_dict[site]["options_url"] + + headers = { + "User-Agent": ua, + "Accept": "application/json", + } + + raw_req = requests.get(url=options_url, headers=headers, proxies=proxies, timeout=300) + raw_req = raw_req.json() + + max_file_size = raw_req.get("maxSize", "0B") + chunk_size = raw_req.get("chunkSize", {}).get("max", "0B") + file_blacklist = raw_req.get("stripTags", {}).get("blacklistExtensions", []) + + if max_file_size == "0B" or chunk_size == "0B": + raise Exception("Invalid max file size or chunk size") + + # TODO: check if either one is 0 and abort + + units_to_calc = [max_file_size, chunk_size] + units_calculated = [] + + for unit in units_to_calc: + size_str = unit.lower() + unit_multiplier = {'b': 1, 'kb': 1024, 'mb': 1024 ** 2, 'gb': 1024 ** 3, 'tb': 1024 ** 4} + match = re.match(r'^(\d+)([a-z]+)$', size_str) + + if match: + value, unit = match.groups() + bytes_size = int(value) * unit_multiplier.get(unit, 1) + units_calculated.append(bytes_size) + else: + raise ValueError("Invalid input format") + + max_file_size = units_calculated[0] + chunk_size = units_calculated[1] + + file_uuid = str(uuid.uuid4()) + + _, file_extension = os.path.splitext(file_name) + + if file_size <= max_file_size: + if file_extension in file_blacklist: + raise Exception(f"File is blacklisted! {file_blacklist}") + + # Get server URL + server_url = sites_data_dict[site]["server_url"] + + headers = { + "User-Agent": ua, + "Accept": "application/json", + "token": api_token + } + + raw_req = requests.get(url=server_url, headers=headers, proxies=proxies, timeout=300) + + try: + raw_req = raw_req.json() + if not raw_req.get("success", False) == True: + raise Exception("Failed to get server URL. Error: Success was somehow false? Report this!") + upload_url = raw_req.get("url", "") + + except Exception as e: + raise Exception(f"Failed to get server URL. Error: {e}") + + chunk_size = 25000000 + total_chunks = (file_size + chunk_size - 1) // chunk_size + chunk_index = 0 + dzchunkbyteoffset = 0 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + upload_data = { + "dzuuid": file_uuid, + "dzchunkindex": chunk_index, + "dztotalfilesize": file_size, + "dzchunksize": chunk_size, + "dztotalchunkcount": total_chunks, + "dzchunkbyteoffset": dzchunkbyteoffset + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300) + + raw_req = raw_req.json() + + if not raw_req.get("success", False) == True: + raise Exception("Upload failed somehow? Please Report this!") + + chunk_index += 1 + dzchunkbyteoffset += chunk_size + + # final request to get the data + upload_data = { + "files": [ + { + "uuid": file_uuid, + "original": file_name, + "type": "application/octet-stream", + "albumid": "", + "filelength": "", + "age": "" + } + ] + } + + finalize_url = sites_data_dict[site]["finalize_url"].format(server=upload_url) + + raw_req = requests.post(url=finalize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) + + json_req = raw_req.json() + + if json_req.get("success", False) == True: + file_url = json_req["files"][0]["url"] + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": file_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/filechan.py b/modules/deprecated/filechan.py index 2733d1c..e009c73 100644 --- a/modules/deprecated/filechan.py +++ b/modules/deprecated/filechan.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "FileChan" - -""" -Last Checked 24/03/2024 -""" - -""" - -"FileChan": { - "apiKey": False, - "url": "https://api.filechan.org/upload", - "api_url": "https://api.filechan.org/", - "download_url_base": "https://filechan.org/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class FileChan: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "FileChan" + +""" +Last Checked 24/03/2024 +""" + +""" + +"FileChan": { + "apiKey": False, + "url": "https://api.filechan.org/upload", + "api_url": "https://api.filechan.org/", + "download_url_base": "https://filechan.org/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class FileChan: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/filemail.py b/modules/deprecated/filemail.py index 2ce62ea..aee4272 100644 --- a/modules/deprecated/filemail.py +++ b/modules/deprecated/filemail.py @@ -1,60 +1,60 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from .logger import Logger - -from main import DEBUG - -site = "FileMail" - -""" -Last Checked 24/03/2024 -""" - -""" - -Shitty 2 uploads limit per day. Even the initializing counts as one. - -""" - -class FileMail: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - base_url = sites_data_dict[site]["download_url_base"] - server_url = sites_data_dict[site]["server_url"].format(api_key=api_key) - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '') if len(file_name) > 240 else file_name # Changed from 255 to 15 as an additional safety net. - - # upload_url = sites_data_dict[site]["url"].format(server=server) - - headers = {"User-Agent": ua, "Content-Type": "application/octet-stream", "accept": "application/json"} - - # Initialize file upload and get server url - if proxy_list == []: - req = requests.post(url=server_url, headers=headers) - else: - req = requests.put(url=server_url, data=file_upload, headers=headers, proxies=random.choice(proxy_list)) - - - with open(file, "rb") as file_upload: - if proxy_list == []: - req = requests.post(url=rand_url, data=file_upload, headers=headers) - else: - req = requests.put(url=rand_url, data=file_upload, headers=headers, proxies=random.choice(proxy_list)) - file_upload.close() - if req.status_code == 201: - return {"status": "ok", "file_name": file_name, "file_url": rand_url} - else: - raise Exception("Wrong Response Code. View request body below or in log file.") - - except Exception as e: +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from .logger import Logger + +from main import DEBUG + +site = "FileMail" + +""" +Last Checked 24/03/2024 +""" + +""" + +Shitty 2 uploads limit per day. Even the initializing counts as one. + +""" + +class FileMail: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + base_url = sites_data_dict[site]["download_url_base"] + server_url = sites_data_dict[site]["server_url"].format(api_key=api_key) + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '') if len(file_name) > 240 else file_name # Changed from 255 to 15 as an additional safety net. + + # upload_url = sites_data_dict[site]["url"].format(server=server) + + headers = {"User-Agent": ua, "Content-Type": "application/octet-stream", "accept": "application/json"} + + # Initialize file upload and get server url + if proxy_list == []: + req = requests.post(url=server_url, headers=headers) + else: + req = requests.put(url=server_url, data=file_upload, headers=headers, proxies=random.choice(proxy_list)) + + + with open(file, "rb") as file_upload: + if proxy_list == []: + req = requests.post(url=rand_url, data=file_upload, headers=headers) + else: + req = requests.put(url=rand_url, data=file_upload, headers=headers, proxies=random.choice(proxy_list)) + file_upload.close() + if req.status_code == 201: + return {"status": "ok", "file_name": file_name, "file_url": rand_url} + else: + raise Exception("Wrong Response Code. View request body below or in log file.") + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/filestore.py b/modules/deprecated/filestore.py index 22bd4e0..0a4e733 100644 --- a/modules/deprecated/filestore.py +++ b/modules/deprecated/filestore.py @@ -1,88 +1,88 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "FileStore" - -""" -Last Checked 24/03/2024 -""" - -""" - -"FileStore": { - "apiKey": True, - "url": "{server}", - "api_url": "https://filestore.me/", - "download_url_base": "https://filestore.me/", - "server_url": "https://filestore.me/?op=upload_form", - "size_limit": 100, - "size_unit": "MB" -}, - -""" - -class FileStore: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - url = sites_data_dict[site]["api_url"] - download_url_base = sites_data_dict[site]["download_url_base"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - api_username = api_keys.get("username", False) - api_password = api_keys.get("password", False) - - if api_username in (False, "") or api_password in (False, ""): - raise Exception("Missing API Credentials?") - - # Execute Login for session id - data = { - "op": "login", - "login": api_username, - "password": api_password - } - - raw_req = requests.post(url=url, data=data, headers=headers, proxies=proxies) - - if raw_req.status_code == 200: - session_id = raw_req.cookies.get("xfss") - - if calc_size == "OK": - data = { - "sess_id": file_id, - "keepalive": 1 - } - form_data = { - 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, stream=True) - - if raw_req.status_code == 200: - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "FileStore" + +""" +Last Checked 24/03/2024 +""" + +""" + +"FileStore": { + "apiKey": True, + "url": "{server}", + "api_url": "https://filestore.me/", + "download_url_base": "https://filestore.me/", + "server_url": "https://filestore.me/?op=upload_form", + "size_limit": 100, + "size_unit": "MB" +}, + +""" + +class FileStore: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + url = sites_data_dict[site]["api_url"] + download_url_base = sites_data_dict[site]["download_url_base"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + api_username = api_keys.get("username", False) + api_password = api_keys.get("password", False) + + if api_username in (False, "") or api_password in (False, ""): + raise Exception("Missing API Credentials?") + + # Execute Login for session id + data = { + "op": "login", + "login": api_username, + "password": api_password + } + + raw_req = requests.post(url=url, data=data, headers=headers, proxies=proxies) + + if raw_req.status_code == 200: + session_id = raw_req.cookies.get("xfss") + + if calc_size == "OK": + data = { + "sess_id": file_id, + "keepalive": 1 + } + form_data = { + 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, stream=True) + + if raw_req.status_code == 200: + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/filetransfer.py b/modules/deprecated/filetransfer.py index 3270166..107c15c 100644 --- a/modules/deprecated/filetransfer.py +++ b/modules/deprecated/filetransfer.py @@ -1,170 +1,170 @@ -import requests -import os -import random -import base64 - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "FileTransfer" - -""" -Last Checked 24/03/2024 -""" - -""" - -"FileTransfer": { - "apiKey": False, - "url": "{server}", - "api_url": "https://filetransfer.io/", - "download_url_base": "https://filetransfer.io/data-package/", - "server_url": "https://filetransfer.io/api/v1/upload", - "initialize_url": "https://filetransfer.io/start-upload", - "finalize_url": "{final_url}", - "size_limit": 6, - "size_unit": "GB" -}, - -""" - -""" - -Throws 415 errors even tho it should all be correct. wasted too much time for something this poorly coded. -To whoever made this site and system go fuck yourself and do us all a favor and stop coding things. - -~ An edit 3 months later. I was a bit angry yes. - -""" - -class FileTransfer: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Get the upload URL and size limit from the site data dictionary - initialize_url = sites_data_dict[site]["initialize_url"] - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua, - "X-Requested-With": "XMLHttpRequest" - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - # Send the upload request with the form data, headers, and proxies - init_req = requests.get(url=initialize_url, headers=headers, proxies=proxies) - - # Parse the response JSON and get the download URL - init_resp = init_req.json() - server_url = init_resp.get("uploadUrl", "") - - base64_filename = base64.b64encode(file_name.encode('utf-8')) - base64_filename = base64_filename.decode('utf-8') - print(base64_filename) - - headers = { - "User-Agent": ua, - "Tus-Resumable": "1.0.0", - "Upload-Length": f"{file_size}", - "Upload-Metadata": f"filename {base64_filename},filetype ,fileorder MQ==", - } - - server_req = requests.post(url=server_url, headers=headers, proxies=proxies) - - print(server_req.status_code) - print(server_req.headers) - - parts = server_url.split("/") - print(parts) - upload_url_start = parts[2] - print(upload_url_start) - - server_location = server_req.headers["Location"] - upload_url = f"https://{upload_url_start}{server_location}" - print(upload_url) - - chunk_size = 10485760 # 10 MB (WHO THE FUCK DOES THIS SHIT IN 10MB CHUNKS? THIS WEBSITE IS FUCKED) - chunk_offset = 0 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - base64_filename = base64.b64encode(file_name.encode('utf-8')) - - headers = { - "User-Agent": ua, - "Tus-Resumable": "1.0.0", - "Upload-Offset": f"{chunk_offset}" - } - print(headers) - - form_data = { - 'file': (os.path.basename(file), chunk_data, 'application/offset+octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.patch(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300) - - print(raw_req.status_code) - - if raw_req.status_code == 200 or raw_req.status_code == 204: - print("chunk uploaded") - - chunk_offset += chunk_size - - headers = { - "User-Agent": ua, - "X-Requested-With": "XMLHttpRequest" - } - - raw_req = requests.post(url=upload_url, headers=headers, proxies=proxies, timeout=300) - print(raw_req.text) - - upload_resp = raw_req.json() - - download_url = upload_resp.get("deliveryPublicLink", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import base64 + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "FileTransfer" + +""" +Last Checked 24/03/2024 +""" + +""" + +"FileTransfer": { + "apiKey": False, + "url": "{server}", + "api_url": "https://filetransfer.io/", + "download_url_base": "https://filetransfer.io/data-package/", + "server_url": "https://filetransfer.io/api/v1/upload", + "initialize_url": "https://filetransfer.io/start-upload", + "finalize_url": "{final_url}", + "size_limit": 6, + "size_unit": "GB" +}, + +""" + +""" + +Throws 415 errors even tho it should all be correct. wasted too much time for something this poorly coded. +To whoever made this site and system go fuck yourself and do us all a favor and stop coding things. + +~ An edit 3 months later. I was a bit angry yes. + +""" + +class FileTransfer: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Get the upload URL and size limit from the site data dictionary + initialize_url = sites_data_dict[site]["initialize_url"] + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua, + "X-Requested-With": "XMLHttpRequest" + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + # Send the upload request with the form data, headers, and proxies + init_req = requests.get(url=initialize_url, headers=headers, proxies=proxies) + + # Parse the response JSON and get the download URL + init_resp = init_req.json() + server_url = init_resp.get("uploadUrl", "") + + base64_filename = base64.b64encode(file_name.encode('utf-8')) + base64_filename = base64_filename.decode('utf-8') + print(base64_filename) + + headers = { + "User-Agent": ua, + "Tus-Resumable": "1.0.0", + "Upload-Length": f"{file_size}", + "Upload-Metadata": f"filename {base64_filename},filetype ,fileorder MQ==", + } + + server_req = requests.post(url=server_url, headers=headers, proxies=proxies) + + print(server_req.status_code) + print(server_req.headers) + + parts = server_url.split("/") + print(parts) + upload_url_start = parts[2] + print(upload_url_start) + + server_location = server_req.headers["Location"] + upload_url = f"https://{upload_url_start}{server_location}" + print(upload_url) + + chunk_size = 10485760 # 10 MB (WHO THE FUCK DOES THIS SHIT IN 10MB CHUNKS? THIS WEBSITE IS FUCKED) + chunk_offset = 0 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + base64_filename = base64.b64encode(file_name.encode('utf-8')) + + headers = { + "User-Agent": ua, + "Tus-Resumable": "1.0.0", + "Upload-Offset": f"{chunk_offset}" + } + print(headers) + + form_data = { + 'file': (os.path.basename(file), chunk_data, 'application/offset+octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.patch(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300) + + print(raw_req.status_code) + + if raw_req.status_code == 200 or raw_req.status_code == 204: + print("chunk uploaded") + + chunk_offset += chunk_size + + headers = { + "User-Agent": ua, + "X-Requested-With": "XMLHttpRequest" + } + + raw_req = requests.post(url=upload_url, headers=headers, proxies=proxies, timeout=300) + print(raw_req.text) + + upload_resp = raw_req.json() + + download_url = upload_resp.get("deliveryPublicLink", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/gofilecc.py b/modules/deprecated/gofilecc.py index 48ee9ad..c5ba257 100644 --- a/modules/deprecated/gofilecc.py +++ b/modules/deprecated/gofilecc.py @@ -1,64 +1,64 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "GoFileCC" - -""" -Last Checked 24/03/2024 -""" - -""" - -"GoFileCC": { - "apiKey": False, - "url": "https://gofile.cc/api/v1/upload", - "api_url": "https://gofile.cc/", - "download_url_base": "https://gofile.cc/", - "size_limit": 7, - "size_unit": "GB" -}, - -""" - -class GoFileCC: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, stream=True) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "GoFileCC" + +""" +Last Checked 24/03/2024 +""" + +""" + +"GoFileCC": { + "apiKey": False, + "url": "https://gofile.cc/api/v1/upload", + "api_url": "https://gofile.cc/", + "download_url_base": "https://gofile.cc/", + "size_limit": 7, + "size_unit": "GB" +}, + +""" + +class GoFileCC: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, stream=True) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/hotfile.py b/modules/deprecated/hotfile.py index 0ffd91f..0cda825 100644 --- a/modules/deprecated/hotfile.py +++ b/modules/deprecated/hotfile.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "HotFile" - -""" -Last Checked 24/03/2024 -""" - -""" - -"HotFile": { - "apiKey": False, - "url": "https://api.hotfile.io/upload", - "api_url": "https://api.hotfile.io/", - "download_url_base": "https://hotfile.io/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class HotFile: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "HotFile" + +""" +Last Checked 24/03/2024 +""" + +""" + +"HotFile": { + "apiKey": False, + "url": "https://api.hotfile.io/upload", + "api_url": "https://api.hotfile.io/", + "download_url_base": "https://hotfile.io/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class HotFile: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/krakenfiles_api.py b/modules/deprecated/krakenfiles_api.py index f740b0e..9947cf7 100644 --- a/modules/deprecated/krakenfiles_api.py +++ b/modules/deprecated/krakenfiles_api.py @@ -1,71 +1,71 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Krakenfiles" - -""" -Last Checked 24/03/2024 -""" - -# This version is currently not in use because the API docs are outdated. Following the API rules results in a 500 error. - -class Krakenfiles: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - server_url = sites_data_dict[site]["server_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - characters = string.ascii_lowercase + string.digits + string.ascii_uppercase - file_id = ''.join(random.choice(characters) for i in range(10)) - access_code = ''.join(random.choice(characters) for i in range(7)) - - if proxy_list == []: - server_req = requests.get(url=server_url, headers={"User-Agent": ua}) - else: - server_req = requests.get(url=server_url, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)) - - server_response = server_req.json() - print(server_response) - upload_url = server_response.get("data", {}).get("url", "") - print(upload_url) - token = server_response.get("data", {}).get("serverAccessToken", "") - print(token) - - if calc_size == "OK": - data = { - "serverAccessToken": token - } - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - if proxy_list == []: - raw_req = requests.post(url=upload_url, data=data, files=form_data, headers={"User-Agent": ua}) - else: - raw_req = requests.post(url=upload_url, files=form_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)) - - if raw_req.status_code == 200: - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Krakenfiles" + +""" +Last Checked 24/03/2024 +""" + +# This version is currently not in use because the API docs are outdated. Following the API rules results in a 500 error. + +class Krakenfiles: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + server_url = sites_data_dict[site]["server_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + characters = string.ascii_lowercase + string.digits + string.ascii_uppercase + file_id = ''.join(random.choice(characters) for i in range(10)) + access_code = ''.join(random.choice(characters) for i in range(7)) + + if proxy_list == []: + server_req = requests.get(url=server_url, headers={"User-Agent": ua}) + else: + server_req = requests.get(url=server_url, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)) + + server_response = server_req.json() + print(server_response) + upload_url = server_response.get("data", {}).get("url", "") + print(upload_url) + token = server_response.get("data", {}).get("serverAccessToken", "") + print(token) + + if calc_size == "OK": + data = { + "serverAccessToken": token + } + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + if proxy_list == []: + raw_req = requests.post(url=upload_url, data=data, files=form_data, headers={"User-Agent": ua}) + else: + raw_req = requests.post(url=upload_url, files=form_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)) + + if raw_req.status_code == 200: + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/letsupload.py b/modules/deprecated/letsupload.py index 0f991af..c4a6e77 100644 --- a/modules/deprecated/letsupload.py +++ b/modules/deprecated/letsupload.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "LetsUpload" - -""" -Last Checked 24/03/2024 -""" - -""" - -"LetsUpload": { - "apiKey": False, - "url": "https://api.letsupload.cc/upload", - "api_url": "https://api.letsupload.cc/", - "download_url_base": "https://letsupload.cc/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class LetsUpload: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "LetsUpload" + +""" +Last Checked 24/03/2024 +""" + +""" + +"LetsUpload": { + "apiKey": False, + "url": "https://api.letsupload.cc/upload", + "api_url": "https://api.letsupload.cc/", + "download_url_base": "https://letsupload.cc/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class LetsUpload: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/lolabits.py b/modules/deprecated/lolabits.py index 242a914..bfa9cc6 100644 --- a/modules/deprecated/lolabits.py +++ b/modules/deprecated/lolabits.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "LolaBits" - -""" -Last Checked 24/03/2024 -""" - -""" - -"LolaBits": { - "apiKey": False, - "url": "https://api.lolabits.se/upload", - "api_url": "https://api.lolabits.se/", - "download_url_base": "https://lolabits.se/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class LolaBits: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "LolaBits" + +""" +Last Checked 24/03/2024 +""" + +""" + +"LolaBits": { + "apiKey": False, + "url": "https://api.lolabits.se/upload", + "api_url": "https://api.lolabits.se/", + "download_url_base": "https://lolabits.se/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class LolaBits: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/megaupload.py b/modules/deprecated/megaupload.py index ca61646..cc7fca5 100644 --- a/modules/deprecated/megaupload.py +++ b/modules/deprecated/megaupload.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "MegaUpload" - -""" -Last Checked 24/03/2024 -""" - -""" - -"MegaUpload": { - "apiKey": False, - "url": "https://api.megaupload.nz/upload", - "api_url": "https://api.megaupload.nz/", - "download_url_base": "https://megaupload.nz/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class MegaUpload: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "MegaUpload" + +""" +Last Checked 24/03/2024 +""" + +""" + +"MegaUpload": { + "apiKey": False, + "url": "https://api.megaupload.nz/upload", + "api_url": "https://api.megaupload.nz/", + "download_url_base": "https://megaupload.nz/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class MegaUpload: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/myfile.py b/modules/deprecated/myfile.py index ac9a5ee..aabc1ac 100644 --- a/modules/deprecated/myfile.py +++ b/modules/deprecated/myfile.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "MyFile" - -""" -Last Checked 24/03/2024 -""" - -""" - -"MyFile": { - "apiKey": False, - "url": "https://api.myfile.is/upload", - "api_url": "https://api.myfile.is/", - "download_url_base": "https://myfile.is/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class MyFile: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "MyFile" + +""" +Last Checked 24/03/2024 +""" + +""" + +"MyFile": { + "apiKey": False, + "url": "https://api.myfile.is/upload", + "api_url": "https://api.myfile.is/", + "download_url_base": "https://myfile.is/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class MyFile: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/nitrofile.py b/modules/deprecated/nitrofile.py index 009e21c..1626db6 100644 --- a/modules/deprecated/nitrofile.py +++ b/modules/deprecated/nitrofile.py @@ -1,64 +1,64 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "NitroFile" - -""" -Last Checked 24/03/2024 -""" - -""" - -"NitroFile": { - "apiKey": False, - "url": "https://nitrofile.cc/api/v1/upload", - "api_url": "https://nitrofile.cc/", - "download_url_base": "https://nitrofile.cc/", - "size_limit": 7, - "size_unit": "GB" -}, - -""" - -class NitroFile: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, stream=True) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "NitroFile" + +""" +Last Checked 24/03/2024 +""" + +""" + +"NitroFile": { + "apiKey": False, + "url": "https://nitrofile.cc/api/v1/upload", + "api_url": "https://nitrofile.cc/", + "download_url_base": "https://nitrofile.cc/", + "size_limit": 7, + "size_unit": "GB" +}, + +""" + +class NitroFile: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, stream=True) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/openload.py b/modules/deprecated/openload.py index bf5563d..89cfcfd 100644 --- a/modules/deprecated/openload.py +++ b/modules/deprecated/openload.py @@ -1,54 +1,54 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "OpenLoad" - -""" -Last Checked 24/03/2024 -""" - -""" -"OpenLoad": { - "apiKey": False, - "url": "https://api.openload.cc/upload", - "api_url": "https://api.openload.cc/", - "download_url_base": "https://openload.cc/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -} - -""" - -class OpenLoad: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "OpenLoad" + +""" +Last Checked 24/03/2024 +""" + +""" +"OpenLoad": { + "apiKey": False, + "url": "https://api.openload.cc/upload", + "api_url": "https://api.openload.cc/", + "download_url_base": "https://openload.cc/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +} + +""" + +class OpenLoad: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/rapidshare.py b/modules/deprecated/rapidshare.py index 24f30dd..e0a017f 100644 --- a/modules/deprecated/rapidshare.py +++ b/modules/deprecated/rapidshare.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "RapidShare" - -""" -Last Checked 24/03/2024 -""" - -""" - -"RapidShare": { - "apiKey": False, - "url": "https://api.rapidshare.nu/upload", - "api_url": "https://api.rapidshare.nu/", - "download_url_base": "https://rapidshare.nu/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class RapidShare: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "RapidShare" + +""" +Last Checked 24/03/2024 +""" + +""" + +"RapidShare": { + "apiKey": False, + "url": "https://api.rapidshare.nu/upload", + "api_url": "https://api.rapidshare.nu/", + "download_url_base": "https://rapidshare.nu/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class RapidShare: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/shareonline.py b/modules/deprecated/shareonline.py index f297a7c..75f2ceb 100644 --- a/modules/deprecated/shareonline.py +++ b/modules/deprecated/shareonline.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "ShareOnline" - -""" -Last Checked 24/03/2024 -""" - -""" - -"ShareOnline": { - "apiKey": False, - "url": "https://api.share-online.is/upload", - "api_url": "https://api.share-online.is/", - "download_url_base": "https://share-online.is/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class ShareOnline: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "ShareOnline" + +""" +Last Checked 24/03/2024 +""" + +""" + +"ShareOnline": { + "apiKey": False, + "url": "https://api.share-online.is/upload", + "api_url": "https://api.share-online.is/", + "download_url_base": "https://share-online.is/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class ShareOnline: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/udrop.py b/modules/deprecated/udrop.py index 10ab045..3b2551a 100644 --- a/modules/deprecated/udrop.py +++ b/modules/deprecated/udrop.py @@ -1,117 +1,117 @@ -import requests -import os -import random -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "uDrop" - -""" -For some weird unholy reason this script stopped working. it works fine in insonmnia tho? what the fuck.. -""" - -""" - - "uDrop": { - "apiKey": False, - "url": "https://udrop.com/ajax/file_upload_handler", - "api_url": "https://udrop.com/", - "download_url_base": "https://udrop.com/", - "size_limit": 10, - "size_unit": "GB" - }, - -""" - -class uDrop: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - # Assemble Size Limit e.g. 5 GB - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - chunk_size = 500000000 # 500 MB - chunk_position_before = -1 - chunk_position_after = -1 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - chunk_length = len(chunk_data) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - chunk_position_before = chunk_position_after + 1 - chunk_position_after = chunk_position_before + chunk_length - 1 - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-Requested-With": "XMLHttpRequest", - "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" - } - - upload_data = { - "maxChunkSize": chunk_size, - "uploadSource": "file_manager", - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Get the upload URL from the site data dictionary - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url="https://udrop.com/ajax/file_upload_handler", data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - download_url = raw_req[0].get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "uDrop" + +""" +For some weird unholy reason this script stopped working. it works fine in insonmnia tho? what the fuck.. +""" + +""" + + "uDrop": { + "apiKey": False, + "url": "https://udrop.com/ajax/file_upload_handler", + "api_url": "https://udrop.com/", + "download_url_base": "https://udrop.com/", + "size_limit": 10, + "size_unit": "GB" + }, + +""" + +class uDrop: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + # Assemble Size Limit e.g. 5 GB + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + chunk_size = 500000000 # 500 MB + chunk_position_before = -1 + chunk_position_after = -1 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + chunk_length = len(chunk_data) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + chunk_position_before = chunk_position_after + 1 + chunk_position_after = chunk_position_before + chunk_length - 1 + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-Requested-With": "XMLHttpRequest", + "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" + } + + upload_data = { + "maxChunkSize": chunk_size, + "uploadSource": "file_manager", + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Get the upload URL from the site data dictionary + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url="https://udrop.com/ajax/file_upload_handler", data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + download_url = raw_req[0].get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/deprecated/up2share.py b/modules/deprecated/up2share.py index e18663c..a1b0c3c 100644 --- a/modules/deprecated/up2share.py +++ b/modules/deprecated/up2share.py @@ -1,130 +1,130 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Up2Share" - -""" -Last Checked 24/03/2024 -""" - -""" - -"Up2Share": { - "apiKey": False, - "url": "https://up2sha.re/upload", - "api_url": "https://up2sha.re/", - "download_url_base": "https://up2sha.re/file?f=", - "size_limit": 1, - "size_unit": "GB" -}, - -""" - -""" -This file is marked as deprecated due to a 400 error when uploading files after chunk 0. -I can't figure out why it does that - -Full Error: - -{ - "error": { - "message": "Something went wrong. Please try again." - } -} - -""" - -class Up2Share: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - # Define the maximum chunk size (in bytes) - max_chunk_size = round(75.976 * 1024 * 1024) # 75.976 MB in bytes - - # Initialize the upload key - upload_key = None - - # Calculate the expected number of chunks - expected_chunks = (file_size + max_chunk_size - 1) // max_chunk_size - print("expected chunks: " + str(expected_chunks)) - - # Open the file in binary mode for reading - with open(file, 'rb') as file: - chunk_number = 0 - - while True: - # Read a chunk of the file - chunk = file.read(max_chunk_size) - - # If the chunk is empty, we've reached the end of the file - if not chunk: - break - - # Create a dictionary with the file content for multipart encoding - files = { - 'file': ('blob', chunk, 'application/octet-stream'), - 'chunk': (None, str(chunk_number)), - 'chunks': (None, str(expected_chunks)), # Include the expected number of chunks - 'clientFilename': (None, file_name), - 'filesize': (None, str(file_size)) - } - - # If we have an upload key, add it to the form data - if upload_key: - files['uploadKey'] = (None, upload_key) - - # Make a POST request to upload the chunk using multipart encoding - if proxy_list == []: - raw_req = requests.post(url=upload_url, files=files, headers={"User-Agent": ua}) - else: - raw_req = requests.post(url=upload_url, files=files, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)) - - print(raw_req.text) - - # Handle the response - if raw_req.status_code == 308: - print(f"Chunk {chunk_number} uploaded successfully") - - # Extract the uploadKey from the JSON response using the get() method - response_data = raw_req.json() - upload_key = response_data.get('result', {}).get('uploadKey') - print(upload_key) - else: - print(f"Failed to upload chunk {chunk_number}. Status code: {raw_req.status_code}") - - chunk_number += 1 - - # Close the file when done - file.close() - - response = raw_req.json() - file_url = response.get("result", {}).get("public_url", "") - - if raw_req.status_code == 201: - return {"status": "ok", "file_name": file_name, "file_url": file_url} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Up2Share" + +""" +Last Checked 24/03/2024 +""" + +""" + +"Up2Share": { + "apiKey": False, + "url": "https://up2sha.re/upload", + "api_url": "https://up2sha.re/", + "download_url_base": "https://up2sha.re/file?f=", + "size_limit": 1, + "size_unit": "GB" +}, + +""" + +""" +This file is marked as deprecated due to a 400 error when uploading files after chunk 0. +I can't figure out why it does that + +Full Error: + +{ + "error": { + "message": "Something went wrong. Please try again." + } +} + +""" + +class Up2Share: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + # Define the maximum chunk size (in bytes) + max_chunk_size = round(75.976 * 1024 * 1024) # 75.976 MB in bytes + + # Initialize the upload key + upload_key = None + + # Calculate the expected number of chunks + expected_chunks = (file_size + max_chunk_size - 1) // max_chunk_size + print("expected chunks: " + str(expected_chunks)) + + # Open the file in binary mode for reading + with open(file, 'rb') as file: + chunk_number = 0 + + while True: + # Read a chunk of the file + chunk = file.read(max_chunk_size) + + # If the chunk is empty, we've reached the end of the file + if not chunk: + break + + # Create a dictionary with the file content for multipart encoding + files = { + 'file': ('blob', chunk, 'application/octet-stream'), + 'chunk': (None, str(chunk_number)), + 'chunks': (None, str(expected_chunks)), # Include the expected number of chunks + 'clientFilename': (None, file_name), + 'filesize': (None, str(file_size)) + } + + # If we have an upload key, add it to the form data + if upload_key: + files['uploadKey'] = (None, upload_key) + + # Make a POST request to upload the chunk using multipart encoding + if proxy_list == []: + raw_req = requests.post(url=upload_url, files=files, headers={"User-Agent": ua}) + else: + raw_req = requests.post(url=upload_url, files=files, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)) + + print(raw_req.text) + + # Handle the response + if raw_req.status_code == 308: + print(f"Chunk {chunk_number} uploaded successfully") + + # Extract the uploadKey from the JSON response using the get() method + response_data = raw_req.json() + upload_key = response_data.get('result', {}).get('uploadKey') + print(upload_key) + else: + print(f"Failed to upload chunk {chunk_number}. Status code: {raw_req.status_code}") + + chunk_number += 1 + + # Close the file when done + file.close() + + response = raw_req.json() + file_url = response.get("result", {}).get("public_url", "") + + if raw_req.status_code == 201: + return {"status": "ok", "file_name": file_name, "file_url": file_url} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/upvid.py b/modules/deprecated/upvid.py index 5c07e6f..c5d405e 100644 --- a/modules/deprecated/upvid.py +++ b/modules/deprecated/upvid.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "UpVid" - -""" -Last Checked 24/03/2024 -""" - -""" - -"UpVid": { - "apiKey": False, - "url": "https://api.upvid.cc/upload", - "api_url": "https://api.upvid.cc/", - "download_url_base": "https://upvid.cc/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class UpVid: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "UpVid" + +""" +Last Checked 24/03/2024 +""" + +""" + +"UpVid": { + "apiKey": False, + "url": "https://api.upvid.cc/upload", + "api_url": "https://api.upvid.cc/", + "download_url_base": "https://upvid.cc/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class UpVid: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/vshare.py b/modules/deprecated/vshare.py index 82e1073..2b6f16c 100644 --- a/modules/deprecated/vshare.py +++ b/modules/deprecated/vshare.py @@ -1,55 +1,55 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "vShare" - -""" -Last Checked 24/03/2024 -""" - -""" - -"vShare": { - "apiKey": False, - "url": "https://api.vshare.is/upload", - "api_url": "https://api.vshare.is/", - "download_url_base": "https://vshare.is/", - "size_limit_human": 20, - "size_limit_bytes": 21474836480, - "size_unit": "GB" -}, - -""" - -class vShare: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - if proxy_list == []: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() - else: - req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() - return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "vShare" + +""" +Last Checked 24/03/2024 +""" + +""" + +"vShare": { + "apiKey": False, + "url": "https://api.vshare.is/upload", + "api_url": "https://api.vshare.is/", + "download_url_base": "https://vshare.is/", + "size_limit_human": 20, + "size_limit_bytes": 21474836480, + "size_unit": "GB" +}, + +""" + +class vShare: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + if proxy_list == []: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}).json() + else: + req = requests.post(url=upload_url, files=files_data, headers={"User-Agent": ua}, proxies=random.choice(proxy_list)).json() + return {"status": "ok", "file_name": file_name, "file_url": req.get("data").get("file").get("url").get("short")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/deprecated/wetransfer.py b/modules/deprecated/wetransfer.py index 83c7566..b8cd70d 100644 --- a/modules/deprecated/wetransfer.py +++ b/modules/deprecated/wetransfer.py @@ -1,189 +1,189 @@ -import requests -import os -import random -import string -import hashlib -from time import sleep - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from .logger import Logger - -from main import DEBUG - -site = "WeTransfer" - -""" -Last Checked 24/03/2024 -""" - -""" - -"WeTransfer": { - "apiKey": False, - "url": "{server}", - "api_url": "https://wetransfer.com/", - "download_url_base": "https://wetransfer.com/downloads/{file_id}/{security_hash}", - "announce_url": "https://wetransfer.com/api/v4/transfers/link", - "initialize_url": "https://storm-eu-west-1.wetransfer.net/api/v2/batch/preflight", - "prepare_blocks_url": "https://storm-eu-west-1.wetransfer.net/api/v2/blocks", - "check_status_url": "https://storm-eu-west-1.wetransfer.net/api/v2/batch", - "finalize_url": "https://wetransfer.com/api/v4/transfers/{file_id}/finalize", - "size_limit": 2, - "size_unit": "GB" -}, - -""" - -class WeTransfer: - - def Uploader(file, proxy_list, user_agents, api_keys): - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - base_url = sites_data_dict[site]["download_url_base"] - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '') if len(file_name) > 240 else file_name # Changed from 255 to 15 as an additional safety net. - file_name_normal = file_name - file_name = file_name.replace(" ", "_") - - # Announce the upload to the server - announce_url = sites_data_dict[site]["announce_url"] - announce_data = { - "message": "Uploaded using Mul-Tor on Github!", - "display_name": file_name, - "ui_language": "en", - "files": [ - { - "name": file_name, - "size": file_size, - "item_type": "file" - } - ] - } - headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json"} - announce = requests.post(url=announce_url, json=announce_data, headers=headers) - - # Extract all needed data - announce_json = announce.json() - file_id = announce_json.get("id", "") - short_url = announce_json.get("shortened_url", "") - security_hash = announce_json.get("security_hash", "") - storm_upload_token = announce_json.get("storm_upload_token", "") - - # Check if everything is okay - initialize_url = sites_data_dict[site]["initialize_url"] - initialize_data = {"items": [ - { - "path": file_name, - "item_type": "file", - "blocks": [{"content_length": file_size}] - } - ]} - headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {storm_upload_token}"} - preflight = requests.post(url=initialize_url, json=initialize_data, headers=headers) - - # Requests upload server. It also needs an md5 hash - - # Create an MD5 hash object - md5_hash = hashlib.md5() - - # Open the file in binary mode and read it in chunks - with open(file, 'rb') as md5_file: - while True: - # Read a chunk of data from the file - chunk = md5_file.read(8192) # You can adjust the chunk size as needed - - # If the chunk is empty, we've reached the end of the file - if not chunk: - break - - # Update the hash object with the chunk of data - md5_hash.update(chunk) - - # Get the hexadecimal representation of the MD5 hash - md5_hex = md5_hash.hexdigest() - - prepare_blocks_url = sites_data_dict[site]["prepare_blocks_url"] - blocks_data = {"blocks": [ - { - "content_length": file_size, - "content_md5_hex": f"{str(md5_hex)}" - } - ]} - headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {storm_upload_token}"} - blocks = requests.post(url=prepare_blocks_url, json=blocks_data, headers=headers) - - # Extract all needed data again - blocks_json = blocks.json() - server_url = blocks_json.get("data", {}).get("blocks", [])[0].get("presigned_put_url", "") - block_id = blocks_json.get("data", {}).get("blocks", [])[0].get("block_id", "") - print(block_id) - server_md5 = blocks_json.get("data", {}).get("blocks", [])[0].get("put_request_headers", {}).get("Content-MD5", "") - x_uploader = blocks_json.get("data", {}).get("blocks", [])[0].get("put_request_headers", {}).get("X-Uploader", "") - - headers = { - "Content-Type": "application/octet-stream", - "User-Agent": ua, - "X-Uploader": x_uploader, - "Content-MD5": server_md5 - } - - - files = {'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream')} - if proxy_list == []: - req = requests.put(url=server_url, files=files, headers=headers) - else: - req = requests.put(url=server_url, files=files, headers=headers, proxies=random.choice(proxy_list)) - - - check_status_url = sites_data_dict[site]["check_status_url"] - check_data = {"items": [ - { - "path": file_name, - "item_type": "file", - "block_ids": [block_id] - } - ]} - - headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {storm_upload_token}"} - check = requests.post(url=check_status_url, json=check_data, headers=headers) - print(check.text) - - check_json = check.json() - - while True: - if check_json.get("ok", "") == False: - print("Rechecking") - sleep(15) - check = requests.post(url=check_status_url, json=check_data, headers=headers) - check_json = check.json() - print(check.text) - else: - print("should be good now") - break - - check_json = check.json() - final_id = check_json.get("data", {}).get("batch_after_mutation", {}).get("foreign_id", "") - - finalize_url = sites_data_dict[site]["finalize_url"].format(file_id=final_id) - headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json"} - finalize = requests.put(url=initialize_url, json=check_data, headers=headers) - - finalize_json = finalize.json() - - file_id = finalize_json.get("id", "") - state = finalize_json.get("state", "") - security_hash = finalize_json.get("security_hash", "") - - download_url = sites_data_dict[site]["download_url_base"].format(file_id=final_id, security_hash=security_hash) - - if state == "downloadable": - return {"status": "ok", "file_name": file_name_normal, "file_url": download_url} - else: - raise Exception("Fuck me it failed somehow") - - except Exception as e: +import requests +import os +import random +import string +import hashlib +from time import sleep + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from .logger import Logger + +from main import DEBUG + +site = "WeTransfer" + +""" +Last Checked 24/03/2024 +""" + +""" + +"WeTransfer": { + "apiKey": False, + "url": "{server}", + "api_url": "https://wetransfer.com/", + "download_url_base": "https://wetransfer.com/downloads/{file_id}/{security_hash}", + "announce_url": "https://wetransfer.com/api/v4/transfers/link", + "initialize_url": "https://storm-eu-west-1.wetransfer.net/api/v2/batch/preflight", + "prepare_blocks_url": "https://storm-eu-west-1.wetransfer.net/api/v2/blocks", + "check_status_url": "https://storm-eu-west-1.wetransfer.net/api/v2/batch", + "finalize_url": "https://wetransfer.com/api/v4/transfers/{file_id}/finalize", + "size_limit": 2, + "size_unit": "GB" +}, + +""" + +class WeTransfer: + + def Uploader(file, proxy_list, user_agents, api_keys): + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + base_url = sites_data_dict[site]["download_url_base"] + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '') if len(file_name) > 240 else file_name # Changed from 255 to 15 as an additional safety net. + file_name_normal = file_name + file_name = file_name.replace(" ", "_") + + # Announce the upload to the server + announce_url = sites_data_dict[site]["announce_url"] + announce_data = { + "message": "Uploaded using Mul-Tor on Github!", + "display_name": file_name, + "ui_language": "en", + "files": [ + { + "name": file_name, + "size": file_size, + "item_type": "file" + } + ] + } + headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json"} + announce = requests.post(url=announce_url, json=announce_data, headers=headers) + + # Extract all needed data + announce_json = announce.json() + file_id = announce_json.get("id", "") + short_url = announce_json.get("shortened_url", "") + security_hash = announce_json.get("security_hash", "") + storm_upload_token = announce_json.get("storm_upload_token", "") + + # Check if everything is okay + initialize_url = sites_data_dict[site]["initialize_url"] + initialize_data = {"items": [ + { + "path": file_name, + "item_type": "file", + "blocks": [{"content_length": file_size}] + } + ]} + headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {storm_upload_token}"} + preflight = requests.post(url=initialize_url, json=initialize_data, headers=headers) + + # Requests upload server. It also needs an md5 hash + + # Create an MD5 hash object + md5_hash = hashlib.md5() + + # Open the file in binary mode and read it in chunks + with open(file, 'rb') as md5_file: + while True: + # Read a chunk of data from the file + chunk = md5_file.read(8192) # You can adjust the chunk size as needed + + # If the chunk is empty, we've reached the end of the file + if not chunk: + break + + # Update the hash object with the chunk of data + md5_hash.update(chunk) + + # Get the hexadecimal representation of the MD5 hash + md5_hex = md5_hash.hexdigest() + + prepare_blocks_url = sites_data_dict[site]["prepare_blocks_url"] + blocks_data = {"blocks": [ + { + "content_length": file_size, + "content_md5_hex": f"{str(md5_hex)}" + } + ]} + headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {storm_upload_token}"} + blocks = requests.post(url=prepare_blocks_url, json=blocks_data, headers=headers) + + # Extract all needed data again + blocks_json = blocks.json() + server_url = blocks_json.get("data", {}).get("blocks", [])[0].get("presigned_put_url", "") + block_id = blocks_json.get("data", {}).get("blocks", [])[0].get("block_id", "") + print(block_id) + server_md5 = blocks_json.get("data", {}).get("blocks", [])[0].get("put_request_headers", {}).get("Content-MD5", "") + x_uploader = blocks_json.get("data", {}).get("blocks", [])[0].get("put_request_headers", {}).get("X-Uploader", "") + + headers = { + "Content-Type": "application/octet-stream", + "User-Agent": ua, + "X-Uploader": x_uploader, + "Content-MD5": server_md5 + } + + + files = {'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream')} + if proxy_list == []: + req = requests.put(url=server_url, files=files, headers=headers) + else: + req = requests.put(url=server_url, files=files, headers=headers, proxies=random.choice(proxy_list)) + + + check_status_url = sites_data_dict[site]["check_status_url"] + check_data = {"items": [ + { + "path": file_name, + "item_type": "file", + "block_ids": [block_id] + } + ]} + + headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json", "Authorization": f"Bearer {storm_upload_token}"} + check = requests.post(url=check_status_url, json=check_data, headers=headers) + print(check.text) + + check_json = check.json() + + while True: + if check_json.get("ok", "") == False: + print("Rechecking") + sleep(15) + check = requests.post(url=check_status_url, json=check_data, headers=headers) + check_json = check.json() + print(check.text) + else: + print("should be good now") + break + + check_json = check.json() + final_id = check_json.get("data", {}).get("batch_after_mutation", {}).get("foreign_id", "") + + finalize_url = sites_data_dict[site]["finalize_url"].format(file_id=final_id) + headers = {"User-Agent": ua, "Content-Type": "application/json", "Accept": "application/json"} + finalize = requests.put(url=initialize_url, json=check_data, headers=headers) + + finalize_json = finalize.json() + + file_id = finalize_json.get("id", "") + state = finalize_json.get("state", "") + security_hash = finalize_json.get("security_hash", "") + + download_url = sites_data_dict[site]["download_url_base"].format(file_id=final_id, security_hash=security_hash) + + if state == "downloadable": + return {"status": "ok", "file_name": file_name_normal, "file_url": download_url} + else: + raise Exception("Fuck me it failed somehow") + + except Exception as e: return {"status": "error", "file_name": file_name_normal, "exception": str(e), "extra": req} \ No newline at end of file diff --git a/modules/deprecated/yourfilestore.py b/modules/deprecated/yourfilestore.py index e4cbea8..b8da2f9 100644 --- a/modules/deprecated/yourfilestore.py +++ b/modules/deprecated/yourfilestore.py @@ -1,84 +1,84 @@ -import requests -import os -import random -import string -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -""" -Last Checked 24/03/2024 -""" - -""" - -"YourFileStore": { - "apiKey": False, - "url": "https://yourfilestore.com/upload", - "api_url": "https://yourfilestore.com/upload", - "download_url_base": "https://yourfilestore.com/download/", - "size_limit": 500, - "size_unit": "MB" -}, - -""" - -""" -This worked perfectly before but they changed something in the uploading system. -I tried to figure it out for half an hour or more but i was unable to figure it out. -It says "some error occured" and that's it. Uploading on the site works but it can't be recreated in insomnia. -Further Testing is needed. Maybe it can be fixed. -""" - -site = "YourFileStore" - -class YourFileStore: - - def Uploader(file, proxy_list, user_agents, api_keys): - req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - characters = string.ascii_lowercase + string.digits + string.ascii_uppercase - random_string = ''.join(random.choice(characters) for i in range(32)) - - # This site has problems with certain characters in file names - safe_file_name = os.path.basename(file).replace("(", ""). replace(")", "").replace("[", "").replace("]", "") - - form_data = { - 'UPLOAD_IDENTIFIER': random_string, - 'userfile': (safe_file_name, open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, stream=True) - - print(raw_req.text) - - url_pattern = r'https://yourfilestore\.com/download/\d+/[^"]+' - - match = re.search(url_pattern, raw_req.text) - download_url = match.group() - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +""" +Last Checked 24/03/2024 +""" + +""" + +"YourFileStore": { + "apiKey": False, + "url": "https://yourfilestore.com/upload", + "api_url": "https://yourfilestore.com/upload", + "download_url_base": "https://yourfilestore.com/download/", + "size_limit": 500, + "size_unit": "MB" +}, + +""" + +""" +This worked perfectly before but they changed something in the uploading system. +I tried to figure it out for half an hour or more but i was unable to figure it out. +It says "some error occured" and that's it. Uploading on the site works but it can't be recreated in insomnia. +Further Testing is needed. Maybe it can be fixed. +""" + +site = "YourFileStore" + +class YourFileStore: + + def Uploader(file, proxy_list, user_agents, api_keys): + req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + characters = string.ascii_lowercase + string.digits + string.ascii_uppercase + random_string = ''.join(random.choice(characters) for i in range(32)) + + # This site has problems with certain characters in file names + safe_file_name = os.path.basename(file).replace("(", ""). replace(")", "").replace("[", "").replace("]", "") + + form_data = { + 'UPLOAD_IDENTIFIER': random_string, + 'userfile': (safe_file_name, open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, stream=True) + + print(raw_req.text) + + url_pattern = r'https://yourfilestore\.com/download/\d+/[^"]+' + + match = re.search(url_pattern, raw_req.text) + download_url = match.group() + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/anontransfer.py b/modules/old_scripts/anontransfer.py index 0798e64..10aab7d 100644 --- a/modules/old_scripts/anontransfer.py +++ b/modules/old_scripts/anontransfer.py @@ -1,104 +1,104 @@ -import requests -import os -import random -import uuid - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "AnonTransfer" - -class AnonTransfer: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - download_url_base = sites_data_dict[site]["download_url_base"] - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - file_uuid = str(uuid.uuid4()) - - if calc_size == "OK": - - chunk_size = 52428800 # 52.4288 MB - total_chunks = (file_size + chunk_size - 1) // chunk_size - chunk_index = 0 - dzchunkbyteoffset = 0 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - upload_data = { - "dzuuid": file_uuid, - "dzchunkindex": chunk_index, - "dztotalfilesize": file_size, - "dzchunksize": chunk_size, - "dztotalchunkcount": total_chunks, - "dzchunkbyteoffset": dzchunkbyteoffset - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - chunk_index += 1 - dzchunkbyteoffset += chunk_size - - json_req = raw_req.json() - - name = json_req.get("name", "") - dir = json_req.get("dir", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": f"{download_url_base}{dir}/{name}"} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import uuid + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "AnonTransfer" + +class AnonTransfer: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + download_url_base = sites_data_dict[site]["download_url_base"] + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + file_uuid = str(uuid.uuid4()) + + if calc_size == "OK": + + chunk_size = 52428800 # 52.4288 MB + total_chunks = (file_size + chunk_size - 1) // chunk_size + chunk_index = 0 + dzchunkbyteoffset = 0 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + upload_data = { + "dzuuid": file_uuid, + "dzchunkindex": chunk_index, + "dztotalfilesize": file_size, + "dzchunksize": chunk_size, + "dztotalchunkcount": total_chunks, + "dzchunkbyteoffset": dzchunkbyteoffset + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + chunk_index += 1 + dzchunkbyteoffset += chunk_size + + json_req = raw_req.json() + + name = json_req.get("name", "") + dir = json_req.get("dir", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": f"{download_url_base}{dir}/{name}"} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/anonymfile.py b/modules/old_scripts/anonymfile.py index e40ae25..09e2176 100644 --- a/modules/old_scripts/anonymfile.py +++ b/modules/old_scripts/anonymfile.py @@ -1,77 +1,77 @@ -import requests -import os -import random -import string -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Anonymfile" - -class Anonymfile: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - normal_url = sites_data_dict[site]["api_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - download_url_base = sites_data_dict[site]["download_url_base"] - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) - - csrf_token_match = re.search(r'', raw_req.text) - - # Check if the match was found - if csrf_token_match: - csrf_token = csrf_token_match.group(1) - else: - csrf_token = False - - x_csrf_token = raw_req.cookies.get("XSRF-TOKEN", False) - session = raw_req.cookies.get("anonymfile_session", False) - - if csrf_token in (False, "") or x_csrf_token in (False, "") or session in (False, ""): - raise Exception("Failed to get CSRF Tokens. Report this!") - - - if calc_size == "OK": - - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-CSRF-TOKEN": csrf_token, - "Cookie": f"XSRF-TOKEN={x_csrf_token}; anonymfile_session={session}" - } - - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if raw_req.status_code != 200: - raise Exception(f"Failed to upload file. Status Code {raw_req.status_code}. Report this!") - - download_url = download_url_base + raw_req.text - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Anonymfile" + +class Anonymfile: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + normal_url = sites_data_dict[site]["api_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + download_url_base = sites_data_dict[site]["download_url_base"] + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) + + csrf_token_match = re.search(r'', raw_req.text) + + # Check if the match was found + if csrf_token_match: + csrf_token = csrf_token_match.group(1) + else: + csrf_token = False + + x_csrf_token = raw_req.cookies.get("XSRF-TOKEN", False) + session = raw_req.cookies.get("anonymfile_session", False) + + if csrf_token in (False, "") or x_csrf_token in (False, "") or session in (False, ""): + raise Exception("Failed to get CSRF Tokens. Report this!") + + + if calc_size == "OK": + + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-CSRF-TOKEN": csrf_token, + "Cookie": f"XSRF-TOKEN={x_csrf_token}; anonymfile_session={session}" + } + + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if raw_req.status_code != 200: + raise Exception(f"Failed to upload file. Status Code {raw_req.status_code}. Report this!") + + download_url = download_url_base + raw_req.text + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/bowfile.py b/modules/old_scripts/bowfile.py index 8145191..ad6ac63 100644 --- a/modules/old_scripts/bowfile.py +++ b/modules/old_scripts/bowfile.py @@ -1,77 +1,77 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "BowFile" - -class BowFile: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - auth_url = sites_data_dict[site]["authorize_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - api_key1 = api_keys.get("apiKey1", False) - api_key2 = api_keys.get("apiKey2", False) - - if api_key1 in (False, "") or api_key2 in (False, ""): - raise Exception("Missing API Credentials?") - - if calc_size == "OK": - - auth_data = { - "key1": api_key1, - "key2": api_key2 - } - - raw_auth = requests.post(url=auth_url, data=auth_data, headers=headers, proxies=proxies, timeout=300) - - auth_resp = raw_auth.json() - access_token = auth_resp.get("data", {}).get("access_token", "") - account_id = auth_resp.get("data", {}).get("account_id", "") - - status = auth_resp.get("_status", "") - - if status != "success": - raise Exception("Auth Failed. Invalid API Keys?") - - - - form_data = { - 'access_token': access_token, - 'account_id': account_id - } - - file_data = { - 'upload_file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, data=form_data, files=file_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - response = raw_req.json() - download_url = response.get("data", [])[0].get("url", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "BowFile" + +class BowFile: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + auth_url = sites_data_dict[site]["authorize_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + api_key1 = api_keys.get("apiKey1", False) + api_key2 = api_keys.get("apiKey2", False) + + if api_key1 in (False, "") or api_key2 in (False, ""): + raise Exception("Missing API Credentials?") + + if calc_size == "OK": + + auth_data = { + "key1": api_key1, + "key2": api_key2 + } + + raw_auth = requests.post(url=auth_url, data=auth_data, headers=headers, proxies=proxies, timeout=300) + + auth_resp = raw_auth.json() + access_token = auth_resp.get("data", {}).get("access_token", "") + account_id = auth_resp.get("data", {}).get("account_id", "") + + status = auth_resp.get("_status", "") + + if status != "success": + raise Exception("Auth Failed. Invalid API Keys?") + + + + form_data = { + 'access_token': access_token, + 'account_id': account_id + } + + file_data = { + 'upload_file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, data=form_data, files=file_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + response = raw_req.json() + download_url = response.get("data", [])[0].get("url", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/catbox.py b/modules/old_scripts/catbox.py index 9179caf..b294da7 100644 --- a/modules/old_scripts/catbox.py +++ b/modules/old_scripts/catbox.py @@ -1,78 +1,78 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Catbox" - -class Catbox: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - upload_data = { - "reqtype": "fileupload" - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'fileToUpload': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if download_url_base in raw_req.text: - download_url = raw_req.text - else: - raise Exception("Upload somehow failed. Please report this!") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Catbox" + +class Catbox: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + upload_data = { + "reqtype": "fileupload" + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'fileToUpload': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if download_url_base in raw_req.text: + download_url = raw_req.text + else: + raise Exception("Upload somehow failed. Please report this!") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/clicknupload.py b/modules/old_scripts/clicknupload.py index 598464d..9e168ab 100644 --- a/modules/old_scripts/clicknupload.py +++ b/modules/old_scripts/clicknupload.py @@ -1,91 +1,91 @@ -import requests -import os -import random -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "ClicknUpload" - -class ClicknUpload: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - # Get the upload server - normal_url = sites_data_dict[site]["api_url"] - - raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300, stream=True) - - pattern = r'https://(\w+\.clicknupload\.net)/cgi-bin/upload\.cgi' - match = re.search(pattern, raw_req.text) - - if match: - upload_url = match.group(0) - else: - raise Exception("Server URL Missing. Report this!") - - if calc_size == "OK": - upload_data = { - "utype": "anon", - "file_descr": "Uploaded using Mul-Tor on GitHub!", - "file_public": 1, - "keepalive": 1 - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - req = raw_req.json() - - file_code = req[0].get("file_code", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_code} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "ClicknUpload" + +class ClicknUpload: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + # Get the upload server + normal_url = sites_data_dict[site]["api_url"] + + raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300, stream=True) + + pattern = r'https://(\w+\.clicknupload\.net)/cgi-bin/upload\.cgi' + match = re.search(pattern, raw_req.text) + + if match: + upload_url = match.group(0) + else: + raise Exception("Server URL Missing. Report this!") + + if calc_size == "OK": + upload_data = { + "utype": "anon", + "file_descr": "Uploaded using Mul-Tor on GitHub!", + "file_public": 1, + "keepalive": 1 + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + req = raw_req.json() + + file_code = req[0].get("file_code", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_code} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/cyberfile.py b/modules/old_scripts/cyberfile.py index 9473dc4..f5fa68a 100644 --- a/modules/old_scripts/cyberfile.py +++ b/modules/old_scripts/cyberfile.py @@ -1,100 +1,100 @@ -import requests -import os -import random -import uuid -import re -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "CyberFile" - -class CyberFile: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - chunk_size = 25000000 # 25 MB - chunk_position_before = -1 - chunk_position_after = -1 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - chunk_length = len(chunk_data) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - chunk_position_before = chunk_position_after + 1 - chunk_position_after = chunk_position_before + chunk_length - 1 - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json", - "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" - } - - upload_data = { - "maxChunkSize": chunk_size, - "uploadSource": "file_manager" - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Get the upload URL from the site data dictionary - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - download_url = raw_req[0].get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import uuid +import re +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "CyberFile" + +class CyberFile: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + chunk_size = 25000000 # 25 MB + chunk_position_before = -1 + chunk_position_after = -1 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + chunk_length = len(chunk_data) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + chunk_position_before = chunk_position_after + 1 + chunk_position_after = chunk_position_before + chunk_length - 1 + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json", + "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" + } + + upload_data = { + "maxChunkSize": chunk_size, + "uploadSource": "file_manager" + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Get the upload URL from the site data dictionary + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + download_url = raw_req[0].get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/delafil.py b/modules/old_scripts/delafil.py index 5363af5..512f93b 100644 --- a/modules/old_scripts/delafil.py +++ b/modules/old_scripts/delafil.py @@ -1,46 +1,46 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Delafil" - -class Delafil: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - if calc_size == "OK": - form_data = { - 'maxChunkSize': '2000000000', - 'files[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=1200, stream=True) - - raw_req = raw_req.json() - - return {"status": "ok", "file_name": file_name, "file_url": raw_req[0].get("url", "url went AWOL")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Delafil" + +class Delafil: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + if calc_size == "OK": + form_data = { + 'maxChunkSize': '2000000000', + 'files[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=1200, stream=True) + + raw_req = raw_req.json() + + return {"status": "ok", "file_name": file_name, "file_url": raw_req[0].get("url", "url went AWOL")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/doodrive.py b/modules/old_scripts/doodrive.py index 9b42502..64d5b75 100644 --- a/modules/old_scripts/doodrive.py +++ b/modules/old_scripts/doodrive.py @@ -1,136 +1,136 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "DooDrive" - -class DooDrive: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - raw_req = None - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Get the upload URL and size limit from the site data dictionary - initialize_url = sites_data_dict[site]["initialize_url"] - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - api_key = api_keys.get("apiKey", False) - api_token = api_keys.get("apiToken", False) - - if api_key in (False, "") or api_token in (False, ""): - raise Exception("Missing API Credentials?") - - if calc_size == "OK": - - # Prepare the form data for file upload - init_data = { - "api_key": api_key, - "api_token": api_token, - "file_name": file_name, - "file_size": file_size - } - # Send the upload request with the form data, headers, and proxies - init_req = requests.post(url=initialize_url, data=init_data, headers=headers, proxies=proxies, timeout=300) - - # Parse the response JSON and get the download URL - init_resp = init_req.json() - status = init_resp.get("status", "") - upload_token = init_resp.get("data", {}).get("token", "") - upload_url = init_resp.get("data", {}).get("chunk_url", "") - finalize_url = init_resp.get("data", {}).get("complete_url", "") - chunk_size = init_resp.get("data", {}).get("max_chunk_size", "") - - if status != "success": - raise Exception(f"Init status: {status}") - - total_chunks = (file_size + chunk_size - 1) // chunk_size - chunk_index = 0 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - upload_data = { - "api_key": api_key, - "api_token": api_token, - "token": upload_token, - "chunk_id": chunk_index, - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - req_resp = raw_req.json() - status = req_resp.get("status", "") - - chunk_index += 1 - - if status != "success": - raise Exception(f"Chunk upload failed: {status}") - - upload_data = { - "api_key": api_key, - "api_token": api_token, - "token": upload_token, - "chunks": total_chunks, - } - - raw_req = requests.post(url=finalize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) - - req_resp = raw_req.json() - download_url = req_resp.get("data", {}).get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "DooDrive" + +class DooDrive: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + raw_req = None + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Get the upload URL and size limit from the site data dictionary + initialize_url = sites_data_dict[site]["initialize_url"] + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + api_key = api_keys.get("apiKey", False) + api_token = api_keys.get("apiToken", False) + + if api_key in (False, "") or api_token in (False, ""): + raise Exception("Missing API Credentials?") + + if calc_size == "OK": + + # Prepare the form data for file upload + init_data = { + "api_key": api_key, + "api_token": api_token, + "file_name": file_name, + "file_size": file_size + } + # Send the upload request with the form data, headers, and proxies + init_req = requests.post(url=initialize_url, data=init_data, headers=headers, proxies=proxies, timeout=300) + + # Parse the response JSON and get the download URL + init_resp = init_req.json() + status = init_resp.get("status", "") + upload_token = init_resp.get("data", {}).get("token", "") + upload_url = init_resp.get("data", {}).get("chunk_url", "") + finalize_url = init_resp.get("data", {}).get("complete_url", "") + chunk_size = init_resp.get("data", {}).get("max_chunk_size", "") + + if status != "success": + raise Exception(f"Init status: {status}") + + total_chunks = (file_size + chunk_size - 1) // chunk_size + chunk_index = 0 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + upload_data = { + "api_key": api_key, + "api_token": api_token, + "token": upload_token, + "chunk_id": chunk_index, + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + req_resp = raw_req.json() + status = req_resp.get("status", "") + + chunk_index += 1 + + if status != "success": + raise Exception(f"Chunk upload failed: {status}") + + upload_data = { + "api_key": api_key, + "api_token": api_token, + "token": upload_token, + "chunks": total_chunks, + } + + raw_req = requests.post(url=finalize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) + + req_resp = raw_req.json() + download_url = req_resp.get("data", {}).get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/downloadgg.py b/modules/old_scripts/downloadgg.py index b204e12..9fa1c38 100644 --- a/modules/old_scripts/downloadgg.py +++ b/modules/old_scripts/downloadgg.py @@ -1,72 +1,72 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Download.gg" - -class Download_gg: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - # Prepare the json data to add extra data to the upload - form_data = { - 'file[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - file_id = raw_req.text - download_url = download_url_base + file_id.replace("&", "_") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Download.gg" + +class Download_gg: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + # Prepare the json data to add extra data to the upload + form_data = { + 'file[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + file_id = raw_req.text + download_url = download_url_base + file_id.replace("&", "_") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/easyupload.py b/modules/old_scripts/easyupload.py index c9c0b54..bee6911 100644 --- a/modules/old_scripts/easyupload.py +++ b/modules/old_scripts/easyupload.py @@ -1,143 +1,143 @@ -import requests -import os -import random -import uuid -import re -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "EasyUpload" -raw_req = "None :(" - -class EasyUpload: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Get the upload URL and size limit from the site data dictionary - initialize_url = sites_data_dict[site]["initialize_url"] - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - # This will get the actual upload URL from the website - normal_url = sites_data_dict[site]["api_url"] - - raw_req = requests.get(url=normal_url, headers={"User-Agent": ua}, proxies=proxies, timeout=300) - - pattern = r"https://upload\d+\.easyupload\.io/action\.php" - match = re.search(pattern, raw_req.text) - - if match: - upload_url = match.group(0) - else: - raise Exception("Server URL Missing. Report this!") - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json", - "Referer": "https://easyupload.io/", - } - - file_uuid = str(uuid.uuid4()) - - pattern = r'\{.*\}' - - if calc_size == "OK": - # Prepare the form data for file upload - init_data = { - "type": "validate_tuf", - "files[]": file_uuid - } - # Send the upload request with the form data, headers, and proxies - init_req = requests.post(url=initialize_url, data=init_data, headers=headers, proxies=proxies, timeout=300) - - # Parse the response JSON and get the download URL - match = re.search(pattern, init_req.text) - json_part = match.group() - init_resp = json.loads(json_part) - status = init_resp.get("status", "") - - if status != True: - raise Exception(f"Init status: {status}") - - chunk_size = 100000000 # 100 MB - total_chunks = (file_size + chunk_size - 1) // chunk_size - chunk_index = 0 - dzchunkbyteoffset = 0 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - upload_data = { - "dzuuid": file_uuid, - "dzchunkindex": chunk_index, - "dztotalfilesize": file_size, - "dzchunksize": chunk_size, - "dztotalchunkcount": total_chunks, - "dzchunkbyteoffset": dzchunkbyteoffset, - "type": "dropzone-multi-upload", - "expiration": "30" - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - chunk_index += 1 - dzchunkbyteoffset += chunk_size - - match = re.search(pattern, raw_req.text) - json_part = match.group() - upload_resp = json.loads(json_part) - - download_url = upload_resp.get("download_link", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import uuid +import re +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "EasyUpload" +raw_req = "None :(" + +class EasyUpload: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Get the upload URL and size limit from the site data dictionary + initialize_url = sites_data_dict[site]["initialize_url"] + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + # This will get the actual upload URL from the website + normal_url = sites_data_dict[site]["api_url"] + + raw_req = requests.get(url=normal_url, headers={"User-Agent": ua}, proxies=proxies, timeout=300) + + pattern = r"https://upload\d+\.easyupload\.io/action\.php" + match = re.search(pattern, raw_req.text) + + if match: + upload_url = match.group(0) + else: + raise Exception("Server URL Missing. Report this!") + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json", + "Referer": "https://easyupload.io/", + } + + file_uuid = str(uuid.uuid4()) + + pattern = r'\{.*\}' + + if calc_size == "OK": + # Prepare the form data for file upload + init_data = { + "type": "validate_tuf", + "files[]": file_uuid + } + # Send the upload request with the form data, headers, and proxies + init_req = requests.post(url=initialize_url, data=init_data, headers=headers, proxies=proxies, timeout=300) + + # Parse the response JSON and get the download URL + match = re.search(pattern, init_req.text) + json_part = match.group() + init_resp = json.loads(json_part) + status = init_resp.get("status", "") + + if status != True: + raise Exception(f"Init status: {status}") + + chunk_size = 100000000 # 100 MB + total_chunks = (file_size + chunk_size - 1) // chunk_size + chunk_index = 0 + dzchunkbyteoffset = 0 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + upload_data = { + "dzuuid": file_uuid, + "dzchunkindex": chunk_index, + "dztotalfilesize": file_size, + "dzchunksize": chunk_size, + "dztotalchunkcount": total_chunks, + "dzchunkbyteoffset": dzchunkbyteoffset, + "type": "dropzone-multi-upload", + "expiration": "30" + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + chunk_index += 1 + dzchunkbyteoffset += chunk_size + + match = re.search(pattern, raw_req.text) + json_part = match.group() + upload_resp = json.loads(json_part) + + download_url = upload_resp.get("download_link", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/fastupload.py b/modules/old_scripts/fastupload.py index 22b297f..87f544b 100644 --- a/modules/old_scripts/fastupload.py +++ b/modules/old_scripts/fastupload.py @@ -1,126 +1,126 @@ -import requests -import os -import random -import string -import re -import uuid - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Fastupload" - -class Fastupload: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - file_blacklist = [".exe", ".php", ".lnk", ".html", ".htm", ".phtml", ".shtm", ".js", ".bat", ".dll"] - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - normal_url = sites_data_dict[site]["api_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - download_url_base = sites_data_dict[site]["download_url_base"] - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) - - csrf_token_match = re.search(r'', raw_req.text) - - # Check if the match was found - if csrf_token_match: - csrf_token = csrf_token_match.group(1) - else: - csrf_token = False - - x_csrf_token = raw_req.cookies.get("XSRF-TOKEN", False) - session = raw_req.cookies.get("filebob_user_session", False) - - if csrf_token in (False, "") or x_csrf_token in (False, "") or session in (False, ""): - raise Exception("Failed to get CSRF Tokens. Report this!") - - _, file_extension = os.path.splitext(file_name) - - if calc_size == "OK": - if file_extension in file_blacklist: - raise Exception(f"File is blacklisted! {file_blacklist}") - - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-CSRF-TOKEN": csrf_token, - "Cookie": f"XSRF-TOKEN={x_csrf_token}; filebob_user_session={session}" - } - - chunk_size = 94371840 # 90 MB - total_chunks = (file_size + chunk_size - 1) // chunk_size - chunk_index = 0 - dzchunkbyteoffset = 0 - - file_uuid = str(uuid.uuid4()) - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-CSRF-TOKEN": csrf_token, - "Cookie": f"XSRF-TOKEN={x_csrf_token}; filebob_user_session={session}" - } - - upload_data = { - "dzuuid": file_uuid, - "dzchunkindex": chunk_index, - "dztotalfilesize": file_size, - "dzchunksize": chunk_size, - "dztotalchunkcount": total_chunks, - "dzchunkbyteoffset": dzchunkbyteoffset, - "size": file_size, - "upload_auto_delete": 0 - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - x_csrf_token = raw_req.cookies.get("XSRF-TOKEN", False) - session = raw_req.cookies.get("filebob_user_session", False) - - chunk_index += 1 - dzchunkbyteoffset += chunk_size - - if raw_req.status_code != 200: - raise Exception(f"Failed to upload file. Status Code {raw_req.status_code}. Report this!") - - req_json = raw_req.json() - - download_url = req_json.get("download_link", False) - - if download_url in (False, ""): - raise Exception("Failed to get download link. Report this!") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string +import re +import uuid + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Fastupload" + +class Fastupload: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + file_blacklist = [".exe", ".php", ".lnk", ".html", ".htm", ".phtml", ".shtm", ".js", ".bat", ".dll"] + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + normal_url = sites_data_dict[site]["api_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + download_url_base = sites_data_dict[site]["download_url_base"] + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) + + csrf_token_match = re.search(r'', raw_req.text) + + # Check if the match was found + if csrf_token_match: + csrf_token = csrf_token_match.group(1) + else: + csrf_token = False + + x_csrf_token = raw_req.cookies.get("XSRF-TOKEN", False) + session = raw_req.cookies.get("filebob_user_session", False) + + if csrf_token in (False, "") or x_csrf_token in (False, "") or session in (False, ""): + raise Exception("Failed to get CSRF Tokens. Report this!") + + _, file_extension = os.path.splitext(file_name) + + if calc_size == "OK": + if file_extension in file_blacklist: + raise Exception(f"File is blacklisted! {file_blacklist}") + + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-CSRF-TOKEN": csrf_token, + "Cookie": f"XSRF-TOKEN={x_csrf_token}; filebob_user_session={session}" + } + + chunk_size = 94371840 # 90 MB + total_chunks = (file_size + chunk_size - 1) // chunk_size + chunk_index = 0 + dzchunkbyteoffset = 0 + + file_uuid = str(uuid.uuid4()) + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-CSRF-TOKEN": csrf_token, + "Cookie": f"XSRF-TOKEN={x_csrf_token}; filebob_user_session={session}" + } + + upload_data = { + "dzuuid": file_uuid, + "dzchunkindex": chunk_index, + "dztotalfilesize": file_size, + "dzchunksize": chunk_size, + "dztotalchunkcount": total_chunks, + "dzchunkbyteoffset": dzchunkbyteoffset, + "size": file_size, + "upload_auto_delete": 0 + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + x_csrf_token = raw_req.cookies.get("XSRF-TOKEN", False) + session = raw_req.cookies.get("filebob_user_session", False) + + chunk_index += 1 + dzchunkbyteoffset += chunk_size + + if raw_req.status_code != 200: + raise Exception(f"Failed to upload file. Status Code {raw_req.status_code}. Report this!") + + req_json = raw_req.json() + + download_url = req_json.get("download_link", False) + + if download_url in (False, ""): + raise Exception("Failed to get download link. Report this!") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/filebin.py b/modules/old_scripts/filebin.py index c1a909b..eadf5a7 100644 --- a/modules/old_scripts/filebin.py +++ b/modules/old_scripts/filebin.py @@ -1,45 +1,45 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from .logger import Logger - -from main import DEBUG - -site = "FileBin" - -class FileBin: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - base_url = sites_data_dict[site]["download_url_base"] - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '') if len(file_name) > 240 else file_name # Changed from 255 to 15 as an additional safety net. - - characters = string.ascii_lowercase + string.digits - random_string = ''.join(random.choice(characters) for i in range(16)) - - rand_url = f"{base_url}{random_string}/{file_name}" - - headers = {"User-Agent": ua, "Content-Type": "application/octet-stream", "accept": "application/json"} - proxies = random.choice(proxy_list) if proxy_list else None - - with open(file, "rb") as file_upload: - raw_req = requests.post(url=rand_url, data=file_upload, headers=headers, proxies=proxies, timeout=300, stream=True) - file_upload.close() - if raw_req.status_code == 201: - return {"status": "ok", "file_name": file_name, "file_url": rand_url} - else: - raise Exception(raw_req.status_code) - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from .logger import Logger + +from main import DEBUG + +site = "FileBin" + +class FileBin: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + base_url = sites_data_dict[site]["download_url_base"] + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '') if len(file_name) > 240 else file_name # Changed from 255 to 15 as an additional safety net. + + characters = string.ascii_lowercase + string.digits + random_string = ''.join(random.choice(characters) for i in range(16)) + + rand_url = f"{base_url}{random_string}/{file_name}" + + headers = {"User-Agent": ua, "Content-Type": "application/octet-stream", "accept": "application/json"} + proxies = random.choice(proxy_list) if proxy_list else None + + with open(file, "rb") as file_upload: + raw_req = requests.post(url=rand_url, data=file_upload, headers=headers, proxies=proxies, timeout=300, stream=True) + file_upload.close() + if raw_req.status_code == 201: + return {"status": "ok", "file_name": file_name, "file_url": rand_url} + else: + raise Exception(raw_req.status_code) + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/fileio.py b/modules/old_scripts/fileio.py index beac83a..8832325 100644 --- a/modules/old_scripts/fileio.py +++ b/modules/old_scripts/fileio.py @@ -1,92 +1,92 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Fileio" - -class Fileio: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Get the upload URL and size limit from the site data dictionary - upload_url = sites_data_dict[site]["url"].format(file_name=file_name) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = {"User-Agent": ua} - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - # Prepare the form data for file upload - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - # Parse the response JSON and get the download URL - token = raw_req.headers.get("x-file-io-anonymous-access-token", "") - req = raw_req.json() - download_url = req.get("link", "") - file_id = req.get("key", "") - - # Prepare the json data to add extra data to the upload - json_data = { - "title": file_name, - "description":"Uploaded using Mul-Tor on GitHub!", - "expires":"2M" - } - - # Set the user agent header with additional Authorization header - headers = {"User-Agent": ua, "Authorization": f"Bearer {token}"} - - # Get the patch URL from the site data dictionary - patch_url = sites_data_dict[site]["patch_url"].format(file_id=file_id) - - # Send the patch request - patch_req = requests.patch(url=patch_url, json=json_data, headers=headers, proxies=proxies, timeout=300) - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Fileio" + +class Fileio: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Get the upload URL and size limit from the site data dictionary + upload_url = sites_data_dict[site]["url"].format(file_name=file_name) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = {"User-Agent": ua} + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + # Prepare the form data for file upload + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + # Parse the response JSON and get the download URL + token = raw_req.headers.get("x-file-io-anonymous-access-token", "") + req = raw_req.json() + download_url = req.get("link", "") + file_id = req.get("key", "") + + # Prepare the json data to add extra data to the upload + json_data = { + "title": file_name, + "description":"Uploaded using Mul-Tor on GitHub!", + "expires":"2M" + } + + # Set the user agent header with additional Authorization header + headers = {"User-Agent": ua, "Authorization": f"Bearer {token}"} + + # Get the patch URL from the site data dictionary + patch_url = sites_data_dict[site]["patch_url"].format(file_id=file_id) + + # Send the patch request + patch_req = requests.patch(url=patch_url, json=json_data, headers=headers, proxies=proxies, timeout=300) + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/files_dp_ua.py b/modules/old_scripts/files_dp_ua.py index c020b50..8139c12 100644 --- a/modules/old_scripts/files_dp_ua.py +++ b/modules/old_scripts/files_dp_ua.py @@ -1,56 +1,56 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Files.dp.ua" - -class Files_dp_ua: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - download_url_base = sites_data_dict[site]["download_url_base"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - characters = string.ascii_lowercase + string.digits + string.ascii_uppercase - file_id = ''.join(random.choice(characters) for i in range(10)) - access_code = ''.join(random.choice(characters) for i in range(7)) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - data = { - "idfile": file_id, - "accesscode": access_code - } - form_data = { - 'files[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if raw_req.status_code == 200: - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Files.dp.ua" + +class Files_dp_ua: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + download_url_base = sites_data_dict[site]["download_url_base"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + characters = string.ascii_lowercase + string.digits + string.ascii_uppercase + file_id = ''.join(random.choice(characters) for i in range(10)) + access_code = ''.join(random.choice(characters) for i in range(7)) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + data = { + "idfile": file_id, + "accesscode": access_code + } + form_data = { + 'files[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if raw_req.status_code == 200: + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/filesadmin.py b/modules/old_scripts/filesadmin.py index 942c9f9..cd3c6dd 100644 --- a/modules/old_scripts/filesadmin.py +++ b/modules/old_scripts/filesadmin.py @@ -1,101 +1,101 @@ -import requests -import os -import random -import uuid -import re -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Filesadmin" - -class Filesadmin: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - chunk_size = 100000000 # 93 MB - chunk_position_before = -1 - chunk_position_after = -1 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - chunk_length = len(chunk_data) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - chunk_position_before = chunk_position_after + 1 - chunk_position_after = chunk_position_before + chunk_length - 1 - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-Requested-With": "XMLHttpRequest", - "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" - } - - upload_data = { - "maxChunkSize": chunk_size, - "uploadSource": "file_manager", - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Get the upload URL from the site data dictionary - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - download_url = raw_req[0].get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import uuid +import re +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Filesadmin" + +class Filesadmin: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + chunk_size = 100000000 # 93 MB + chunk_position_before = -1 + chunk_position_after = -1 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + chunk_length = len(chunk_data) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + chunk_position_before = chunk_position_after + 1 + chunk_position_after = chunk_position_before + chunk_length - 1 + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-Requested-With": "XMLHttpRequest", + "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" + } + + upload_data = { + "maxChunkSize": chunk_size, + "uploadSource": "file_manager", + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Get the upload URL from the site data dictionary + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + download_url = raw_req[0].get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/filesfm.py b/modules/old_scripts/filesfm.py index e3f4e84..be6385f 100644 --- a/modules/old_scripts/filesfm.py +++ b/modules/old_scripts/filesfm.py @@ -1,62 +1,62 @@ -import requests -import os -import random -from time import sleep - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "FilesFm" - -class FilesFm: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - initialize_url = sites_data_dict[site]["initialize_url"] - download_url_base = sites_data_dict[site]["download_url_base"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - raw_req = requests.get(url=initialize_url, headers=headers, proxies=proxies, timeout=300) - - server_response = str(raw_req.text).split(",") - - upload_id = server_response[0] - upload_key = server_response[2] - - upload_url = sites_data_dict[site]["url"].format(upload_id=upload_id, upload_key=upload_key) - - if calc_size == "OK": - form_data = { - 'Filedata': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - finalize_url = sites_data_dict[site]["finalize_url"].format(upload_id=upload_id) - fin_req = requests.get(url=finalize_url, headers=headers, proxies=proxies, timeout=300) - - result = fin_req.json() - - if result.get("status", "") == "ok": - return {"status": "ok", "file_name": file_name, "file_url": download_url_base.format(upload_id=upload_id)} - else: - raise Exception("Upload Failed :(") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +from time import sleep + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "FilesFm" + +class FilesFm: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + initialize_url = sites_data_dict[site]["initialize_url"] + download_url_base = sites_data_dict[site]["download_url_base"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + raw_req = requests.get(url=initialize_url, headers=headers, proxies=proxies, timeout=300) + + server_response = str(raw_req.text).split(",") + + upload_id = server_response[0] + upload_key = server_response[2] + + upload_url = sites_data_dict[site]["url"].format(upload_id=upload_id, upload_key=upload_key) + + if calc_size == "OK": + form_data = { + 'Filedata': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + finalize_url = sites_data_dict[site]["finalize_url"].format(upload_id=upload_id) + fin_req = requests.get(url=finalize_url, headers=headers, proxies=proxies, timeout=300) + + result = fin_req.json() + + if result.get("status", "") == "ok": + return {"status": "ok", "file_name": file_name, "file_url": download_url_base.format(upload_id=upload_id)} + else: + raise Exception("Upload Failed :(") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/filesi.py b/modules/old_scripts/filesi.py index 8697eb7..e5637a4 100644 --- a/modules/old_scripts/filesi.py +++ b/modules/old_scripts/filesi.py @@ -1,47 +1,47 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "FileSi" - -class FileSi: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - response = raw_req.json() - download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "FileSi" + +class FileSi: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + response = raw_req.json() + download_url = response.get("data", {}).get("file", {}).get("url", {}).get("short", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/fileupload.py b/modules/old_scripts/fileupload.py index 58077d4..55dfed5 100644 --- a/modules/old_scripts/fileupload.py +++ b/modules/old_scripts/fileupload.py @@ -1,81 +1,81 @@ -import requests -import os -import random -import uuid -import re -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "FileUpload" - -class FileUpload: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - upload_data = { - "description": "Uploaded using Mul-Tor on GitHub!" - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - req = raw_req.json() - - server_name = req.get("name", "") - file_id = req.get("id", "") - download_url = sites_data_dict[site]["download_url_base"].format(server_name=server_name, file_id=file_id) - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random +import uuid +import re +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "FileUpload" + +class FileUpload: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + upload_data = { + "description": "Uploaded using Mul-Tor on GitHub!" + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + req = raw_req.json() + + server_name = req.get("name", "") + file_id = req.get("id", "") + download_url = sites_data_dict[site]["download_url_base"].format(server_name=server_name, file_id=file_id) + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/gofile.py b/modules/old_scripts/gofile.py index 1fa4a37..f8754e1 100644 --- a/modules/old_scripts/gofile.py +++ b/modules/old_scripts/gofile.py @@ -1,50 +1,50 @@ -import requests -import random -import os - -from .site_data import sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Gofile" - -class Gofile: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - server_url = sites_data_dict[site]["server_url"] - - headers = {"User-Agent": ua} - sleep_time = 30 - - while True: - proxies = random.choice(proxy_list) if proxy_list else None - server_res = requests.get(url=server_url, headers=headers, proxies=proxies, timeout=300).json() - status = server_res.get("status", "noServer") - if status == "ok": - server = server_res["data"]["server"] - break - elif status == "error-rateLimit": - sleep_time = 300 - sleep(sleep_time) - - upload_url = sites_data_dict[site]["url"].format(server=server) - - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - - raw_req = requests.post(url=upload_url, files=files_data, headers=headers, proxies=proxies, timeout=300, stream=True).json() - - if raw_req["status"] != "ok": - raise Exception(raw_req["status"]) - file_url = raw_req["data"]["downloadPage"] - - return {"status": "ok", "file_name": file_name, "file_url": file_url} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import random +import os + +from .site_data import sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Gofile" + +class Gofile: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + server_url = sites_data_dict[site]["server_url"] + + headers = {"User-Agent": ua} + sleep_time = 30 + + while True: + proxies = random.choice(proxy_list) if proxy_list else None + server_res = requests.get(url=server_url, headers=headers, proxies=proxies, timeout=300).json() + status = server_res.get("status", "noServer") + if status == "ok": + server = server_res["data"]["server"] + break + elif status == "error-rateLimit": + sleep_time = 300 + sleep(sleep_time) + + upload_url = sites_data_dict[site]["url"].format(server=server) + + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + + raw_req = requests.post(url=upload_url, files=files_data, headers=headers, proxies=proxies, timeout=300, stream=True).json() + + if raw_req["status"] != "ok": + raise Exception(raw_req["status"]) + file_url = raw_req["data"]["downloadPage"] + + return {"status": "ok", "file_name": file_name, "file_url": file_url} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/hexupload.py b/modules/old_scripts/hexupload.py index 3374836..3157fcb 100644 --- a/modules/old_scripts/hexupload.py +++ b/modules/old_scripts/hexupload.py @@ -1,98 +1,98 @@ -import requests -import os -import random -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "HexUpload" - -class HexUpload: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - file_blacklist = [".jpeg", ".jpg", ".png"] - # Select a random user agent - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - _, file_extension = os.path.splitext(file_name) - - if calc_size == "OK": - if file_extension in file_blacklist: - raise Exception(f"File is blacklisted! {file_blacklist}") - - normal_url = sites_data_dict[site]["api_url"] - - raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300, stream=True) - - pattern = r'action\s*=\s*["\'](https?://[^\s"\']+)["\']' - match = re.search(pattern, raw_req.text) - - if match: - upload_url = match.group(1) - else: - raise Exception("Server URL Missing. Report this!") - - - upload_data = { - "utype": "anon", - "file_descr": "Uploaded using Mul-Tor on GitHub!", - "file_public": 1, - "keepalive": 1 - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - - file_code = raw_req[0].get("file_code", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_code} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "HexUpload" + +class HexUpload: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + file_blacklist = [".jpeg", ".jpg", ".png"] + # Select a random user agent + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + _, file_extension = os.path.splitext(file_name) + + if calc_size == "OK": + if file_extension in file_blacklist: + raise Exception(f"File is blacklisted! {file_blacklist}") + + normal_url = sites_data_dict[site]["api_url"] + + raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300, stream=True) + + pattern = r'action\s*=\s*["\'](https?://[^\s"\']+)["\']' + match = re.search(pattern, raw_req.text) + + if match: + upload_url = match.group(1) + else: + raise Exception("Server URL Missing. Report this!") + + + upload_data = { + "utype": "anon", + "file_descr": "Uploaded using Mul-Tor on GitHub!", + "file_public": 1, + "keepalive": 1 + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + + file_code = raw_req[0].get("file_code", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_code} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/keep.py b/modules/old_scripts/keep.py index b5ee0ad..a4f2a83 100644 --- a/modules/old_scripts/keep.py +++ b/modules/old_scripts/keep.py @@ -1,71 +1,71 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Keep" - -class Keep: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - download_url_base = sites_data_dict[site]["download_url_base"] - - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": "curl/8.4.0" - } - - upload_url = sites_data_dict[site]["url"] + file_name - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - with open(file, "rb") as file_upload: - raw_req = requests.put(url=upload_url, data=file_upload, headers=headers, proxies=proxies, timeout=300, stream=True) - file_upload.close() - - if download_url_base in raw_req.text: - download_url = raw_req.text - else: - raise Exception("Upload somehow failed. Please report this!") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Keep" + +class Keep: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + download_url_base = sites_data_dict[site]["download_url_base"] + + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": "curl/8.4.0" + } + + upload_url = sites_data_dict[site]["url"] + file_name + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + with open(file, "rb") as file_upload: + raw_req = requests.put(url=upload_url, data=file_upload, headers=headers, proxies=proxies, timeout=300, stream=True) + file_upload.close() + + if download_url_base in raw_req.text: + download_url = raw_req.text + else: + raise Exception("Upload somehow failed. Please report this!") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/krakenfiles.py b/modules/old_scripts/krakenfiles.py index c189e50..3618227 100644 --- a/modules/old_scripts/krakenfiles.py +++ b/modules/old_scripts/krakenfiles.py @@ -1,70 +1,70 @@ -import requests -import os -import random -import string -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Krakenfiles" - -class Krakenfiles: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - server_url = sites_data_dict[site]["server_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - normal_url = sites_data_dict[site]["api_url"] - - raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) - - pattern = r'https://uploads\d+\.krakenfiles\.com/_uploader/gallery/upload' - match = re.search(pattern, raw_req.text) - - if match: - upload_url = match.group(0) - else: - raise Exception("Server URL Missing. Report this!") - form_data = { - 'files[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - response = raw_req.json() - - if raw_req.status_code == 200: - try: - error = response.get("files", [{}])[0].get("error", "") - except: - error = "" - url = response.get("files", [{}])[0].get("url", "") - - if not error == "": - raise Exception(error) - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + url} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Krakenfiles" + +class Krakenfiles: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + server_url = sites_data_dict[site]["server_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + normal_url = sites_data_dict[site]["api_url"] + + raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) + + pattern = r'https://uploads\d+\.krakenfiles\.com/_uploader/gallery/upload' + match = re.search(pattern, raw_req.text) + + if match: + upload_url = match.group(0) + else: + raise Exception("Server URL Missing. Report this!") + form_data = { + 'files[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + response = raw_req.json() + + if raw_req.status_code == 200: + try: + error = response.get("files", [{}])[0].get("error", "") + except: + error = "" + url = response.get("files", [{}])[0].get("url", "") + + if not error == "": + raise Exception(error) + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + url} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/litterbox.py b/modules/old_scripts/litterbox.py index e75fb19..62800f4 100644 --- a/modules/old_scripts/litterbox.py +++ b/modules/old_scripts/litterbox.py @@ -1,79 +1,79 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "LitterBox" - -class LitterBox: - raw_req = "None :(" - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - try: - # Select a random user agent - ua = random.choice(user_agents) - - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - upload_data = { - "reqtype": "fileupload", - "time": "72h" - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'fileToUpload': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if download_url_base in raw_req.text: - download_url = raw_req.text - else: - raise Exception("Upload somehow failed. Please report this!") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "LitterBox" + +class LitterBox: + raw_req = "None :(" + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + try: + # Select a random user agent + ua = random.choice(user_agents) + + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + upload_data = { + "reqtype": "fileupload", + "time": "72h" + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'fileToUpload': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if download_url_base in raw_req.text: + download_url = raw_req.text + else: + raise Exception("Upload somehow failed. Please report this!") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/mixdrop.py b/modules/old_scripts/mixdrop.py index 1a3523b..8a8d6c4 100644 --- a/modules/old_scripts/mixdrop.py +++ b/modules/old_scripts/mixdrop.py @@ -1,61 +1,61 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Mixdrop" - -class Mixdrop: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - download_url_base = sites_data_dict[site]["download_url_base"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - api_email = api_keys.get("email", False) - api_key = api_keys.get("apiKey", False) - - if api_email in (False, "") or api_key in (False, ""): - raise Exception("Missing API Credentials?") - - if calc_size == "OK": - data = { - "email": api_email, - "key": api_key - } - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - response = raw_req.json() - file_id = response.get("result", {}).get("fileref", "") - - if raw_req.status_code == 200: - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Mixdrop" + +class Mixdrop: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + download_url_base = sites_data_dict[site]["download_url_base"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + api_email = api_keys.get("email", False) + api_key = api_keys.get("apiKey", False) + + if api_email in (False, "") or api_key in (False, ""): + raise Exception("Missing API Credentials?") + + if calc_size == "OK": + data = { + "email": api_email, + "key": api_key + } + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + response = raw_req.json() + file_id = response.get("result", {}).get("fileref", "") + + if raw_req.status_code == 200: + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_id} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/onecloudfile.py b/modules/old_scripts/onecloudfile.py index 2a2ed59..6e4c15f 100644 --- a/modules/old_scripts/onecloudfile.py +++ b/modules/old_scripts/onecloudfile.py @@ -1,106 +1,106 @@ -import requests -import os -import random -import uuid -import re -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "1CloudFile" - -class OneCloudFile: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json" - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - chunk_size = 500000000 # 500 MB - chunk_position_before = -1 - chunk_position_after = -1 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - chunk_length = len(chunk_data) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - chunk_position_before = chunk_position_after + 1 - chunk_position_after = chunk_position_before + chunk_length - 1 - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-Requested-With": "XMLHttpRequest", - "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" - } - - upload_data = { - "maxChunkSize": chunk_size - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Get the upload URL from the site data dictionary - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - download_url = raw_req[0].get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import uuid +import re +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "1CloudFile" + +class OneCloudFile: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json" + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + chunk_size = 500000000 # 500 MB + chunk_position_before = -1 + chunk_position_after = -1 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + chunk_length = len(chunk_data) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + chunk_position_before = chunk_position_after + 1 + chunk_position_after = chunk_position_before + chunk_length - 1 + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-Requested-With": "XMLHttpRequest", + "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" + } + + upload_data = { + "maxChunkSize": chunk_size + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Get the upload URL from the site data dictionary + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + download_url = raw_req[0].get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/onefichier.py b/modules/old_scripts/onefichier.py index 217052d..569d25a 100644 --- a/modules/old_scripts/onefichier.py +++ b/modules/old_scripts/onefichier.py @@ -1,59 +1,59 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "1Fichier" - -class OneFichier: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - initialize_url = sites_data_dict[site]["initialize_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - raw_server = requests.get(url=initialize_url, headers={"User-Agent": ua, "Content-Type": "application/json"}, timeout=300) - - server_response = raw_server.json() - server_url = server_response.get("url", "") - file_id = server_response.get("id", "") - - upload_url = sites_data_dict[site]["url"].format(server=server_url, upload_id=file_id) - - form_data = { - 'file[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - finalize_url = sites_data_dict[site]["finalize_url"].format(server=server_url, upload_id=file_id) - - raw_req = requests.get(url=finalize_url, headers={"User-Agent": ua, "JSON": "1"}, proxies=proxies) - - raw_req = raw_req.json() - download_url = raw_req.get("links", [])[0].get("download", "") - - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "1Fichier" + +class OneFichier: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + initialize_url = sites_data_dict[site]["initialize_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + raw_server = requests.get(url=initialize_url, headers={"User-Agent": ua, "Content-Type": "application/json"}, timeout=300) + + server_response = raw_server.json() + server_url = server_response.get("url", "") + file_id = server_response.get("id", "") + + upload_url = sites_data_dict[site]["url"].format(server=server_url, upload_id=file_id) + + form_data = { + 'file[]': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + finalize_url = sites_data_dict[site]["finalize_url"].format(server=server_url, upload_id=file_id) + + raw_req = requests.get(url=finalize_url, headers={"User-Agent": ua, "JSON": "1"}, proxies=proxies) + + raw_req = raw_req.json() + download_url = raw_req.get("links", [])[0].get("download", "") + + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/oshi.py b/modules/old_scripts/oshi.py index e67a936..66c59d6 100644 --- a/modules/old_scripts/oshi.py +++ b/modules/old_scripts/oshi.py @@ -1,46 +1,46 @@ -import requests -import random -import os - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * - -site = "Oshi" - -class Oshi: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "which one of you maggots ate the fucking request huh?" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - # Get file name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} - req = requests.post(url=upload_url, files=files_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if req.status_code == 200: - file_url = req.content.decode("utf-8").rsplit("\nDL: ") - file_url = file_url[-1].replace("\n", "") - return {"status": "ok", "file_name": file_name, "file_url": file_url} - else: - raise Exception(f"Upload Failed: {req.content.decode('utf-8')}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import random +import os + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * + +site = "Oshi" + +class Oshi: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "which one of you maggots ate the fucking request huh?" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + # Get file name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + files_data = {'file': (os.path.basename(file), open(str(file), 'rb'), 'multipart/form-data')} + req = requests.post(url=upload_url, files=files_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if req.status_code == 200: + file_url = req.content.decode("utf-8").rsplit("\nDL: ") + file_url = file_url[-1].replace("\n", "") + return {"status": "ok", "file_name": file_name, "file_url": file_url} + else: + raise Exception(f"Upload Failed: {req.content.decode('utf-8')}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/pixeldrain.py b/modules/old_scripts/pixeldrain.py index f97a292..1fa64c2 100644 --- a/modules/old_scripts/pixeldrain.py +++ b/modules/old_scripts/pixeldrain.py @@ -1,44 +1,44 @@ -import os -import random -import urllib3 -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from .logger import Logger -import json - -class Pixeldrain: - - @staticmethod - def Uploader(file, proxy_list, user_agents, api_keys): - try: - site = "Pixeldrain" # Moved the 'site' definition inside the method - - ua = random.choice(user_agents) - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - base_url = sites_data_dict[site]["download_url_base"] - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - upload_url = sites_data_dict[site]["url"].format(file_name=file_name) - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua, "Content-Type": "application/octet-stream"} - proxy = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - http = urllib3.PoolManager() - with open(file, "rb") as file_upload: - req = http.urlopen('PUT', upload_url, body=file_upload, headers=headers, timeout=300) - if req.status != 201: - raise Exception(f"HTTP Error {req.status}: {req.reason}") - response_json = json.loads(req.data.decode('utf-8')) - return {"status": "ok", "file_name": file_name, "file_url": base_url + response_json['id']} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": size_limit} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e)} +import os +import random +import urllib3 +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from .logger import Logger +import json + +class Pixeldrain: + + @staticmethod + def Uploader(file, proxy_list, user_agents, api_keys): + try: + site = "Pixeldrain" # Moved the 'site' definition inside the method + + ua = random.choice(user_agents) + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + base_url = sites_data_dict[site]["download_url_base"] + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + upload_url = sites_data_dict[site]["url"].format(file_name=file_name) + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua, "Content-Type": "application/octet-stream"} + proxy = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + http = urllib3.PoolManager() + with open(file, "rb") as file_upload: + req = http.urlopen('PUT', upload_url, body=file_upload, headers=headers, timeout=300) + if req.status != 201: + raise Exception(f"HTTP Error {req.status}: {req.reason}") + response_json = json.loads(req.data.decode('utf-8')) + return {"status": "ok", "file_name": file_name, "file_url": base_url + response_json['id']} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": size_limit} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e)} diff --git a/modules/old_scripts/rapidgator.py b/modules/old_scripts/rapidgator.py index 5c4f5da..81f57e2 100644 --- a/modules/old_scripts/rapidgator.py +++ b/modules/old_scripts/rapidgator.py @@ -1,146 +1,146 @@ -import requests -import os -import random -import string -import re -from time import sleep - -from .site_data import Site_Data_CLSS, sites_data_dict, Hash_Calculator -from .pretty_print import * -from main import DEBUG - -site = "Rapidgator" - -""" -I have no idea why these errors occur. It works on single uploas but shits the bed on multiple uploads. - -[WinError 267] The directory name is invalid: 'FILENAME.zip' -[Errno 2] No such file or directory: 'FILENAME.zip' -""" - -class Rapidgator: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - status = "terrible" - try: - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - api_email = api_keys.get("email", False) - api_password = api_keys.get("password", False) - - if api_email in (False, "") or api_password in (False, ""): - raise Exception("Missing API Credentials?") - - initialize_url = sites_data_dict[site]["initialize_url"] - - params = { - "login": api_email, - "password": api_password - } - - raw_req = requests.get(url=initialize_url, headers={"User-Agent": ua}, proxies=proxies, timeout=300, params=params) - - raw_req = raw_req.json() - - try: - token = raw_req.get("response", {}).get("token", "No_Token") - status = raw_req.get("status", "terrible") - details = raw_req.get("details", "No_Details") - space_left = raw_req.get("response", {}).get("user", {}).get("storage", {}).get("left", 0) - max_file_size = raw_req.get("response", {}).get("user", {}).get("upload", {}).get("max_file_size", 0) - except Exception as e: - raise Exception("Login Failed? Please check your account details else report this.") - - if file_size <= max_file_size and space_left > file_size: - - md5_hash = Hash_Calculator.cal_hash(file) - - server_url = sites_data_dict[site]["server_url"] - - params = { - "name": file_name, - "hash": md5_hash.hexdigest(), - "size": file_size, - "token": token - } - - raw_req = requests.get(url=server_url, params=params, headers=headers, proxies=proxies, timeout=300) - - raw_req = raw_req.json() - - status = raw_req.get("status", 418) - details = raw_req.get("details", "No_Details") - - if not status == 200: - raise Exception(details) - - state = raw_req.get("response", {}).get("upload", {}).get("state", 99) - - if state == 2: - download_url = raw_req.get("response", {}).get("upload", {}).get("file", {}).get("url", "No_FileURL") - return {"status": "ok", "file_name": file_name, "file_url": download_url} - - upload_id = raw_req.get("response", {}).get("upload", {}).get("upload_id", "No_UploadID") - upload_url = raw_req.get("response", {}).get("upload", {}).get("url", "No_UploadURL") - - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - status = raw_req.get("status", "terrible") - details = raw_req.get("details", "No_Details") - - if not status == 200: - try: - raise Exception(details) - except Exception as e: - raise Exception("Well the upload somehow failed. Report this. " + str(e)) - - finalize_url = sites_data_dict[site]["finalize_url"] - - params = { - "upload_id": upload_id, - "token": token - } - - while True: - raw_req = requests.get(url=finalize_url, params=params, headers=headers, proxies=proxies, timeout=300) - - raw_req = raw_req.json() - status = raw_req.get("status", "terrible") - details = raw_req.get("details", "No_Details") - upload_state = raw_req.get("response", {}).get("upload", {}).get("state", "No_UploadState") - - if upload_state == 2: - download_url = raw_req.get("response", {}).get("upload", {}).get("file", {}).get("url", "No_UploadURL") - break - - sleep(5) - - if status == 200: - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - raise Exception(f"Details: {details}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": f"{status} {raw_req}"} - -""" - -Fuck you Rapidgator. - +import requests +import os +import random +import string +import re +from time import sleep + +from .site_data import Site_Data_CLSS, sites_data_dict, Hash_Calculator +from .pretty_print import * +from main import DEBUG + +site = "Rapidgator" + +""" +I have no idea why these errors occur. It works on single uploas but shits the bed on multiple uploads. + +[WinError 267] The directory name is invalid: 'FILENAME.zip' +[Errno 2] No such file or directory: 'FILENAME.zip' +""" + +class Rapidgator: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + status = "terrible" + try: + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + api_email = api_keys.get("email", False) + api_password = api_keys.get("password", False) + + if api_email in (False, "") or api_password in (False, ""): + raise Exception("Missing API Credentials?") + + initialize_url = sites_data_dict[site]["initialize_url"] + + params = { + "login": api_email, + "password": api_password + } + + raw_req = requests.get(url=initialize_url, headers={"User-Agent": ua}, proxies=proxies, timeout=300, params=params) + + raw_req = raw_req.json() + + try: + token = raw_req.get("response", {}).get("token", "No_Token") + status = raw_req.get("status", "terrible") + details = raw_req.get("details", "No_Details") + space_left = raw_req.get("response", {}).get("user", {}).get("storage", {}).get("left", 0) + max_file_size = raw_req.get("response", {}).get("user", {}).get("upload", {}).get("max_file_size", 0) + except Exception as e: + raise Exception("Login Failed? Please check your account details else report this.") + + if file_size <= max_file_size and space_left > file_size: + + md5_hash = Hash_Calculator.cal_hash(file) + + server_url = sites_data_dict[site]["server_url"] + + params = { + "name": file_name, + "hash": md5_hash.hexdigest(), + "size": file_size, + "token": token + } + + raw_req = requests.get(url=server_url, params=params, headers=headers, proxies=proxies, timeout=300) + + raw_req = raw_req.json() + + status = raw_req.get("status", 418) + details = raw_req.get("details", "No_Details") + + if not status == 200: + raise Exception(details) + + state = raw_req.get("response", {}).get("upload", {}).get("state", 99) + + if state == 2: + download_url = raw_req.get("response", {}).get("upload", {}).get("file", {}).get("url", "No_FileURL") + return {"status": "ok", "file_name": file_name, "file_url": download_url} + + upload_id = raw_req.get("response", {}).get("upload", {}).get("upload_id", "No_UploadID") + upload_url = raw_req.get("response", {}).get("upload", {}).get("url", "No_UploadURL") + + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + status = raw_req.get("status", "terrible") + details = raw_req.get("details", "No_Details") + + if not status == 200: + try: + raise Exception(details) + except Exception as e: + raise Exception("Well the upload somehow failed. Report this. " + str(e)) + + finalize_url = sites_data_dict[site]["finalize_url"] + + params = { + "upload_id": upload_id, + "token": token + } + + while True: + raw_req = requests.get(url=finalize_url, params=params, headers=headers, proxies=proxies, timeout=300) + + raw_req = raw_req.json() + status = raw_req.get("status", "terrible") + details = raw_req.get("details", "No_Details") + upload_state = raw_req.get("response", {}).get("upload", {}).get("state", "No_UploadState") + + if upload_state == 2: + download_url = raw_req.get("response", {}).get("upload", {}).get("file", {}).get("url", "No_UploadURL") + break + + sleep(5) + + if status == 200: + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + raise Exception(f"Details: {details}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": f"{status} {raw_req}"} + +""" + +Fuck you Rapidgator. + """ \ No newline at end of file diff --git a/modules/old_scripts/tempsend.py b/modules/old_scripts/tempsend.py index fcd38e7..fab46f3 100644 --- a/modules/old_scripts/tempsend.py +++ b/modules/old_scripts/tempsend.py @@ -1,75 +1,75 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "TempSend" - -class TempSend: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - upload_data = { - "expire": 31536000 - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - download_url = raw_req.url - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "TempSend" + +class TempSend: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + upload_data = { + "expire": 31536000 + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + download_url = raw_req.url + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} \ No newline at end of file diff --git a/modules/old_scripts/tmpfiles.py b/modules/old_scripts/tmpfiles.py index b57449d..674f73c 100644 --- a/modules/old_scripts/tmpfiles.py +++ b/modules/old_scripts/tmpfiles.py @@ -1,49 +1,49 @@ -import requests -import os -import random -from time import sleep - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "TmpFiles" - -class TmpFiles: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if raw_req.status_code == 200: - response = raw_req.json() - else: - raise Exception(raw_req.status_code) - - return {"status": "ok", "file_name": file_name, "file_url": response.get("data", {}).get("url", "No URL :(")} - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +from time import sleep + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "TmpFiles" + +class TmpFiles: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if raw_req.status_code == 200: + response = raw_req.json() + else: + raise Exception(raw_req.status_code) + + return {"status": "ok", "file_name": file_name, "file_url": response.get("data", {}).get("url", "No URL :(")} + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/transfer.py b/modules/old_scripts/transfer.py index cd61cd7..19d1934 100644 --- a/modules/old_scripts/transfer.py +++ b/modules/old_scripts/transfer.py @@ -1,47 +1,47 @@ -import requests -import os -import random -import string - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "Transfer.sh" - -class Transfer_sh: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - try: - ua = random.choice(user_agents) - upload_url = sites_data_dict[site]["url"].format(file_name=os.path.basename(file)) - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - form_data = { - 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.put(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - if raw_req.status_code == 200: - return {"status": "ok", "file_name": file_name, "file_url": str(raw_req.text)} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import string + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "Transfer.sh" + +class Transfer_sh: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + try: + ua = random.choice(user_agents) + upload_url = sites_data_dict[site]["url"].format(file_name=os.path.basename(file)) + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + form_data = { + 'file': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.put(url=upload_url, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + if raw_req.status_code == 200: + return {"status": "ok", "file_name": file_name, "file_url": str(raw_req.text)} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/ufile.py b/modules/old_scripts/ufile.py index ac22011..268ee6b 100644 --- a/modules/old_scripts/ufile.py +++ b/modules/old_scripts/ufile.py @@ -1,124 +1,124 @@ -import requests -import os -import random - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "uFile" - -class uFile: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json" - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - chunk_size = 69512747 # 66 MB - chunk_index = 1 - total_chunks = (file_size + chunk_size - 1) // chunk_size - - if calc_size == "OK": - - server_url = sites_data_dict[site]["server_url"] - - raw_req = requests.post(url=server_url, headers=headers, proxies=proxies, timeout=300) - - raw_req = raw_req.json() - - storage_server = raw_req.get("storageBaseUrl", "") - - initialize_url = sites_data_dict[site]["initialize_url"].format(server=storage_server) - - upload_data = { - "file_size": file_size - } - - raw_req = requests.post(url=initialize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) - - raw_req = raw_req.json() - file_id = raw_req.get("fuid", "") - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - upload_data = { - "fuid": file_id, - "chunk_index": chunk_index - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Get the upload URL from the site data dictionary - upload_url = sites_data_dict[site]["url"].format(server=storage_server) - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - chunk_index += 1 - - finalize_url = sites_data_dict[site]["finalize_url"].format(server=storage_server) - - upload_data = { - "fuid": file_id, - "file_name": file_name, - "file_type": "unknown", - "total_chunks": total_chunks - } - - raw_req = requests.post(url=finalize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) - - raw_req = raw_req.json() - download_url = raw_req.get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "uFile" + +class uFile: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json" + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + chunk_size = 69512747 # 66 MB + chunk_index = 1 + total_chunks = (file_size + chunk_size - 1) // chunk_size + + if calc_size == "OK": + + server_url = sites_data_dict[site]["server_url"] + + raw_req = requests.post(url=server_url, headers=headers, proxies=proxies, timeout=300) + + raw_req = raw_req.json() + + storage_server = raw_req.get("storageBaseUrl", "") + + initialize_url = sites_data_dict[site]["initialize_url"].format(server=storage_server) + + upload_data = { + "file_size": file_size + } + + raw_req = requests.post(url=initialize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) + + raw_req = raw_req.json() + file_id = raw_req.get("fuid", "") + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + upload_data = { + "fuid": file_id, + "chunk_index": chunk_index + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Get the upload URL from the site data dictionary + upload_url = sites_data_dict[site]["url"].format(server=storage_server) + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + chunk_index += 1 + + finalize_url = sites_data_dict[site]["finalize_url"].format(server=storage_server) + + upload_data = { + "fuid": file_id, + "file_name": file_name, + "file_type": "unknown", + "total_chunks": total_chunks + } + + raw_req = requests.post(url=finalize_url, data=upload_data, headers=headers, proxies=proxies, timeout=300) + + raw_req = raw_req.json() + download_url = raw_req.get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/usercloud.py b/modules/old_scripts/usercloud.py index 9f2ef02..42a03eb 100644 --- a/modules/old_scripts/usercloud.py +++ b/modules/old_scripts/usercloud.py @@ -1,92 +1,92 @@ -import requests -import os -import random -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "UserCloud" - -class UserCloud: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Set the user agent header - headers = { - "User-Agent": ua - } - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - normal_url = sites_data_dict[site]["api_url"] - - raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) - - pattern = r'action\s*=\s*["\'](https?://[^\s"\']+)["\']' - match = re.search(pattern, raw_req.text) - - if match: - upload_url = match.group(1) - else: - raise Exception("Server URL Missing. Report this!") - - - upload_data = { - "utype": "anon", - "file_descr": "Uploaded using Mul-Tor on GitHub!", - "file_public": 1, - "keepalive": 1 - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - - file_code = raw_req[0].get("file_code", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_code} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "UserCloud" + +class UserCloud: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Set the user agent header + headers = { + "User-Agent": ua + } + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + normal_url = sites_data_dict[site]["api_url"] + + raw_req = requests.get(url=normal_url, headers=headers, proxies=proxies, timeout=300) + + pattern = r'action\s*=\s*["\'](https?://[^\s"\']+)["\']' + match = re.search(pattern, raw_req.text) + + if match: + upload_url = match.group(1) + else: + raise Exception("Server URL Missing. Report this!") + + + upload_data = { + "utype": "anon", + "file_descr": "Uploaded using Mul-Tor on GitHub!", + "file_public": 1, + "keepalive": 1 + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + + file_code = raw_req[0].get("file_code", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url_base + file_code} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/old_scripts/usersdrive.py b/modules/old_scripts/usersdrive.py index 0bbb9cc..0b51b45 100644 --- a/modules/old_scripts/usersdrive.py +++ b/modules/old_scripts/usersdrive.py @@ -1,78 +1,78 @@ -import requests -import os -import random -import string -import re - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "UsersDrive" - -class UsersDrive: - - def Uploader(file, proxy_list, user_agents, api_keys): - raw_req = "None :(" - status = "terrible" - try: - ua = random.choice(user_agents) - download_url_base = sites_data_dict[site]["download_url_base"] - normal_url = sites_data_dict[site]["api_url"] - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. - - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - headers = {"User-Agent": ua} - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - raw_req = requests.get(url=normal_url, headers={"User-Agent": ua}, proxies=proxies, timeout=300) - - pattern = r'https://(\S+)\.userdrive\.(me|org)/cgi-bin/upload\.cgi\?upload_type=file' - match = re.search(pattern, raw_req.text) - - if match: - upload_url = match.group(0) - else: - raise Exception("Server URL Missing. Report this!") - - data = { - "utype": "anon", - "keepalive": 1, - } - form_data = { - 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') - } - - raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - response = raw_req.json() - status = response[0].get("file_status", "terrible") - file_id = response[0].get("file_code", "No_Code :(") - - if raw_req.status_code == 200 and status == "OK": - return {"status": "ok", "file_name": file_name, "file_url": download_url_base.format(file_id=file_id)} - else: - raise Exception(f"Status code: {raw_req.status_code}") - else: - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - - except Exception as e: - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": f"{status} {raw_req}"} - - -""" -Here i will store encountered server addresses for regex purposes. - -https://dns3.userdrive.org/cgi-bin/upload.cgi?upload_type=file - - - +import requests +import os +import random +import string +import re + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "UsersDrive" + +class UsersDrive: + + def Uploader(file, proxy_list, user_agents, api_keys): + raw_req = "None :(" + status = "terrible" + try: + ua = random.choice(user_agents) + download_url_base = sites_data_dict[site]["download_url_base"] + normal_url = sites_data_dict[site]["api_url"] + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name # Changed from 255 to 240 as an additional safety net. + + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + headers = {"User-Agent": ua} + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + raw_req = requests.get(url=normal_url, headers={"User-Agent": ua}, proxies=proxies, timeout=300) + + pattern = r'https://(\S+)\.userdrive\.(me|org)/cgi-bin/upload\.cgi\?upload_type=file' + match = re.search(pattern, raw_req.text) + + if match: + upload_url = match.group(0) + else: + raise Exception("Server URL Missing. Report this!") + + data = { + "utype": "anon", + "keepalive": 1, + } + form_data = { + 'file_0': (os.path.basename(file), open(str(file), 'rb'), 'application/octet-stream') + } + + raw_req = requests.post(url=upload_url, data=data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + response = raw_req.json() + status = response[0].get("file_status", "terrible") + file_id = response[0].get("file_code", "No_Code :(") + + if raw_req.status_code == 200 and status == "OK": + return {"status": "ok", "file_name": file_name, "file_url": download_url_base.format(file_id=file_id)} + else: + raise Exception(f"Status code: {raw_req.status_code}") + else: + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + + except Exception as e: + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": f"{status} {raw_req}"} + + +""" +Here i will store encountered server addresses for regex purposes. + +https://dns3.userdrive.org/cgi-bin/upload.cgi?upload_type=file + + + """ \ No newline at end of file diff --git a/modules/old_scripts/wdho.py b/modules/old_scripts/wdho.py index 2dc9233..21346f0 100644 --- a/modules/old_scripts/wdho.py +++ b/modules/old_scripts/wdho.py @@ -1,100 +1,100 @@ -import requests -import os -import random -import uuid -import re -import json - -from .site_data import Site_Data_CLSS, sites_data_dict -from .pretty_print import * -from main import DEBUG - -site = "WDHO" - -class WDHO: - def Uploader(file, proxy_list, user_agents, api_keys): - """ - Uploads a file to a specified site using random user agents and proxies. - - Args: - file (str): The path to the file to be uploaded. - proxy_list (list): A list of proxy URLs. - user_agents (list): A list of user agent strings. - - Returns: - dict: A dictionary containing the status, file name, file URL, and site. - - Raises: - Exception: If an error occurs during the upload process. - """ - raw_req = "None :(" - try: - # Select a random user agent - ua = random.choice(user_agents) - - size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' - - # Get the file size and name - file_size = os.stat(file).st_size - file_name = os.path.basename(file) - - # Truncate the file name if it is too long - file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name - - # Calculate the size unit for the site - calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) - - # Select a random proxy, if available - proxies = random.choice(proxy_list) if proxy_list else None - - if calc_size == "OK": - - chunk_size = 100000000 # 93 MB - chunk_position_before = -1 - chunk_position_after = -1 - - with open(file, 'rb') as file_data: - while True: - chunk_data = file_data.read(chunk_size) - chunk_length = len(chunk_data) - if not chunk_data: - break # Exit the loop if we've reached the end of the file - - chunk_position_before = chunk_position_after + 1 - chunk_position_after = chunk_position_before + chunk_length - 1 - - # Set the user agent header - headers = { - "User-Agent": ua, - "Accept": "application/json", - "X-Requested-With": "XMLHttpRequest", - "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" - } - - upload_data = { - "maxChunkSize": chunk_size - } - - # Prepare the json data to add extra data to the upload - form_data = { - 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') - } - - # Get the upload URL from the site data dictionary - upload_url = sites_data_dict[site]["url"] - - # Send the upload request with the form data, headers, and proxies - raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) - - raw_req = raw_req.json() - download_url = raw_req[0].get("url", "") - - # Return successful message with the status, file name, file URL, and site - return {"status": "ok", "file_name": file_name, "file_url": download_url} - else: - # Return size error message - return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} - except Exception as e: - # Return error message - return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} - +import requests +import os +import random +import uuid +import re +import json + +from .site_data import Site_Data_CLSS, sites_data_dict +from .pretty_print import * +from main import DEBUG + +site = "WDHO" + +class WDHO: + def Uploader(file, proxy_list, user_agents, api_keys): + """ + Uploads a file to a specified site using random user agents and proxies. + + Args: + file (str): The path to the file to be uploaded. + proxy_list (list): A list of proxy URLs. + user_agents (list): A list of user agent strings. + + Returns: + dict: A dictionary containing the status, file name, file URL, and site. + + Raises: + Exception: If an error occurs during the upload process. + """ + raw_req = "None :(" + try: + # Select a random user agent + ua = random.choice(user_agents) + + size_limit = f'{sites_data_dict[site]["size_limit"]} {sites_data_dict[site]["size_unit"]}' + + # Get the file size and name + file_size = os.stat(file).st_size + file_name = os.path.basename(file) + + # Truncate the file name if it is too long + file_name = (file_name[:240] + '..') if len(file_name) > 240 else file_name + + # Calculate the size unit for the site + calc_size = Site_Data_CLSS.size_unit_calc(site, file_size) + + # Select a random proxy, if available + proxies = random.choice(proxy_list) if proxy_list else None + + if calc_size == "OK": + + chunk_size = 100000000 # 93 MB + chunk_position_before = -1 + chunk_position_after = -1 + + with open(file, 'rb') as file_data: + while True: + chunk_data = file_data.read(chunk_size) + chunk_length = len(chunk_data) + if not chunk_data: + break # Exit the loop if we've reached the end of the file + + chunk_position_before = chunk_position_after + 1 + chunk_position_after = chunk_position_before + chunk_length - 1 + + # Set the user agent header + headers = { + "User-Agent": ua, + "Accept": "application/json", + "X-Requested-With": "XMLHttpRequest", + "Content-Range": f"bytes {chunk_position_before}-{chunk_position_after}/{file_size}" + } + + upload_data = { + "maxChunkSize": chunk_size + } + + # Prepare the json data to add extra data to the upload + form_data = { + 'files[]': (os.path.basename(file), chunk_data, 'application/octet-stream') + } + + # Get the upload URL from the site data dictionary + upload_url = sites_data_dict[site]["url"] + + # Send the upload request with the form data, headers, and proxies + raw_req = requests.post(url=upload_url, data=upload_data, files=form_data, headers=headers, proxies=proxies, timeout=300, stream=True) + + raw_req = raw_req.json() + download_url = raw_req[0].get("url", "") + + # Return successful message with the status, file name, file URL, and site + return {"status": "ok", "file_name": file_name, "file_url": download_url} + else: + # Return size error message + return {"status": "size_error", "file_name": file_name, "exception": "SIZE_ERROR", "size_limit": f"{str(size_limit)}"} + except Exception as e: + # Return error message + return {"status": "error", "file_name": file_name, "exception": str(e), "extra": raw_req} + diff --git a/modules/preset_manager.py b/modules/preset_manager.py index e4c131d..008bd35 100644 --- a/modules/preset_manager.py +++ b/modules/preset_manager.py @@ -1,28 +1,28 @@ -# Import Standard Libraries -import json - -# Import Third-Party Libraries - -# Import Local Libraries -from .logger import Logger - -class PresetManager: - - def __init__(self, preset_name: str) -> None: - self.preset_name = preset_name - - def _load(self) -> tuple[list[str], str]: - try: - with open(f"presets/{self.preset_name}", "r", encoding="utf-8") as preset_file: - preset: dict = json.load(preset_file) - preset_sites: list[str] = preset.get("sites", []) - link_format: str = preset.get("link-format", None) - - return preset_sites, link_format - - except Exception as e: - logger_instance = Logger(message=f"Failed to load preset {self.preset_name}", extra=str(e), severity="error") - logger_instance.log_event() - - def _update_preset(self) -> None: - pass # TODO: implement update preset code +# Import Standard Libraries +import json + +# Import Third-Party Libraries + +# Import Local Libraries +from .logger import Logger + +class PresetManager: + + def __init__(self, preset_name: str) -> None: + self.preset_name = preset_name + + def _load(self) -> tuple[list[str], str]: + try: + with open(f"presets/{self.preset_name}", "r", encoding="utf-8") as preset_file: + preset: dict = json.load(preset_file) + preset_sites: list[str] = preset.get("sites", []) + link_format: str = preset.get("link-format", None) + + return preset_sites, link_format + + except Exception as e: + logger_instance = Logger(message=f"Failed to load preset {self.preset_name}", extra=str(e), severity="error") + logger_instance.log_event() + + def _update_preset(self) -> None: + pass # TODO: implement update preset code diff --git a/modules/pretty_print.py b/modules/pretty_print.py index c264831..c5918c6 100644 --- a/modules/pretty_print.py +++ b/modules/pretty_print.py @@ -1,10 +1,10 @@ -from termcolor import colored - -class PrettyPrint: - def __init__(self) -> None: - self.major = str(colored(f"[{colored('!!!', 'red')}]")) - self.error = str(colored(f"[{colored('!', 'red')}]")) - self.warning = str(colored(f"[{colored('!', 'yellow')}]")) - self.info = str(colored(f"[{colored('i', 'light_blue')}]")) - self.ok = str(colored(f"[{colored('+', 'green')}]")) - self.debug = str(colored(f"[{colored('dbg', 'blue')}]")) +from termcolor import colored + +class PrettyPrint: + def __init__(self) -> None: + self.major = str(colored(f"[{colored('!!!', 'red')}]")) + self.error = str(colored(f"[{colored('!', 'red')}]")) + self.warning = str(colored(f"[{colored('!', 'yellow')}]")) + self.info = str(colored(f"[{colored('i', 'light_blue')}]")) + self.ok = str(colored(f"[{colored('+', 'green')}]")) + self.debug = str(colored(f"[{colored('dbg', 'blue')}]")) diff --git a/modules/proxy_scraper.py b/modules/proxy_scraper.py index 1c04468..927622b 100644 --- a/modules/proxy_scraper.py +++ b/modules/proxy_scraper.py @@ -1,51 +1,51 @@ -# Import Standard Libraries - -# Import Third-Party Libraries -import requests -from termcolor import colored - -# Import Local Libraries -from .storage import __version__ as version -from .storage import __user_agent__ as user_agent -from .pretty_print import PrettyPrint -from .logger import Logger - - -# scrape proxies from a given destination -class ProxyScraper(): - """Fetch a fresh list of proxies for usage during runtime. - """ - - def __init__(self, proxy_source_list: list=None) -> None: - self.proxy_source_list = proxy_source_list - self.proxy_list = self._scraper() - self.user_agent = user_agent - - def _scraper(self): - try: - proxy_list = [] - for source in self.proxy_source_list: - response = requests.get( - url=source, - headers={"User-Agent":self.user_agent}, - timeout=30 - ) - proxy_raw = response.text - split_proxies = proxy_raw.split() - for proxy in split_proxies: - if proxy in proxy_list: - break - else: - proxyy = {"http": proxy} - proxy_list.append(proxyy) - return proxy_list - except Exception as e: - # Construct and print the error - - - - logger_instance = Logger(message="An error occurred during the fetching of proxies!", extra=str(e), severity="error") - - error_str = f"An error occurred during the fetching of proxies! Please report this. Exception: {e}" - print(colored(f"{error} {error_str}")) +# Import Standard Libraries + +# Import Third-Party Libraries +import requests +from termcolor import colored + +# Import Local Libraries +from .storage import __version__ as version +from .storage import __user_agent__ as user_agent +from .pretty_print import PrettyPrint +from .logger import Logger + + +# scrape proxies from a given destination +class ProxyScraper(): + """Fetch a fresh list of proxies for usage during runtime. + """ + + def __init__(self, proxy_source_list: list=None) -> None: + self.proxy_source_list = proxy_source_list + self.proxy_list = self._scraper() + self.user_agent = user_agent + + def _scraper(self): + try: + proxy_list = [] + for source in self.proxy_source_list: + response = requests.get( + url=source, + headers={"User-Agent":self.user_agent}, + timeout=30 + ) + proxy_raw = response.text + split_proxies = proxy_raw.split() + for proxy in split_proxies: + if proxy in proxy_list: + break + else: + proxyy = {"http": proxy} + proxy_list.append(proxyy) + return proxy_list + except Exception as e: + # Construct and print the error + + + + logger_instance = Logger(message="An error occurred during the fetching of proxies!", extra=str(e), severity="error") + + error_str = f"An error occurred during the fetching of proxies! Please report this. Exception: {e}" + print(colored(f"{error} {error_str}")) Logger.log_event(error_str, response) \ No newline at end of file diff --git a/modules/setup.py b/modules/setup.py deleted file mode 100644 index 09462af..0000000 --- a/modules/setup.py +++ /dev/null @@ -1,224 +0,0 @@ -# Import Basics -from time import sleep -import os -import sys -from datetime import datetime - -# Import Third Party -import inquirer -from termcolor import colored -import plyer -from alive_progress import alive_bar - -# Import custom modules -from .Config_Manager import ConfigManager -from .auto_update import AutoUpdate -from .proxy_scraper import ProxyScraper -from .logger import Logger -from .pretty_print import PrettyPrint -from .availability_checker import AvailabilityChecker -from .storage import __dev_debug__ as DEBUG - -class Main: - - def __init__(self): - self.version = "2.0.0" - self.owd = os.getcwd() - self.platform = sys.platform - self.user_agent = f"mul-tor/{self.version}- (by Official Husko on GitHub)" - self.version_for_logo = colored(f"v{self.version}", "cyan") - self.config = None - self.current_working_directory: str = os.getcwd() - - self.logo = f""" - {colored(f''' - .88b d88. db db db d888888b .d88b. d8888b. - 88'YbdP`88 88 88 88 `~~88~~' .8P Y8. 88 `8D - 88 88 88 88 88 88 88 88 88 88oobY' - 88 88 88 88 88 88 C8888D 88 88 88 88`8b - 88 88 88 88b d88 88booo. 88 `8b d8' 88 `88. - YP YP YP ~Y8888P' Y88888P YP `Y88P' 88 YD - {self.version_for_logo} | by {colored("Official-Husko", "yellow")}''', "red")} - """ - - def _check_read_write_permissions(self): - return os.access(self.current_working_directory, os.W_OK) and os.access(self.current_working_directory, os.R_OK) - - def _file_selection(self): - pass - - def _preset_selection(self): - pass - - def startup(self): - if self.platform == "win32": - os.system("cls") - print(self.logo) - - if DEBUG: - print(f"{colored('Platform:', 'green')} {self.platform}") - print("") - - # Run config system - config_instance = ConfigManager - - proxies_enabled = config.get("useProxies", False) - check_for_updates_enabled = config.get("checkForUpdates", True) - - if check_for_updates_enabled: - os.system("cls") - print(self.logo) - print("") - print(colored("Checking for Updates...", "yellow"), end='\r') - AutoUpdate.Checker() - os.system("cls") - print(self.logo) - print("") - - # Check if the user wants to use proxies and get them - if proxies_enabled: - print(colored("Fetching Fresh Proxies...", "yellow"), end='\r') - proxy_list = ProxyScraper.Scraper() - print(f"{colored('Fetched', 'green')} {colored(len(proxy_list), 'yellow')} {colored('Proxies. ', 'green')}") - print("") - else: - proxy_list = [] - - available = AvailabilityChecker.Evaluate(config, proxy_list) - if DEBUG: - print(available) - - if not os.path.exists("presets"): - os.mkdir("presets") - if not os.path.exists("presets/readme.txt"): - with open("presets\\readme.txt", "a", encoding="utf-8") as readme: - text = "To create your own preset visit the wiki here: https://github.com/Official-Husko/mul-tor/wiki/Preset-Configuration" - readme.write(text) - - return config, available, proxy_list, ua_list - - def selection(config, available, user_agents_list, proxy_list=""): - - auto_load_preset = config.get("presetSystem", {}).get("autoLoadPreset", False) - enable_preset_selection = config.get("presetSystem", {}).get("enablePresetSelection", False) - preset_name = config.get("presetSystem", {}).get("presetName", "") - - if auto_load_preset == True and not os.path.exists(f"presets/{preset_name}"): - print(colored(f"Error: Preset {preset_name} does not exist. Continuing without preset!", "red")) - print("") - auto_load_preset = False - - if auto_load_preset == True and DEBUG == False: - auto_load_data = Preset_Manager.loader(available, preset_name) - available = auto_load_data[0] - link_format = auto_load_data[1] - else: - link_format = "" - - if DEBUG == True and use_test_file == True: - if test_small_file == True: - files_list = [f"{owd}\\test.png"] - elif test_large_file == True: - files_list = [f"{owd}\\big_game.zip"] - elif test_very_large_file == True: - files_list = [f"{owd}\\very_big_game.7z"] - else: - print(colored("Something fucked up! Please report this on github. Test_File_Error", "red")) - - else: - amount_question = [ - inquirer.List('selection', - message=colored("What file/s do you want to upload?", "green"), - choices=["Single", "Multiple"], - ), - ] - amount_answers = inquirer.prompt(amount_question) - print("") - sites = amount_answers.get("selection") - - - files_list = [] - while len(files_list) == 0 or files_list == [[]]: - files_list = [] # Reset it - if amount_answers.get("selection") == "Single": - files_list = plyer.filechooser.open_file() - elif amount_answers.get("selection") == "Multiple": - fn = plyer.filechooser.choose_dir() - fn = fn[0] - files_in_folder = os.listdir(fn) - for found_file in files_in_folder: - if os.path.isdir(f"{fn}\\{found_file}") != True: - files_list.append(f"{fn}\\{found_file}") - else: - print(colored("Something fucked up! Please report this on github. Selection_Error", "red")) - sleep(5) - - if available == []: - print(colored("No sites are available. Please double check your config (and preset if used). If you think this is an error please report it on github.", "red")) - sleep(10) - exit(0) - - questions = [ - inquirer.Checkbox('selections', - message=f"{colored('What sites do you want to upload too?', 'green')} {colored(f'{len(available)} available', 'yellow')}", - choices=available, - ), - ] - answers = inquirer.prompt(questions) - print("") - - sites = answers.get("selections") - - with alive_bar(len(files_list), calibrate=1, dual_line=True, title='Uploading', enrich_print=False, stats=False, receipt=False, receipt_text=False) as list_bar: - for file in files_list: - for site in sites: - bar_file_name = os.path.basename(file) - list_bar.title = f'-> Uploading {colored(bar_file_name, "light_blue")} to {colored(site, "yellow")}, please wait...' - output = { - "status": "", - "file_name": "", - "file_url": "", - "exception": "", - "size_limit": "", - "extra": "" - } - - uploader_classes = { - "Buzzheavier": Buzzheavier - } - - if site in uploader_classes: - api_key = config.get("api_keys", {}).get(site, None) if sites_data_dict.get(site, "").get("apiKey") == True else None - - site_instance = uploader_classes.get(site, "No_Site")(file, proxy_list, user_agents_list, api_key) - output = site_instance.Uploader() - - - print(output) - - # output = uploader_classes.get(site, "No_Site").Uploader(file, proxy_list, user_agents_list, api_key) - - status = output.get("status", "404 status not found") - file_name = output.get("file_name", "oopsie_daisie.fish") - file_url = output.get("file_url", "url be doing the hidy hole") - exception_str = output.get("exception", "Fuck me there was no exception.") - size_limit = output.get("size_limit", "-3 GB") - extra = output.get("extra", "Monkey stole the bananas") - - os.chdir(owd) - if status == "ok": - print(f"{ok} {colored(file_name, 'light_blue')} {colored('successfully uploaded to', 'green')} {colored(site, 'yellow')}{colored('! URL:', 'green')} {colored(file_url, 'light_blue')}") - with open("file_links.txt", "a") as file_links: - file_links.writelines(f"{datetime.now()} | {site} | {file_name} - {file_url}\n") - file_links.close() - if auto_load_preset == True and link_format != "" and DEBUG == False: - with open("file_links_formatted.txt", "a") as formatted_links_file: - formatted_links_file.writelines(f"{link_format.format(status=status, file_name=file_name, file_url=file_url, site_name=site, date_and_time=datetime.now())}\n") - formatted_links_file.close() - else: - touch_grass = False - feel_woman_touch = False - pass - - list_bar() - os.chdir(owd) # reset to default working dir diff --git a/modules/site_data.py b/modules/site_data.py deleted file mode 100644 index 89a584d..0000000 --- a/modules/site_data.py +++ /dev/null @@ -1,308 +0,0 @@ -sites_data_dict = { - "Gofile": { - "apiKey": False, - "url": "https://{server}.gofile.io/uploadFile", - "api_url": "https://gofile.io/api/", - "download_url_base": "https://gofile.io/d/", - "server_url": "https://api.gofile.io/getServer" - }, - "Pixeldrain": { - "apiKey": False, - "url": "https://pixeldrain.com/api/file/{file_name}", - "api_url": "https://pixeldrain.com/api/", - "download_url_base": "https://pixeldrain.com/u/", - "size_limit": 20, - "size_unit": "GB" - }, - "FileBin": { - "apiKey": False, - "url": "https://filebin.net/", - "api_url": "https://filebin.net/", - "download_url_base": "https://filebin.net/" - }, - "Delafil": { - "apiKey": False, - "url": "https://delafil.se/core/page/ajax/file_upload_handler.ajax.php", - "api_url": "https://delafil.se/", - "download_url_base": "https://delafil.se/", - "size_limit": 6, - "size_unit": "GB" - }, - "Files.dp.ua": { - "apiKey": False, - "url": "https://files2.dp.ua/upload.php", - "api_url": "https://files2.dp.ua/upload.php", - "download_url_base": "https://files.dp.ua/en/", - "size_limit": 100, - "size_unit": "GB" - }, - "FilesFm": { - "apiKey": False, - "url": "https://free.files.fm/save_file.php?up_id={upload_id}&ignore_user_abort=1&skip_update=1&key={upload_key}", - "api_url": "https://free.files.fm/save_file.php", - "download_url_base": "https://files.fm/u/{upload_id}", - "initialize_url": "https://files.fm/server_scripts/get_upload_id.php?show_add_key=1", - "finalize_url": "https://free.files.fm/finish_upload.php?upload_hash={upload_id}", - "size_limit": 5, - "size_unit": "GB" - }, - "Krakenfiles": { - "apiKey": False, - "url": "{server}", - "api_url": "https://krakenfiles.com/", - "download_url_base": "https://krakenfiles.com", - "server_url": "https://krakenfiles.com/api/server/available", - "size_limit": 1, - "size_unit": "GB" - }, - "Transfer_sh": { - "apiKey": False, - "url": "https://transfer.sh/{file_name}", - "api_url": "https://transfer.sh/", - "download_url_base": "https://transfer.sh/", - "size_limit": 10, - "size_unit": "GB" - }, - "TmpFiles": { - "apiKey": False, - "url": "https://tmpfiles.org/api/v1/upload", - "api_url": "https://tmpfiles.org/api", - "download_url_base": "https://tmpfiles.org/", - "size_limit": 100, - "size_unit": "MB" - }, - "Mixdrop": { - "apiKey": True, - "url": "https://ul.Mixdrop.ag/api", - "api_url": "https://ul.Mixdrop.ag/api", - "download_url_base": "https://Mixdrop.ag/f/", - "size_limit": 10, - "size_unit": "GB" - }, - "1Fichier": { - "apiKey": False, - "url": "https://{server}/upload.cgi?id={upload_id}", - "api_url": "https://api.1fichier.com/v1/upload/", - "download_url_base": "https://1fichier.com/?", - "initialize_url": "https://api.1fichier.com/v1/upload/get_upload_server.cgi", - "finalize_url": "https://{server}/end.pl?xid={upload_id}", - "size_limit": 300, - "size_unit": "GB" - }, - "Fileio": { - "apiKey": False, - "url": "https://file.io/?title={file_name}", - "api_url": "https://file.io/", - "download_url_base": "https://file.io/", - "patch_url": "https://file.io/{file_id}", - "size_limit": 2, - "size_unit": "GB" - }, - "EasyUpload": { - "apiKey": False, - "url": "https://upload{number}.easyupload.io/action.php", - "api_url": "https://easyupload.io/", - "download_url_base": "https://easyupload.io/", - "initialize_url": "https://easyupload.io/action.php", - "size_limit": 10, - "size_unit": "GB" - }, - "AnonTransfer": { - "apiKey": False, - "url": "https://anontransfer.com/upload.php", - "api_url": "https://anontransfer.com/", - "download_url_base": "https://anontransfer.com/download/", - "size_limit": 5, - "size_unit": "GB" - }, - "1CloudFile": { - "apiKey": False, - "url": "https://1cloudfile.com/ajax/file_upload_handler", - "api_url": "https://1cloudfile.com/", - "download_url_base": "https://1cloudfile.com/", - "size_limit": 5, - "size_unit": "GB" - }, - "Anonymfile": { - "apiKey": False, - "url": "https://anonymfile.com/upload", - "api_url": "https://anonymfile.com/", - "download_url_base": "https://anonymfile.com/", - "size_limit": 7, - "size_unit": "GB" - }, - "FileSi": { - "apiKey": False, - "url": "https://file.si/api/v1/upload", - "api_url": "https://file.si/", - "download_url_base": "https://file.si/", - "size_limit": 7, - "size_unit": "GB" - }, - "ClicknUpload": { - "apiKey": False, - "url": "{server}", - "api_url": "https://clicknupload.click", - "download_url_base": "https://clicknupload.vip/", - "size_limit": 2, - "size_unit": "GB" - }, - "FileUpload": { - "apiKey": False, - "url": "https://up.file-upload.net/upload.php", - "api_url": "https://file-upload.net/", - "download_url_base": "https://file-upload.net/download-{file_id}/{server_name}.html", - "size_limit": 5, - "size_unit": "GB" - }, - "BowFile": { - "apiKey": True, - "url": "https://bowfile.com/api/v2/file/upload", - "api_url": "https://bowfile.com/", - "download_url_base": "https://bowfile.com/", - "authorize_url": "https://bowfile.com/api/v2/authorize", - "size_limit": 5, - "size_unit": "GB" - }, - "HexUpload": { - "apiKey": False, - "url": "{server}", - "api_url": "https://hexupload.net/", - "download_url_base": "https://hexupload.net/", - "size_limit": 2, - "size_unit": "GB" - }, - "UserCloud": { - "apiKey": False, - "url": "{server}", - "api_url": "https://userscloud.com/", - "download_url_base": "https://userscloud.com/", - "size_limit": 5, - "size_unit": "GB" - }, - "DooDrive": { - "apiKey": True, - "url": "{server}", - "api_url": "https://doodrive.com/", - "download_url_base": "https://doodrive.com/f/", - "initialize_url": "https://doodrive.com/api/v1/upload", - "finalize_url": "{server}", - "size_limit": 2, - "size_unit": "GB" - }, - "uFile": { - "apiKey": False, - "url": "{server}v1/upload/chunk", - "api_url": "https://ufile.io/", - "download_url_base": "https://ufile.io/", - "initialize_url": "{server}v1/upload/create_session", - "finalize_url": "{server}v1/upload/finalise", - "server_url": "https://ufile.io/v1/upload/select_storage", - "size_limit": 5, - "size_unit": "GB" - }, - "Download_gg": { - "apiKey": False, - "url": "https://download.gg/server/upload.php", - "api_url": "https://download.gg/", - "download_url_base": "https://download.gg/file-", - "size_limit": 25, - "size_unit": "GB" - }, - "Catbox": { - "apiKey": False, - "url": "https://catbox.moe/user/api.php", - "api_url": "https://catbox.moe/", - "download_url_base": "https://files.catbox.moe/", - "size_limit": 200, - "size_unit": "MB", - }, - "LitterBox": { - "apiKey": False, - "url": "https://litterbox.catbox.moe/resources/internals/api.php", - "api_url": "https://litterbox.catbox.moe/", - "download_url_base": "https://litter.catbox.moe/", - "size_limit": 1, - "size_unit": "GB" - }, - "Keep": { - "apiKey": False, - "url": "https://free.keep.sh/", - "api_url": "https://keep.sh/", - "download_url_base": "https://free.keep.sh/", - "size_limit": 500, - "size_unit": "MB" - }, - "TempSend": { - "apiKey": False, - "url": "https://tempsend.com/send", - "api_url": "https://tempsend.com/", - "download_url_base": "https://tempsend.com/", - "size_limit": 2, - "size_unit": "GB" - }, - "UsersDrive": { - "apiKey": False, - "url": "{server}", - "api_url": "https://usersdrive.com/", - "download_url_base": "https://usersdrive.com/{file_id}.html", - "size_limit": 2, - "size_unit": "GB" - }, - "Rapidgator": { - "apiKey": True, - "url": "{server}", - "api_url": "https://rapidgator.net/", - "download_url_base": "https://rapidgator.net/file/", - "initialize_url": "https://rapidgator.net/api/v2/user/login", - "server_url": "https://rapidgator.net/api/v2/file/upload", - "finalize_url": "https://rapidgator.net/api/v2/file/upload_info", - }, - "WDHO": { - "apiKey": False, - "url": "https://wdho.ru/core/page/ajax/file_upload_handler.ajax.php", - "api_url": "https://wdho.ru/", - "download_url_base": "https://wdho.ru/", - "size_limit": 5, - "size_unit": "GB" - }, - "Filesadmin": { - "apiKey": False, - "url": "https://filesadmin.com/ajax/file_upload_handler", - "api_url": "https://filesadmin.com/", - "download_url_base": "https://filesadmin.com/", - "size_limit": 3, - "size_unit": "GB" - }, - "Fastupload": { - "apiKey": False, - "url": "https://fastupload.io/upload", - "api_url": "https://fastupload.io/", - "download_url_base": "https://fastupload.io/", - "size_limit": 10, - "size_unit": "GB" - }, - "CyberFile": { - "apiKey": False, - "url": "https://cyberfile.me/ajax/file_upload_handler", - "api_url": "https://cyberfile.me/", - "download_url_base": "https://cyberfile.me/", - "size_limit": 10, - "size_unit": "GB" - }, - "Buzzheavier": { - "apiKey": False, - "url": "https://w.buzzheavier.com/", - "api_url": "https://buzzheavier.com/", - "download_url_base": "https://buzzheavier.com/f/" - }, - "Oshi": { - "comment": "Keep this one as low as possible. Its really a slow piece of shit.", - "apiKey": False, - "url": "https://oshi.at/?shorturl=1", - "api_url": "https://oshi.at/cmd", - "download_url_base": "https://oshi.at/", - "size_limit": 5, - "size_unit": "GB" - }, -} diff --git a/modules/buzzheavier.py b/modules/sites/buzzheavier.py similarity index 93% rename from modules/buzzheavier.py rename to modules/sites/buzzheavier.py index 3997878..2257ca1 100644 --- a/modules/buzzheavier.py +++ b/modules/sites/buzzheavier.py @@ -1,61 +1,60 @@ -# Import Standard Packages -import os -import random - -# Import Third Party Packages -import requests - -# Import Custom Modules -from main import DEBUG - - -class Buzzheavier: - def __init__(self, file: str, user_agent: str, proxy_list: list[str]=None, api_key: list=None) -> None: - self.file = file - self.proxy = random.choice(proxy_list) if proxy_list else None - self.user_agent = user_agent - self.file_name = os.path.basename(file) - self.api_key = api_key - - # Below is the website specific data - self.site: str = "Buzzheavier" - self.api_key_required: bool = False - self.site_url: str = "https://buzzheavier.com/" - self.upload_url: str = "https://w.buzzheavier.com/" - self.download_url_base: str = "https://buzzheavier.com/f/" - - self.headers: dict = { - "User-Agent": user_agent, - "Accept": "*/*", - "Content-Length": str(os.path.getsize(file)) - } - - def uploader(self) -> dict: - try: - with open(self.file, "rb") as file_upload: - full_url = f"{self.upload_url}{self.file_name}?expiry=10368000" - - file_contents = file_upload.read() - - response = requests.put( - full_url, - data=file_contents, - headers=self.headers, - proxies=self.proxy, - timeout=300 - ) - - if not response.status == 201: - raise Exception(response.status) - - try: - response_json = response.json() - file_id = response_json.get("id") - return {"status": "ok", "file_name": self.file_name, "file_url": f"{self.download_url_base}{file_id}"} - except Exception as e: - return {"status": "error", "file_name": self.file_name, "exception": str(e), "extra": f"Failed to get json data. Code: {response.status} | {response.data}"} - - except Exception as e: - # Return error message - return {"status": "error", "file_name": self.file_name, "exception": str(e), "extra": f"Upload Failed. Code fucked up."} +# Import Standard Libraries +import os +import random + +# Import Third-Party Libraries +import requests + +# Import Local Libraries + + +class Buzzheavier: + def __init__(self, file: str, user_agent: str, proxy_list: list[str]=None, api_key: list=None) -> None: + self.file = file + self.proxy = random.choice(proxy_list) if proxy_list else None + self.user_agent = user_agent + self.file_name = os.path.basename(file) + self.api_key = api_key + + # Below is the website specific data + self.site: str = "Buzzheavier" + self.api_key_required: bool = False + self.site_url: str = "https://buzzheavier.com/" + self.upload_url: str = "https://w.buzzheavier.com/" + self.download_url_base: str = "https://buzzheavier.com/f/" + + self.headers: dict = { + "User-Agent": user_agent, + "Accept": "*/*", + "Content-Length": str(os.path.getsize(file)) + } + + def uploader(self) -> dict: + try: + with open(self.file, "rb") as file_upload: + full_url = f"{self.upload_url}{self.file_name}?expiry=10368000" + + file_contents = file_upload.read() + + response = requests.put( + full_url, + data=file_contents, + headers=self.headers, + proxies=self.proxy, + timeout=300 + ) + + if not response.status == 201: + raise Exception(response.status) + + try: + response_json = response.json() + file_id = response_json.get("id") + return {"status": "ok", "file_name": self.file_name, "file_url": f"{self.download_url_base}{file_id}"} + except Exception as e: + return {"status": "error", "file_name": self.file_name, "exception": str(e), "extra": f"Failed to get json data. Code: {response.status} | {response.data}"} + + except Exception as e: + # Return error message + return {"status": "error", "file_name": self.file_name, "exception": str(e), "extra": f"Upload Failed. Code fucked up."} \ No newline at end of file diff --git a/modules/file_hash_calculator.py b/modules/utils/file_hash_calculator.py similarity index 90% rename from modules/file_hash_calculator.py rename to modules/utils/file_hash_calculator.py index d061674..e9f62e0 100644 --- a/modules/file_hash_calculator.py +++ b/modules/utils/file_hash_calculator.py @@ -1,38 +1,38 @@ -import hashlib -import os - -class FileHashCalculator: - """ - A class to calculate hash values of files. - - Attributes: - file (str): The path to the file. - hash_type (hashlib._Hash): The type of hash algorithm to be used. - hash (str): The hash value of the file. - """ - - def __init__(self, file: str): - """ - Initializes the FileHashCalculator object. - - Args: - file (str): The path to the file. - """ - self.file = file - self.hash_type = hashlib.md5() # Default hash algorithm is MD5 - self.hash = self._get_file_hash() - - def _get_file_hash(self): - """ - Calculates the hash value of the file. - - Returns: - str: The hash value of the file. - """ - - with open(os.path.basename(self.file), "rb") as file_hc: - # Read the file in chunks to handle large files - for chunk in iter(lambda: file_hc.read(4096), b""): - self.hash_type.update(chunk) - - return self.hash_type.hexdigest() +import hashlib +import os + +class FileHashCalculator: + """ + A class to calculate hash values of files. + + Attributes: + file (str): The path to the file. + hash_type (hashlib._Hash): The type of hash algorithm to be used. + hash (str): The hash value of the file. + """ + + def __init__(self, file: str): + """ + Initializes the FileHashCalculator object. + + Args: + file (str): The path to the file. + """ + self.file = file + self.hash_type = hashlib.md5(usedforsecurity=False) + self.hash = self._get_file_hash() + + def _get_file_hash(self): + """ + Calculates the hash value of the file. + + Returns: + str: The hash value of the file. + """ + + with open(os.path.basename(self.file), "rb") as file_hc: + # Read the file in chunks to handle large files + for chunk in iter(lambda: file_hc.read(4096), b""): + self.hash_type.update(chunk) + + return self.hash_type.hexdigest() diff --git a/modules/file_size_calculator.py b/modules/utils/file_size_calculator.py similarity index 97% rename from modules/file_size_calculator.py rename to modules/utils/file_size_calculator.py index 313500d..e7b0afd 100644 --- a/modules/file_size_calculator.py +++ b/modules/utils/file_size_calculator.py @@ -1,60 +1,60 @@ -class FileSizeCalculator: - """ - A class to calculate whether a file size exceeds a given limit. - - Attributes: - site_name (str): The name of the site. - file_size (int): The size of the file. - size_limit (int): The size limit to compare against. e.g. 4 - size_unit (str): The unit of the size limit. e.g. GB - """ - - def __init__(self, site_name: str, file_size: int, size_limit_int: int, size_limit_str: str): - """ - Initializes the FileSizeCalculator object. - - Args: - site_name (str): The name of the site. - file_size (int): The size of the file. - size_limit (int): The size limit to compare against. - size_unit (str): The unit of the size limit. - """ - self.site_name = site_name - self.file_size = file_size - self.size_limit_int = size_limit_int - self.size_unit_str = size_limit_str - - # Temporary variables - self.byte_units: dict = self._unit_declaration() - self.size_limit_bytes: int = 0 - - self.status: str = self._calculate_file_size() - - def _unit_declaration(self): - """ - Returns a dictionary with byte units as keys and their respective multipliers as values. - - Returns: - dict: A dictionary mapping byte units to their multipliers. - """ - return { - 'B': 1, - 'KB': 1024, - 'MB': 1024 * 1024, - 'GB': 1024 * 1024 * 1024, - 'TB': 1024 * 1024 * 1024 * 1024, - 'PB': 1024 * 1024 * 1024 * 1024 * 1024, - } - - def _calculate_file_size(self): - """ - Compares the file size with the size limit and returns the status. - - Returns: - str: The status of the file size compared to the limit. OK or SIZE_ERROR. - """ - self.size_limit_bytes = self.size_limit_int * self.byte_units.get(self.size_unit_str.upper(), 1) - - if self.file_size > self.size_limit_bytes: - return "SIZE_ERROR" - return "OK" +class FileSizeCalculator: + """ + A class to calculate whether a file size exceeds a given limit. + + Attributes: + site_name (str): The name of the site. + file_size (int): The size of the file. + size_limit (int): The size limit to compare against. e.g. 4 + size_unit (str): The unit of the size limit. e.g. GB + """ + + def __init__(self, site_name: str, file_size: int, size_limit_int: int, size_limit_str: str): + """ + Initializes the FileSizeCalculator object. + + Args: + site_name (str): The name of the site. + file_size (int): The size of the file. + size_limit (int): The size limit to compare against. + size_unit (str): The unit of the size limit. + """ + self.site_name = site_name + self.file_size = file_size + self.size_limit_int = size_limit_int + self.size_unit_str = size_limit_str + + # Temporary variables + self.byte_units: dict = self._unit_declaration() + self.size_limit_bytes: int = 0 + + self.status: str = self._calculate_file_size() + + def _unit_declaration(self): + """ + Returns a dictionary with byte units as keys and their respective multipliers as values. + + Returns: + dict: A dictionary mapping byte units to their multipliers. + """ + return { + 'B': 1, + 'KB': 1024, + 'MB': 1024 * 1024, + 'GB': 1024 * 1024 * 1024, + 'TB': 1024 * 1024 * 1024 * 1024, + 'PB': 1024 * 1024 * 1024 * 1024 * 1024, + } + + def _calculate_file_size(self): + """ + Compares the file size with the size limit and returns the status. + + Returns: + str: The status of the file size compared to the limit. OK or SIZE_ERROR. + """ + self.size_limit_bytes = self.size_limit_int * self.byte_units.get(self.size_unit_str.upper(), 1) + + if self.file_size > self.size_limit_bytes: + return "SIZE_ERROR" + return "OK" diff --git a/modules/logger.py b/modules/utils/logger.py similarity index 96% rename from modules/logger.py rename to modules/utils/logger.py index 1c64a22..133985d 100644 --- a/modules/logger.py +++ b/modules/utils/logger.py @@ -1,99 +1,99 @@ -# Import Standard Libraries -import os -import platform -from datetime import datetime - -# Import Third-Party Libraries -import psutil -from termcolor import colored - -# Import Local Libraries -from .storage import __version__ as version -from .pretty_print import PrettyPrint - -class Logger: - - def __init__(self, message: str=None, extra: str=None, severity: str=None, site: str=None, size_limit: str=None) -> None: - # File and Error Specific - self.file_name = f"{datetime.today().strftime('%Y-%m-%d')}-runtime.log" - self.message = message - self.extra_info = extra - self.severity = severity - self.site = site - self.exception_str: str = None - self.size_limit = size_limit - - # OS Specific for logging - self.os_bit: str = platform.machine() - self.os_name: str = platform.system() - self.device_name: str = platform.node() - self.os_version: str = platform.version() - self.os_cpu_name: str = platform.processor() - self.os_cpu_cores: int = psutil.cpu_count(logical=False) - self.tool_version: str = version - self.os_ram: float = self._get_ram() - self.os_release: str = platform.release() - self.log_date: str = datetime.utcnow().strftime("%a %d-%b %H:%M:%S UTC %Y") - self.os_family: str = os.name - self.unix_time: float = datetime.utcnow().timestamp() - - self.pretty_print_instance = PrettyPrint() - - self._create_log_file() - self._log_event() - - def _get_ram(self) -> float: - # Get information about virtual memory - virtual_mem = psutil.virtual_memory() - - # Get the total RAM in bytes - total_ram = virtual_mem.total - - # You can convert it to Gigabytes (GB) for better readability - return total_ram / (1024 ** 3) - - def _create_log_file(self) -> None: - """ - Creates the log file if it doesn't exist. Adds the OS information to the log file for additional help when reporting issues. - """ - if not os.path.exists(f"logs/{self.file_name}"): - with open(self.file_name, "w", encoding="utf-8") as log_file: - log_file.write( - f""" - OS: {self.os_bit} | {self.device_name} {self.log_date} | {self.os_name} ({self.os_family}) - CPU: {self.os_cpu_name} cores: {self.os_cpu_cores} - RAM: {self.os_ram} GB - Tool: {self.tool_version} - Date: {self.unix_time} - """ - ) - - # TODO: Add more error handling like debug stuff - def _log_event(self) -> None: - """ - Logs the event based on the severity of the error. - """ - - # Handle most common errors - if self.severity == "error": - - # If the site is Transfer_sh or Keep then print a different message because they need to fix it - if self.site in ["Transfer.sh", "Keep"]: - print(f"{self.pretty_print_instance.error} {colored(self.site, 'yellow')} fucked up again while uploading the file {colored(self.file_name, 'light_blue')}. Don't Report this! Its a known issue they need to fix.") - else: - print(f"{self.pretty_print_instance.error} An error occurred while uploading the file {colored(self.file_name, 'light_blue')} to {colored(self.site, 'yellow')}! Please report this. Exception: {colored(self.extra_info, 'red')}") - self.exception_str = f"An error occurred while uploading the file {self.file_name} to {self.site}! Please report this. Exception: {self.extra_info}" - - elif self.severity == "size_error": - print(f"{self.pretty_print_instance.error} File size of {colored(self.file_name, 'light_blue')} to big for {colored(self.site, 'yellow')}! Compress it to fit the max size of {colored(self.size_limit, 'yellow')}") - self.exception_str = f"File size of {self.file_name} to big for {self.site}! Compress it to fit the max size of {self.size_limit}" - - elif self.severity == "debug": - print(f"{self.pretty_print_instance.debug} {colored(self.message, 'cyan')}") - - else: - print(f"{self.pretty_print_instance.error} An unknown error occured while uploading the file {colored(self.file_name, 'light_blue')} to {colored(self.site, 'yellow')}! Please report this. Exception: {colored(self.extra_info, 'red')}") - self.exception_str = f"An unknown error occured while uploading the file {self.file_name} to {self.site}! Please report this. Exception: {self.extra_info}" - - with open(self.file_name, "a", encoding="utf-8") as log_dumper: - log_dumper.writelines(f"{datetime.now()} | {self.message} | {self.exception_str}\n") +# Import Standard Libraries +import os +import platform +from datetime import datetime + +# Import Third-Party Libraries +import psutil +from termcolor import colored + +# Import Local Libraries +from .utils/storage import __version__ as version +from .pretty_print import PrettyPrint + +class Logger: + + def __init__(self, message: str=None, extra: str=None, severity: str=None, site: str=None, size_limit: str=None) -> None: + # File and Error Specific + self.file_name = f"{datetime.today().strftime('%Y-%m-%d')}-runtime.log" + self.message = message + self.extra_info = extra + self.severity = severity + self.site = site + self.exception_str: str = None + self.size_limit = size_limit + + # OS Specific for logging + self.os_bit: str = platform.machine() + self.os_name: str = platform.system() + self.device_name: str = platform.node() + self.os_version: str = platform.version() + self.os_cpu_name: str = platform.processor() + self.os_cpu_cores: int = psutil.cpu_count(logical=False) + self.tool_version: str = version + self.os_ram: float = self._get_ram() + self.os_release: str = platform.release() + self.log_date: str = datetime.utcnow().strftime("%a %d-%b %H:%M:%S UTC %Y") + self.os_family: str = os.name + self.unix_time: float = datetime.utcnow().timestamp() + + self.pretty_print_instance = PrettyPrint() + + self._create_log_file() + self._log_event() + + def _get_ram(self) -> float: + # Get information about virtual memory + virtual_mem = psutil.virtual_memory() + + # Get the total RAM in bytes + total_ram = virtual_mem.total + + # You can convert it to Gigabytes (GB) for better readability + return total_ram / (1024 ** 3) + + def _create_log_file(self) -> None: + """ + Creates the log file if it doesn't exist. Adds the OS information to the log file for additional help when reporting issues. + """ + if not os.path.exists(f"logs/{self.file_name}"): + with open(self.file_name, "w", encoding="utf-8") as log_file: + log_file.write( + f""" + OS: {self.os_bit} | {self.device_name} {self.log_date} | {self.os_name} ({self.os_family}) + CPU: {self.os_cpu_name} cores: {self.os_cpu_cores} + RAM: {self.os_ram} GB + Tool: {self.tool_version} + Date: {self.unix_time} + """ + ) + + # TODO: Add more error handling like debug stuff + def _log_event(self) -> None: + """ + Logs the event based on the severity of the error. + """ + + # Handle most common errors + if self.severity == "error": + + # If the site is Transfer_sh or Keep then print a different message because they need to fix it + if self.site in ["Transfer.sh", "Keep"]: + print(f"{self.pretty_print_instance.error} {colored(self.site, 'yellow')} fucked up again while uploading the file {colored(self.file_name, 'light_blue')}. Don't Report this! Its a known issue they need to fix.") + else: + print(f"{self.pretty_print_instance.error} An error occurred while uploading the file {colored(self.file_name, 'light_blue')} to {colored(self.site, 'yellow')}! Please report this. Exception: {colored(self.extra_info, 'red')}") + self.exception_str = f"An error occurred while uploading the file {self.file_name} to {self.site}! Please report this. Exception: {self.extra_info}" + + elif self.severity == "size_error": + print(f"{self.pretty_print_instance.error} File size of {colored(self.file_name, 'light_blue')} to big for {colored(self.site, 'yellow')}! Compress it to fit the max size of {colored(self.size_limit, 'yellow')}") + self.exception_str = f"File size of {self.file_name} to big for {self.site}! Compress it to fit the max size of {self.size_limit}" + + elif self.severity == "debug": + print(f"{self.pretty_print_instance.debug} {colored(self.message, 'cyan')}") + + else: + print(f"{self.pretty_print_instance.error} An unknown error occured while uploading the file {colored(self.file_name, 'light_blue')} to {colored(self.site, 'yellow')}! Please report this. Exception: {colored(self.extra_info, 'red')}") + self.exception_str = f"An unknown error occured while uploading the file {self.file_name} to {self.site}! Please report this. Exception: {self.extra_info}" + + with open(self.file_name, "a", encoding="utf-8") as log_dumper: + log_dumper.writelines(f"{datetime.now()} | {self.message} | {self.exception_str}\n") diff --git a/modules/storage.py b/modules/utils/storage.py similarity index 97% rename from modules/storage.py rename to modules/utils/storage.py index b86bac3..78d4bc0 100644 --- a/modules/storage.py +++ b/modules/utils/storage.py @@ -1,8 +1,8 @@ -# Import Standard Libraries -import os - -# This file simply holds some data that is used throughout the project. - -__version__: str = "2.0.0" -__user_agent__: str = f"mul-tor/{__version__}- (by Official Husko on GitHub)" -__dev_debug__: bool = os.path.exists(".DEBUG") +# Import Standard Libraries +import os + +# This file simply holds some data that is used throughout the project. + +__version__: str = "2.0.0" +__user_agent__: str = f"mul-tor/{__version__}- (by Official Husko on GitHub)" +__dev_debug__: bool = os.path.exists(".DEBUG") diff --git a/presets/cs-rin-ru.json b/presets/cs-rin-ru.json index 2c41622..ade0db5 100644 --- a/presets/cs-rin-ru.json +++ b/presets/cs-rin-ru.json @@ -1,34 +1,34 @@ -{ - "identifier": "husko.csrinru", - "name": "CS.Rin.Ru", - "author": "Husko", - "description": "A list of all approved hosts for cs.rin.ru.", - "version": "1.0.0", - "site-url": "https://f95zone.to/", - "source-url": "https://f95zone.to/threads/approved-file-hosts-updated-2022-08-08.3432/", - "repo-url": "https://github.com/husko/mul-tor", - "sites": [ - "1CloudFile", - "1Fichier", - "Archive", - "Bowfile", - "Clicknupload", - "Daily Uploads", - "Gofile", - "Google Drive", - "HexUpload", - "Krakenfiles", - "MediaFire", - "MEGA", - "Mixdrop", - "Pixeldrain", - "Qiwi", - "Sendcm", - "SendSpace", - "Sendfile", - "UploadBuzz", - "Userscloud", - "Yandex.Disk" - ], - "link-format": "[URL='{file_url}']{site_name}[/URL]" +{ + "identifier": "husko.csrinru", + "name": "CS.Rin.Ru", + "author": "Husko", + "description": "A list of all approved hosts for cs.rin.ru.", + "version": "1.0.0", + "site-url": "https://f95zone.to/", + "source-url": "https://f95zone.to/threads/approved-file-hosts-updated-2022-08-08.3432/", + "repo-url": "https://github.com/husko/mul-tor", + "sites": [ + "1CloudFile", + "1Fichier", + "Archive", + "Bowfile", + "Clicknupload", + "Daily Uploads", + "Gofile", + "Google Drive", + "HexUpload", + "Krakenfiles", + "MediaFire", + "MEGA", + "Mixdrop", + "Pixeldrain", + "Qiwi", + "Sendcm", + "SendSpace", + "Sendfile", + "UploadBuzz", + "Userscloud", + "Yandex.Disk" + ], + "link-format": "[URL='{file_url}']{site_name}[/URL]" } \ No newline at end of file diff --git a/presets/f95.json b/presets/f95.json index 0cf9644..17d0d3f 100644 --- a/presets/f95.json +++ b/presets/f95.json @@ -1,29 +1,29 @@ -{ - "identifier": "husko.f95", - "name": "F95", - "author": "Husko", - "description": "A list of all approved hosts for F95.", - "version": "1.2.0", - "site-url": "https://f95zone.to/", - "source-url": "https://f95zone.to/threads/approved-file-hosts-updated-2022-08-08.3432/", - "repo-url": "https://github.com/husko/mul-tor", - "sites": [ - "Pixeldrain", - "Gofile", - "Oshi", - "Delafil", - "Files.dp.ua", - "FilesFm", - "Krakenfiles", - "Mixdrop", - "Anonymfile", - "Download.gg", - "Catbox", - "LitterBox", - "WDHO", - "Filesadmin", - "Fastupload", - "CyberFile" - ], - "link-format": "[URL='{file_url}']{site_name}[/URL]" +{ + "identifier": "husko.f95", + "name": "F95", + "author": "Husko", + "description": "A list of all approved hosts for F95.", + "version": "1.2.0", + "site-url": "https://f95zone.to/", + "source-url": "https://f95zone.to/threads/approved-file-hosts-updated-2022-08-08.3432/", + "repo-url": "https://github.com/husko/mul-tor", + "sites": [ + "Pixeldrain", + "Gofile", + "Oshi", + "Delafil", + "Files.dp.ua", + "FilesFm", + "Krakenfiles", + "Mixdrop", + "Anonymfile", + "Download.gg", + "Catbox", + "LitterBox", + "WDHO", + "Filesadmin", + "Fastupload", + "CyberFile" + ], + "link-format": "[URL='{file_url}']{site_name}[/URL]" } \ No newline at end of file diff --git a/presets/template.json5 b/presets/template.json5 index e6d0ece..433b814 100644 --- a/presets/template.json5 +++ b/presets/template.json5 @@ -1,29 +1,29 @@ -{ - // All lines that have a double slash are comments. Remove them and change the file extension to .json. - - - // Identifier is the name of the preset and should be unique. It consists of author.preset_name - "identifier": "husko.template", - // Name is the name of the preset that is visible in the Tool. - "name": "Template", - // Author is the author of the preset. - "author": "Husko", - // Description is the description of the preset. - "description": "This is a Template Preset", - // Version is the version of the preset. It is used to check for updates using the Repo URL. - "version": "1.0.0", - // Site-URL is the URL of the site that the preset is made for. - "site-url": "https://github.com/husko/mul-tor/presets/template.json", - // Source-URL is the URL of the forum post with the list of approved hosts. - "source-url": "https://f95zone.to/threads/approved-file-hosts-updated-2022-08-08.3432/", - // Repo-URL is the URL where the preset is hosted. - "repo-url": "https://github.com/husko/mul-tor", - // Sites is the list of sites that are whitelisted/should be auto loaded for the target website. - "sites": [ - "Example1", - "Example2", - "Example3" - ], - // Link-Format is the format of the links that are generated. Should make the process of sharing links easier. - "link-format": "[URL='{file_url}']{site_name}[/URL]" +{ + // All lines that have a double slash are comments. Remove them and change the file extension to .json. + + + // Identifier is the name of the preset and should be unique. It consists of author.preset_name + "identifier": "husko.template", + // Name is the name of the preset that is visible in the Tool. + "name": "Template", + // Author is the author of the preset. + "author": "Husko", + // Description is the description of the preset. + "description": "This is a Template Preset", + // Version is the version of the preset. It is used to check for updates using the Repo URL. + "version": "1.0.0", + // Site-URL is the URL of the site that the preset is made for. + "site-url": "https://github.com/husko/mul-tor/presets/template.json", + // Source-URL is the URL of the forum post with the list of approved hosts. + "source-url": "https://f95zone.to/threads/approved-file-hosts-updated-2022-08-08.3432/", + // Repo-URL is the URL where the preset is hosted. + "repo-url": "https://github.com/husko/mul-tor", + // Sites is the list of sites that are whitelisted/should be auto loaded for the target website. + "sites": [ + "Example1", + "Example2", + "Example3" + ], + // Link-Format is the format of the links that are generated. Should make the process of sharing links easier. + "link-format": "[URL='{file_url}']{site_name}[/URL]" } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f37ea11..c8afd6a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,21 +1,21 @@ -about-time==4.2.1 -alive-progress==3.1.5 -ansicon==1.89.0 -blessed==1.20.0 -certifi==2024.2.2 -charset-normalizer==3.3.2 -editor==1.6.6 -grapheme==0.6.0 -idna==3.7 -inquirer==3.2.4 -jinxed==1.2.1 -plyer==2.1.0 -psutil==5.9.8 -readchar==4.1.0 -requests==2.32.2 -runs==1.2.2 -six==1.16.0 -termcolor==2.4.0 -urllib3==2.2.1 -wcwidth==0.2.13 -xmod==1.8.1 +about-time==4.2.1 +alive-progress==3.1.5 +ansicon==1.89.0 +blessed==1.20.0 +certifi==2024.2.2 +charset-normalizer==3.3.2 +editor==1.6.6 +grapheme==0.6.0 +idna==3.7 +inquirer==3.2.4 +jinxed==1.2.1 +plyer==2.1.0 +psutil==5.9.8 +readchar==4.1.0 +requests==2.32.2 +runs==1.2.2 +six==1.16.0 +termcolor==2.4.0 +urllib3==2.2.2 +wcwidth==0.2.13 +xmod==1.8.1 diff --git a/test.png b/test.png deleted file mode 100644 index 474e06f58a350a083cd813e20d8f3d5fd00bf0aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 957832 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

!s(VSi*GFA3W- zh0{Z@zs#D)gfCf{=~9JzhR>tc<_2l1r$=v4uHHDKeLO+$>2m{m2J(#VLIl4(X63w3 zFCJ@w0`880zJ2h!i@wI!>qpQ-pQ103INj2|grDzV9%a0K=wEhu|KF6IZLClDdn@px zx9_rS5z_pCpIt3VuwBPY;MM_!Z>k=s0b@2&VU2UmP$q zFhe{;7~*N(Y#%OTID5+go$=zC&-7wgubzQDf9v_%zK>||Ss2$DZ@75 zJZ5rdl!Aus(G!W^<8NvCw+ZcpOh(n$0Uz}SfLeXzmM zKb962tIE(1=I5hdgct_Ov8W8q4ac@(UXk_{9dCYCrN@Tn&+ z%K{&uPJxf!y=0xz!OH+?GgN5La*`q zJ$|t(&)|FotY!~xp*jM zW=kkKnp|`;)qv??KwjU3H~5Xt%}Y&Fv&1K-Yp7=w937r-%j9u-MMVUeU16-yTW zC%|cayxbhgEr4-XQ!CZY&FYO~DCR!&as1$<@k(MpV}g&vNDY%Z+;lx?_)P4Q6c!-? z0JY#S7_AI-2nv!I+)RYE0=@~GnpUqIA&s8JmL5}TA{E~?<7SEqU^165DMbgLf{ryG zjXMCq7Y$>8`+6ky?zD&34Sop+++OS5dLU<-F=8DfeoL10dNEI z20wcD2z=J~bG`MaxIddK^5F57Tw6IKHGrF%nrd`R2{P1ME0<4A%bEExxiCKp_?wZ& z{%Uz}`J|klfzjMjrXD}muPe?;Rp?_@Gd}2w3(_PfD@lufj}Np;E)43dlt`(C;oaR_ zDc4R;%KeQw+1i+p+tS=rrKgr;S4eMr9g{Hc73`}I7aXmNg0h6cI- zies9XrMjvN56uEeK_{f4q3FD#@vw}6SnsR5t5jK~zy* z58xV-uFg&w8S0ZT7?Sa^9M6@i;f1UXSW%LvWAiG?^3c&oNk7NtB}L-F765oEl%CFN zSwA%o2%eC^z7}c1IT-41l$qI1nVIg9TL8E13jn|AE`V{hl;-Ebc!-y|v36;#HQ-m2 zpM&$#B`3zZ6{gND4awX@w{*0y12^LXnY@HvIlh_ZIvnT7P(yyEu|e;cj?Duw@#PRf zk08bIZpHb45gbb~`povGG8r9gmZgP3xj;|e@|4`bK3+dLC0CXRY5+Q1U+%|ch@qLj zz-MK_@2mrQ^a3;SkA=Jwiz6~O-USFR*D;6$y>jeFVQ#uU$QWKqj~pTIc;GQ(9669@ zK+hZK4plres$m@(MtCR&hX5J@ccn$ydVW|Agf9roa19%4%A|#$hx4}p&}+k#u?V zXTT%X-X1}3+Y9!rcC7$?yY~TqdjPpT2mFqJKFWZf8SA$Xe&|m;kpt{M0Cfs^8@T_? ze0%@%1Uw2x zo(JHpU_5!ePyW{NUB>=TXz{oFe{S-3POS7h0vg8~QT*()jK6JqL~k0sVlZ%_WQgOL zJ>qvs^nPT(z=qwRN{7MCL@3N~3A+IXIIpt-JlIt<&V9u7yr55CHUy&2NE0R>WM4+( zUbmf*jef(_=3|H*`zL0P?(OcB<%M}Xo4Pco1LqS!qGF@59gYiQ=0^NJj!Vl>r~nSw z$9b)3gJXn7gWh9YWBAqTMVoqR1G@c5jooE83XtF?o6aCb`%kz?XQ z`{!G84HJp|4{4|cV$(iC#QqY;PgK30sh@Q}k?6&Vmh86gtLJ>pK^geF7p7KCt|Fwh z=T%>78(zI;yRv)}9S_QSjiBme6rCq;vK^gp+9IOwZW|{SV|M zLjORF*c;3yStO}Oc1RsY-?20F3J~jsTVw5NA)foNKr?QQF0o&7{1$YWny+7(U%zwu zsnn=bxkk!Es!nVKxcC(Uw^v7`@fFQkkzY;%;X5|6Kuykh1vS-ux`d;#n+Ns-AaqymR-M}&I zkms+F7k1A+31b;Eeb?Mn4~dXIGS-pLvCq;mC+ML~wg zvtP1WDp1k1C<6?{zEx)k0KBPBQg#K%kt}p;vgej{4-fqT7`iSiQvOnZAI6Jr+LFEG zk|m-~Lpf!Goaxe%Ly%~5`Qx=C!1|wNu7gm`qXkQj;BV|{%dnp12<&f1ObZB6wnuW_ z91zY!+n^XrbOs|H&qD#bixzFbbiWv$9G6clbO_iQiZ$Zz*o`Nv|HqPxa^ZZxz>R8Y zH+VQU>}yn^mk*WC21qX2Tt3f zXke{V`7j~>4^*ck#qacA1Cx{fkQMwtZ{hQjOh`s1Bfla_c4a7bM+r0Y%dT9IWA;G8 z_`8vjNn0P1)Iiyxsg9RpQ&fLt&}nGY+`A}sj7CW)s~^7tu<#t9eJsQKiAF7zmPuZ(9>J@$yuu*nO!&DcU2 z$$Tk(Ip;_JCz3#UH9K86LXNg^EV!?Ma5-+qoMH}AZQ6bH^z`){@K3u-MD=bsByX9& zYgMGF_*7wVAxaMv)wj2K{_>07Z8{tTN%DIhDPAq#dI{>;UZ)8r2Xt(5-D8&%F`8R~N^#*LI#R-Q^lUG%O$+;vzCq?s5qURYKX}?&3e$PW?!xAJ z)5U+KC?QYBNm@|k^U)7OKDwd%%BCq7W!&tn3rzL~jXO!e6oc6hv=RYti-a@#;?OL# z*hWK}Rxj~pGX}2il%|gm$m#~``8MtilL z4J?CB;xE3142ECWVg=8dj6VMYIps7XVxVmB-?T*>BuR}$Szbu8aPri#phXLxUiDTT zg|v))*`G_X<@;nXfDrwivl{5R&E%C&k-isptuyr7yXEaz_s^TL$RtSLStC`@PE)Bd z2@BxmL#98{y@GNF#tCD+Z^-e%m5-@*&i!UpIlcN;45*>8U@?kw?5+{wAdk^(ZTHDw z@70Fn@ATZuP)zx~iN9cURmmo~`gm1BT4DrN*L0#eD;_dFa7YcCnU)+xMV|2!S(}dV zVv=+9=+5&4VLvji2sgLV@4-#c#=XALw<|x_Ymvvd3(|2UCego(E>qju-kywZW+C3* zbGl9o!>^B34=0dP>mbCMKA_7?J=}f?M1bK|?qKtNk`g-1aABuKYE?64D<~EKpD-={ zw<=tb0$@*M_knxgJBevCMS{%2Q5)6icfMk;+U278ZGFNKfOndo;HVL_x0rsAsI}s7 zk~A#Ks$Y+Nian6SRFzWIW+@W#R(F*@%nAyt61zKj6H8P1kB%n4uI(m==Ejma=vtOz zYqmLfa+-_m42MV41rRpMyh-ucdQH}D*M}P+CGTIogy-KYh?~&S{!Xi-=hexqyBVT( zj5jgaYE|jmiA@8$97ZrCU$FodyIB{@xyuCUAF$K>Tvr8^TyG+j_vi zk0>B-F)d`+a-!Yo-#Fi&*wUudjRWiV*Fsv14%p+5Mc!A6Tp%=pI|XbuxVguionZdP z^EL@j&+L!RP^$Q6^nV`RQ~3~pcoJs=mJ`k~HHOA4Z#XOazIyudzqjZ)CJ^?OpcFqF zZ{~e60J{)ZUhz&28)7A~&5;eLDJzh(QeG)Ny|)^Cy^6Zlyk1R<6ts`Hw3+q-YC8U0 zT3X1c+4Y3N{r~)$yC<5slMBINk~1E&`g7{^rz)sRQZtN;Bql|_YV4V;vW;+yk9e@;*ziD{Rhz%BX*01^_lLAZi&i|F4kQy@Jt6c;5+KRNw5&Dpu#dK9QaKX}R&t(cO}{=|$k z%(ktJ-zPuSaIXDo&dB}Hm%5#Hy_^Q<;UafAD2UZ7kD{~j?E4K?O4+$C_U&zWmN zaUmR6%D}W;W``3>#AcK_pd>B4bYK0U_c9QtDnIp0Ab9RoakofJLhkL$W@s&FmFbdo zb?9OdUd#bd_SUH)M6itf=thw&3-w9+E5PPai)2}#g9KKqLPv%qxCQ{11jFfI;s7QGq;35p~J`ilxJ79y+50r^gRv`3txxPzAy z05XxCu=DWjgVTKOgN1#aV&%=DZ%0L>F*9U3?;&vOef92?^wO26$FxlQBIEq(VaZie z0t-ZmTQL)r^S{eCuAWt~q_6XL_q&hM>^jEj@$-M7+Lk4oX-itsMbtBS=AN&YLpnLr zeMXd7?$a zJZ5BxuMcs5NHPHN1} zjZ4qj0@(kELW~9s4IJdvmyi>3xfEzdHlsN#|MI~%Sb}hf^Oc!mAVHlJ*YOwwvB*x_ z+PxUcX=w0!{=xcRMQ5p9nFFA|2jT7sB+wm~{*vl80r?m_N}rw%{rpWlfiK)hop8u? zb`Weoh_qLGuy)y5LTo)hTj%dthMc{z>q@g9RxSR~5ixzV$xjEWq$QoaK*}=2_P!u0 z?YwZ1)~aKA^)TMObhFT_g(8hO4GqWQw7R9nQ`g68*>{ZAES^}ES%DiHeR~|LNlD3# z{#Zxxs16w)zu%3q=lffQRZ4s%pWDzteY|&^3JRf&gg0`Nuve6jV>tRwnmy8G zr@k-y^&u%)2g&?7Z~IlRW9*R@2j@L=M?RHoNn-7yF-b>k%A&0-ZHUvLFrT!Xuo<5u zdAuW2a?2z6AJm@&=(+BC{dtcw80s6lo9ro_Eb&0h`ac}nd!IwPG!H+O0$eyxsC03# z3{4mS1Xk}V-n%MCx5|+rjzN?ZB}*$rD`mxbi57tSqmJcr=oNOW;*=5Lu9>s)`N0rOv5(@pse@5Hk`g8S{|MC5ydnlR1v|!-o15l zm`$MOgZ0#O3R=fHnHZi-WrwgLCz(@V%=!Gl9Rn0b0plH(5YJ1earv=)caiR@h`g8` zrrL7s+&6hxot#2n276ydr)y{pX-lSWxqn$mrfKuCAUo=FP)%1eG|=>Km5QSX%Oks> z>UF1nLl!_{;N@STbEfl8ai1fsK9maAyp%<=1q3#KF>i+k8@*Ju40gAO_mvm`VEJ2v zMuf9{yIQ_%zOCQeF`h(E;7r6-Jt5T;m=ASNAIho>hLe5%^W~KrnXAkl!4aSh2;)(Z z|88u=pE@)c5W<<+5)@=HJ+7<*rh1&8k&hnE^PT&VyiqduncJ;asy}diGGP_}>0ml8 zf!yE)#~-J#8soIU&j~m@k&xHja;trc`vm8Endom(Q2bes*8Y7R8Y=kK#NCZ%M`O=T zRVd99tgfyXm1g&GGFqH7ZHWA3JY;*fIxFwMRGH#&dnavOZ|73UxarXSZ!>>}tcW=O zJ9nZEYQlen$SFRH=K5=E^8tX%D?6AmGamUOeDJ6$fFxt98#3rF`Yibxgfp~k+*HS~ z(#*=qCo()_f4GFuJJT*~+3_3oa~T#Tn z+TVg9fY)o6{ac6sY-3ZksIwXA5b2tk9ZwoPNE*(XiSAfqpTS~XH`xanewgigiMC@PlyQUpA)4Q5=?@J;W zCO7B^T$IQ7?c@14V}mm=UXb_-euRVY;24RDvE-o-xjz$6e~@W>g%Q@mh4Eo5^Yw{# zJ2d<)2`FIaJRw4-NrD63rOLD&b^mhL{mu_E*6&toU=qw$u4eQSvzE6>(5aXEvOh;U z^mT+eIR&|I z)b2z;Ngu~Bjk40eMt#-hYTjrs3WISf_CL1Tj%z$poAl3x@1k`!Z!SPHlc0|UsO8nO zCba%;aj+Nvtt+w89vU@DJ?S4;|Lg9diHub*EUTT&@ppAcMw2`kQM@Ra{wTDywX17A znxK_(O&LUD|9CP2;ztked`iMSp0n3-%nPxXks^Bn3VT{0ryF)8TwtHJb3;#QC{>dRIs&KVO-d5z~CO|DjTCGNEq zIppU}hE4FIa?8mF*8x+`VAqiMe@=bj^^>cw)Vz-Z2#CJf@5#N~JY0F{@Av>1#2aE3 z%ZP5L(T~I~5frLk)y4#X?XPQ%h^aD_Ba>$ zj=((2q9WBNOQ4b*AfmTvE%$L~@(?>G|066!&n)_0t>a_Xq9OdBnp)c|@6M~+=+i_+ z{KWhzaouoyqARLHu{>4}i-X?IVx{T*_Vk=0lxR1w_M`C=RFO2El$)$<|7tk==;#3b zGPAbp%BJ)D{0S(+v~^RTI)X?EqUfnk)gIB4emO-^T@kki&%IDQ2vi|<<5L|9Oaw)H zmQ~Hxm75#ulq&UJ(3HeT&hfIwAY-(bNG?T!;`6lA>?2Hp2&os;xIC8JLZ%K!Fl}!^ z;ml4xMF|6YK~eT?R{gEEvy4PN9d8@6hXp$Wm5%`IZZ=Nur&h{d97@<3C6#c@rsEVQp?Fz)Rez`jv60PKISwrJbGMilgphcY&`-m6f$AX z$YbYqb2Fb@d?`5Mek@#x2@RGF~@cn$)UC< zIUARs?`kd^23#lpn}bBtO-q!um}Rg@*DxEGiz#msq_`0QUTN+6|c@0dh*3qwh$VmGOAY@ls$C*jO znLyp}r1HB6#g%;&?Xkkp`DeB^DxVH0xkFG=(NA9l8^H8|(2LwF|5OM4m7{xq+jvn% zvDygkx9#?-G9Yw5F(PGz1Z0=gIuXp_=R#}!-;e`4aF&Zyak&}!luYACjWeKn zTxXRjK?q>ly?^WaRI~ViWbc0$P~1ETL2FjBBlr{uV>k&q1xHZyfUUk4243uid}oN* z0r_ZX^nrKa%biGuHN!6|4a zql6I!C4bmvU$g=1>-onS=3Ls(k7Rs-)lnr15NIO2((D}^;H2?!u8~}fgX>x==d#-T zS?EnUBVlCruTKh67~q54DtH3yK!uz*>N$!QAEXgVz5Oj_o|vyiAH#TKPI$W0xHWos zoRK(U6q>q6O=^K+^ps4&Yneuck8WPDb<3Nh&Uqdp^z=!|0wDdJ?Kq$qDHp$sJEeTO z%yPao`b!_ifQ@ODl6l7&nYf0y=B9>)hSTHB)pEwq0`2d}WlNcM8}rd1)u%LgpAcJ# z)RiP5{5t4XW7^a~H13meGJS6MLVR(KXMy&g?{t-5R z9L31OQ%YrjenCvxZuspESe@;$Xk@S%x|~biANC;3pM&odeHqDRp&Qrb}6WU<8yp zBK&J5h63QeyQQ$fd8xS!(5(6LV_<4PCuYU6Z4mwVbDAOgURffbt8b8X6of53g2)7f zUiFYfPtE6i$bt+jppVF{%wC!p$(1xd_QPGwk&#(EeSQzxFKA);vP{tc8kqI;`3s{L zHzl+Hb*4QLGB79v3`5r)%~g8o|GnYc62#ImU_$f)tYOmlb70#86BBCasP-4W&(JpZ zbN09Ns+@(PAx@+!jI5ts!=PmS|3sZX2{*dSOn}yE&q&HCHv^oH)o2GO{7zTC$xPBm zX@KC&BtY2ZPYNAcjQ&~A@;ktrjTRoIRhQwT4u;Fc7@1EPiWu~lSMcQzle6h2i>K6w89!Z+{3hv}1{STWI%+?-x?ZH;7B z{0CW+(FsfQ>Y>-BMXXuvEG$4Bxygy=NxLn>4lhz{Y`C*j#pQf`A5BY|jrfzK>J||bzRKii zOuj=B12nTx!RF3_^!F^JE`Qwd@go}9XQW_lW6S~LBDb7#)AO96S%0_NYlA2TxIX4clPAEwJB_dKnwZYUv=H-97=*wUIJfsdLG{)UaPL|eB*pZ&#EufWD18Vh2NwwlB!urf|^ z!iqElLYlQdAF8On1cY44CaJqJB8V~ip|OFZubTJ8MjRX}R@<`EF5<~wH+&qw+12Ek zso$Om0Zo-GntL&t-#QUVO{*^!UEWxF)QQH!Hpn$2m!Dim+#FjFde1NFHY3}X<3pD2 zI?>w*8*FlvG@z@}H>YeCSvo|-#~dD}6<^5pdnAN!t<%7mF9|(4yF~SFkXDF%kx4Qq z=Iuu&@jG9ej;7i_(6%Sco1q@IzX9U1>g!6pL~mF-opJ-N3b2`Rdc!PVU1zeB z!y&(b(dT&USda%$4URXJT#Et^hOVDDju~`VUV^W`Sr=@Ea4uf>J>J`w7R33A^G&;S zjU9xO6PD=DJ%-3{(l@{E^Q;b?N2$4RqR#Zt$fKd7;Uk*4?NV(GJrNq+<$i(WWCu(- z$w}~9OgVKpq!%KqE-PNH1Cb?Z5BkrEDM%;reRd8zhM36G#r*Oper6gXoVlpHnV_j} zR<_r&WKA`z-)y+o5~VJr4dF60g`ivh)=3J4bZ4J9Na%-N$R9B5@sOz_xJTq-b#)&p zIi#hde)24&vH3jIGz!6KaWFK&zPY@-EGTXh;_dw;;`*!i`jJ#51qOK#=}i(b z1*|Q;agt)b-UD410k4bH7c+y^Ly{;qzp#s$&^1{+u`Oi-Q$=vD<;2r$@f?aQ?~4=e z_F~54#0mA!t>6_dE}$Rxot(VJY0gFBoli`RA3gIdtN^~j@A4(rz|$Q>b$e53X*1Mp z7DCiq+4k7(G7IFvHB*sm)^W*~BtyvF@HcDw@;kRN55{lPKOtIk{teZQbtk&H?O`(< zHD7D_zDstsV2gJ*Ra#P`SQW>aN5Iqmagk%S&aL4;?XGND|J965PW~2kv&ws!US#N! zI~(tVJSy2_jtBL|HZ&aKQ)r(2*3+H*8?zuBhp$-4Z@6KgnWmL6SKux zefYtF4V1Wia>5wsoE*EwkH5S5pN%q4z)mjZpKf*`$Uw`+Utcxm-gAI8;HQQ7^89mA zqaz)^tM!V7PBnh_oY&vSZPgvV-$qzGPYx=`;nO9vB6u`7ED>wQ9>n|Kz69u9!@Ubh z@QXhw3-dC@Xc`-!Zl=>_CPSkhX;UO`T5D7Ql&1+zr@0f2t-Q8$V~~H9a@=4!Zb3V( zv@({o#1~l4`=dr6gip0qVrrroX!Ly#u5x%{V#dMF&|G2Mn_uOE*{X=+ecAViY}hYZ zjessy7Y2|9fO~xCE{``4IFvfH%4K6R(M{qvdeQDP^40A@Oabs?F6{taC$1QGP|VTjTv}%R2SN3Bz6lm+CTOV182W|rXwye7~9H2F{K-uuvVHx zai_2TK@@c;@TF-K!%Mwb`RT^x>YVfQ{|ZpRHXldxpowd$P_sO@qd6V;4A?A0(7AMs zKXh;DF)6r(IKXNFXzah*#Y&yfiZ8-^Xs#&l=t0BI7GyEV;|}8Ih?*jS4QqY0u(pIw z*bhRjwSf@jl%ZcZmVSiw!i#%&y7yB-p$i{>C9H%r*MWuJT6Ms5Ur!XzyqIyFth9)> zli71amgi*Vf3~6@LGPaiH4WhqyqeyRQ@BB)RxkIE*={A~eYlT1)wF6O4URsIh4qr< zJXn9)54|a#r>F8$CqPuJa3}c*E*$;CUB0LQbw6UWeLOP2iuYnsdv5VoFlq%9`grn} z6Pk)kTGU;;ARBy%)hsSf{jOu*J2G`uFK?ccItJ?3>Z{%d5xyhiYg5B>IWtKYDI0;2 z2Xo1rjp)vYHUNf_qrVwV@FY>N^vd%R^Sf1W5)3$vMx+mk1D+Pi|=eNKQ#>A9d&D#j`pCMl#sO>c3z!RTV^qN z+wlT4%=&WFznA6qzm47-PO~pkUbEhg#ZCLY*ZuC+J;(j;ci&Pa$^v1WwK;jtno{|B zc4urJTC?RYQlxdr4@riJLp{dDJKNh|zBoudGcwisMmhytP_pyf7`8eaLUrNUQTmt* zLgtIZITs!Ppx6lFU!!gBXs+&cZ7B+xJGp%xs!|d8$?U)FFAlkl>5lKGrk@*nd$Tkz z!YMY$o3DQ7$1GEjUlxJ(s+XuQ7p%aGhll4}T!)5W&?T5C>W4K5??>Xb#|sKU^(>F9 z{rR~ws&)E*1UV*zTzEh!7QQFI?V~6z{T_T3R=vwUx3O{8B0AO2A#@lNK0QB!`V$7| zVz+7ezCdzp*XK}pUw)lLzU-Bn&l5oCkmHI9cNzk@D=Q!mV%PwZEX^u4>jMwtfxh&) z$0?fSy^~-CaaiWsq?~k;v;JLtC{>^r=145w=LcU}o>IL;xEGOA2qrnqg~_YxXHlWo z@>LktyIpCc9gFhvK%aD~cJtM+YJBrMUa^{H{bfx z(1YCHnKM-+@wAz@MF?OYL|OxmIJjmFoxY&J%&_blJj#xDX*?rHpTc z<=dbB;YF#!L{!~h?g}s({#jHcJ@beN@VHr;j?x>N{{Te@3jrb;6QY-Y%Vqk(fJiEU zy#~07y91hP3uR5;Vo9a_%|?968wj)@5@z!dt%^6$||nYZ|;Sdzn$BuKF#F*ENs@ zLxG;R{oT0(z**h8WV)^sZyr;3rMT$QHCq|yY75#Z8#Oj7AFJ;p0n}DlCK)|CpcQ*Z zq89>KpFBwZQhlES8%VN8i%luvL5&Zk-&5PCu?qgeOHuq5*QR-Rc!X9zZ0Z^t8SDM2 zW@u*iKriH>z#n$^XY5!SEshnrH;9jr36Te03*-;zAV-B^1w}pa?EZx6CmMde+1q6e$~{gnA0f`=ycQK zSjvs@(M+n-^J%Q}1)SR)lBqN7C`&gp$d13iIXbQ0Io&(k3$zn<0r!|27_`zC&z<5s zxbPiqRcWEBSjblV724F__DZ{$n+3I^h4lw1b)eqWscvnEmBmz)7z{X~=)3i}y91o+ zSn3poAOQ9MNYILE(!7wmJSrINfzw&MpCbO5%AD#1!^DY;r@>zP!QrjHXs=nbt&X^> z?#>SiLkdoI_pr0-)hIuPfBn4?|AF;I=GkiX(GZcE(33hf@SDI`@TEfITZ_Au)uNX7 zfy!}blQYZTR73pN8ZL4A067{MTuz&(zaF-|{i3p-isA4Fdy14Z|G(Yc?4l+5Enh@h zqV4LPd%y3@{`n)~=_w(blzF(MZ?>LKWEYA3x;%hO^}c2e;!X2{`BI&n&~f_h=gms< zPX=5VkIyL(&veK@B%by-{@0*FLHM;()QNW42)QcKIOREXyVHqlq{bnSm#)^i+5+4R z!NA=blZ?zlD#-n*2c4*B?*0~2rnNz3FzMyt+rV&pJ3FAHn(C;fXw9eeM>f*aIF5jU zQ{t~vNwSs!_u|PDF*oHi>{NyTGs7Rt9sQ>cbq^^h3^*O+3&`2opAo|XPJjOz7}?j- zrkNQnOY{1%5+61-FMkQ05krR${O3}4#1?45d{O7UM(cded?wOKV&OTDW^GNok(QLi zuY+|hVz@o_F<+Y1qPDh!G&#a@a0=LkUq2YrS31#XEU_VfuJNukrPc{Q%_8f!3u4Rb z5P|r=a1P1f{UdC9RX92IQmnGIKKDf7UUXAvw8?Wb)&dX+EGs9+C$$8n)S<(;AU7<} zLT^}qR1y~x$G;K&>#WfEc2W%ra=z(vx#Mf;#SStEgAc*=&OnuDZwVmerrAR_;Qc`E zn#|OGu5v&yUGxOSEwz0QnMBZcNC3wlheH;MYs(L>eBCTwe(>d)p6<1L3tE3ZGP#-_ zO-2(am(q1i0Jnu%grc8+6-yEnl&~|plYH`Em`aoGPUm~3za@8i+K|0JDamcZwF^jN zbsybTN$6}2b#wockqIx9K+KM_YkCJh_W~_=LFFY>XEvQ8%E(Fz`Jr=$)KWj2@sshT zpfO;<^JmOMgPQrNyHBv~vVz+#d6oVa9njG~(4*1h(XnGg4Toy_kw#OVMs;>2*_Bui zRZ?ZI;s*$7U>^VC7=V@eU&=I;R3o%3*LNmFq+Wu{n-cB*H6!j!iwLDx&1qAW1&@yn zO6-iB=eZ%+F${oKUoUzGMajh)=Ztr`_h~Z0eye@zgyX>9T!60as(}q=hoHO2dOyFH z+$Xkbj;|2wNsXs{F>T|T6QUG03v(g~W&<`g6PN;I zsTaxYbXkq_sTFLbBv1WH2>PTaL&wp~&!E&wih-;$Mwp2@eY!<)Yk?CA#qFq3;KX<4 zTK-Z;*bI0fhrMnhJwxZ$hzc$3QnT7Q^-Dq$`bBi}b4o_>?3OGR0u&yzdofmm;=#>% z65^Cjf6l;=H@nUBneJec+a2M{H0OZuYTv8B5aK-~R(&Vt;E)Xq2}6?{N2KL#%IMzq zH7;T_D{|i~_%*`9!6kev#8mc>&!{6jMmG7{$Fj7g` zzDcR_1U*vTxyyqsuR;;2aP4ep!D}_1?qoalX50CQS?|2Z&scC;zJ>=GpjOCj7Or1N zH@*1yrTbVxzXBlw(DTQ)A20vI&Vgc|-+4HJY$O3z{dRZ@r(9sA-S_bHdi?3)eBSI- zM^yq3`%ha<%El`D{QSP#{(s#A5FCH~q#|0ZFt*c+QjdVp%podzW8mJlKidCPbk>`i z_5uihiIurhUDpQ0IuRBEjQ0PFtfI&?jHx2_NiLVj2pu%7s_aBXVY&&9>NT8`C%;_ltL%muOo4N5^@KxuS^*wRfdmbiKMf zvgUn50X_H?DPb0Q;=R$`a?`OBaVq6}x~-A3=zXny(s{mlxL15l@wo<-b9=$ZiVZ5Q zk}D(qa9C`(qO(DJ0MIDRT;;n<84(UK1C8HG{sCIjxUTg+xkB)O1Ekj%oOz~jG1!iI z(!Slp8~xYN9-fYvc4;5wj*Gr1T{z!L`btIczPASJQxbee#IY~>zN;{NwGJh6;q$Ny7E(40=RkB~T-KWtz z+v^iF?sgFMWGs{z~{O6tCGgH!1q+=V0kL`8<*H9e90*FWEy zysX~EyG___`eiH*D$L7DIr8^gn_|l5IE63oHp&6o4K@AqDv(vI{}ZM512m?|)Y3K- zP~&2C4L^GpjMMOePf6ryDjG&(J+tLJG6QdJ*GD25jCv0Lrf-@$)iH#^2Qiwvs`9sJ zN>Xsy#f4=MmJuKt?`2BgJWQP$T!K2lt`x{szpq0*4kQV5;MHU}b#Hj^-lx-wIbO<@ zGSoP>mx9UYY-$=~$)}Dxzi4klA29PeF{Jw!uUT)E{vjXqs2LnsH2UD_=RXosvR6{` z>tf7+vDtU&PA#Y##wxElARzvnA__em%~$nYd=0TruU&jfP~YAypA`-{rSKwt=u;g9 zMDggf74}I|=(JHqm{O6GX@COsh_A2R0{MeNoLSIP;k5v_&& zg1W8W!Y3TnLTM+)A1)W}5m$-s~FG>_ih{@2g1ESgK6>-Y3?aBO)6&7vBttAE8 z?p1nZBm*%f&_Z%=BLRQQx-{aOiNl8KqKIbiq&4L&iN`UyXuuW?X%Fc8{%^TuC;&8n z3NM88{R&C*|LAqrQ)JDJ^M5-ZbTb_}zFKeDmS*02%y%l=xjp9`-leMjKYQ)1C~BB4 zKuwG$^3ukJ7OTUNNTwE|L&P;y14kI}D@ssU6HEzdg7!D+5S;b)6eH{a)jc`7#ISOF zP;Np`<8R{88`z0P-lUPL+rMd?4?_8mEQhz#_xpwg&3pNFE=oo$t0s?Gt^P1Z1lhTv1g5PDV?tHUz8pH;HYnXs#*HY?T3iKNXB z<~)(nQ9&jEVCiw{@gb(&A0>6?zeyg&t53gEmo8$ss4=vey@{eL^BFZa7Z;9E_=4H+l?h~G ze479R4mP*9>%N@-x6vrIoW&D2K0HTcxW!6gINisd}ZB!;l(fX%;X=1 z8XX>BJh%6<-_0r0WlcFrN)k8#csdiatz5PLT>T!YgkDs9Ze+pqKNLB$m|2hn$Mnjo zJ=i57GUSd)6dK5#V|t5n`b#3$*8+mx=gL&Pmr^5PVf{jQ?hHDRnUhuNGbDdXerS9m z4uTRr=bk_*S=nKcd)nKlS!L$a3QY!Kks6rqMy4Jx$*|>1Bj~a4jSKWx|3)8ryd5dL ze{~u8{>AdO81!VZ>s`X~l^hiJyLe>R?B-i_1fk0BzaxJ)*Utm>&5!g#C21L6%VJ$55@a2IGwmGZ3tOG|pU*HB7{;0COT<=`<>-TSV*6t}D zw&b)nRvGi~8Yr{fe)WSTwa^s+bfXe#G3e7nT1DG^um(s6aJ|)EO9u>!>cGK{`2?HX z9C4H5yOWP!@HNdc1K*(SpTZULnC~^gJLx&MS6Az@lV+7P#31~;7Eg+5rS&kMyS>d) zn^)S;_`9Xva(B5=T)rj;ewve2pZv1HuVOuXP$He~Qu1I?^Xr{vL&jgB7P&%7B_}XV zGsm=TEiW{`!Jj&l7DaDbpWxkv=uzWsP?pZwA?H|%^QD3v+RqeNIsjhJ5rKYOzjj1TO@kX9 zA{QWG0*1wQhN}^4n5}r^ts4NLR)7uxJcBV9)iO>Ctm4!CRCa4nagFxuDLQ7tsUsYS zj85*R;9p{up;sadj=xa$Oe0sL^QQ@8-V+~e+lW_-T$K&7=GMe`Kkn?>&$j&=IC6!| z4(kdLe}0{c>PX&KYp=c$cD3wg;@`U_}rzGmEZjmmNI&`I7LNCst(v>bSCcy`tw)v~pTa<|j85pBA%i`8 zMu9x4hxGwT$|1J}NH)dzdmobP>FKWJhS=24vScg1;utvYu4mk_jF0MH>;;B7_Y2n1 ztX7o%pg&>m2z9=&z=Ckko{Qn0y?7cb3P;>7%n<5WteLc2=4GiZepefLnfStWGoc{j z{81<2-<`JlP+c9hZH|8e9|ChSUJ;jVG`zEI3=ukeeUiRKeUiVGfZ-uGhcA`~tL%Sz zBleAmxe@X6=;Z|BpaMXEVd2I6G?AT<>;IL0D<5Aj0jFdZe%Ye-4G5|v0EtU*e~?`` z&R|btX&|Q2=$|9296y(%UWZl4EHU|)ugQ~D=2&!5$?1nviSzQ@# zAiw(J%a+TEgpz+ZhfCir@$li~RRU5vX=fjZvUP7>*BfdeHeCa>&#iJj z_?w;#3%9+ktdmZ4iC>5h;a9V$)TR5Jn-8FeYmxjs*T-G&Uv%Bjqyjb+DC@aZ&NMJy|XAFCuztd<)_R! z!+63Qo6ew@OVHCi_Jk>&H)~!yv+C?YC#npD&lHRUMXyQXx(B39SbgoHfd&|eWfpsw zJPAWor)^FGoX>&$k`lJ?4HVkB+KOoBkmgl3O&|FXSk!f7U@DpK`>}@3o%(<+_CH~vpNNn79N|2)2F;Z0eX)2yK$T#R1&O%l z9WFJhD= z;SK;4c-LxyPkhX`Lu@t^NXgftxKfUCDEVs`VZm|g2<(G@dmcGtc>V2d7bnPe#=;MO zz3CQ(^>YbL&Vb!%U8}Cf`-=Mj0wAKr%l?-IumuoF9i4lh(hEQu4A3UkOx5>y@Btwp zTIgcM^rA!C1(wkwH%&%HVilOD%b6e=avQ|MJ>`(Z_i7Mq$hB<+a*!A^l^&35`p+*_*H zk(D5smf-5sizBFwSv7=R5cByvCVZ)U65-w(&lvAtnF2C%A?vy18q6?NtD{?EpXVI|%y(xGZKPh`Esn$FN~bwPUnlq7CQO7Ajk(ae7`#P^AjCa z8l%fkOsgYt8T_SEMbIXtMMc)l)f5xi4-V`9vIjYFYia>g4 zj|2#}2K#RMQR zjzTQ90~CgC0wSb<9<_Gdw+`JlK=4jB4dMtR{F0U&^*~cMWjgQGs5qF`u@s=8hM%0I z3?SZG+*-FL`1-00i)bznm8YdfD&C`X^{uR4Nb&yybglSq@sPjK>fooXja7r-&kr;{ z0u;Zn6jK0#p4M{UIgisU)@0??=^U*jO4RSgFoKhJ!PVWAgS~;{r0bRSA2d#o!?Cm* z2LFW$dDT5VW}axw$;+xtQKgF42?EmkY1)PH@OlH%6@h~RytNFE|HQy{2CiEIvquO! zy2?j~k^J+^m+o#b9E0=m+Z!$BpqnCNwR5EG8HPvmris?$(!_1~8nV@fZ^ElzgGD>= z5BI{4($*)x?gRRtSjLH_1GtZ^UOw@?pC)xu)1jCQ*H&l!w zS2wr5)6Ah!7r`kBT3|Z75+c2^%$!2UgbvIOH+@qjMesaheNzk4xO48N{tNBQ=L(7- zK6OCXlMxyVa$E^Tk?-2o;&DSzkk+>!h}w@WPgXYO#zn0@>}Mz4W(_Bk#-X>!$P$3! zvyS@M*;ZN2sU88j@StG>GjMV@tsxoVSvSJNUHqN@(VE}>bOFVsmpv)omdHem4V^SW zP4Ip&x0iokUsSZGlsv|ebUbC{k_q)x`iq(x^zY#$T8!^x{vSnW9n|#u!0`oLLr|Ix zL_nlN=~j_eR7$!PrE_!}lr&0y0TJnL7~PDLkQzM!VZeX^gZ=iqgFEt=&F;98R7j?JB2DLCUT(`{AkHtV2#bP!mGEb`Y2>$v1+e5#0gt8k|H&i}r?GN$ko z5+&VS%YSVyaQgeVgxG|@Nv&i}ON&tBfmz~r_TtUUKTn!lf(>Vlkna|v*q!+|<^CW} z<@Z99@0gGSD%7N1ECHK9&|JmH*c&DiaZ>a$h=qad@V%u*$Swl)s6Cv<){D!Hn%-|t zE$;|Uti!8%ML%T(2!Nk3f!fv8#=c}VMyXi35_hDVdpffNu4oYn_FPLFSNQN;$?bC} z^{{9AvM%D}7tz)OV0VjdBR@)n`ij4zEBG%Gs;Cemn{roKlsMuC!nXV_kRBBmP;Upc zzYn#@*<{`X-2TFG2vre+l6_0zT03e8hQ`W5NHXL*AgH^U1=s=OI6m_XiWkfGdak zym_OFR(A!&KG}(mQu;IPn0JVtl7ymbuUyWjHJ~U@yD)v?j?I2>2yR;ru6V$>)=dlT zSW%MRcVGDqgefYI`w$+iKWhF!9f%i39yTR4J;s5Rb}7(3CnGT26Pf9Vyq#Gh{G&aP zuP%9qeU53Tmm0rcjcy*0V8WU0C<)&pD#@?l6aU>q`F-qoRsfEkkd~7YumuB@u>~ZZ zFNo2>5L+y+gv{P7ztS>40cEH;0m8ZaeU0`34SOlTP~$l;aF9%Ylb@!(bf!G3hh>cY z-+J2y!^xVuPJA=}V%n34BH(T}5;ys1p2GI3W<4;UJW7=A~NBThZI%iiaL z^t*X^DIo4zUYb*ycUn1i$LIIG}F!yQq_re|Tl%59aM-LGSHiLM@F#Vrcvr zS|6iSk_+qWRsZ}kwSVuWVi9=xxZ~=qmKYjF5Nk?@cYYjp5bxArmDQJMSyEg8B_@E* z1m*b!b-ol1<2vXIAiIgDxv<;T_dU~>##<|bLr6NWj&C3q!wb~Z21YL*WS8rrN2#pM z#1#XZV6Llc69b1yFM;|;B^E?HhEZhv=TG7wqKN(C*SB|e89DNx@1SKatMQ?hl672* z>R|Y46FHuY63%qY2k^&M#Z@cx6uz31(ll2G=ZP3ec>Lset>y6Jrs1_kaK4?LUDxyb zGvl8KjQHc@lDisxRAIDEuzF!{2^!m?5K!LmQHU*Z(1o-ex(|7RvVFsvZIM)xEo#5> zJwy}|d>oQQJgd(o&e4Y>*j7Te!qsN($O=F42OQdRu>JhzQ<>rw`BcqmfJD`CiB22- zyM)_b(BIXIuUT;XCoIjmrmV~7`z$>EvTaaclXX&IQHka-Yq6pP7m-MUez+1a=&lG* zc4D-7=jr>ic$hYXJ`BShJH*Kr^k_esEY}u0iJrMMms)|^XvvZZw1ahUHnB57lL7e? zKVPaXM}N+1{L8R&3qXrw#Vs0Q0`6;nk(8sWEG>N^VUS!1sq)zw4QHaZl$8bE|CSVe zBeLM&pre9XdR)9|SF{dfiy0Tc1=%+q8X*$ZSXfC_M&r&0N1qi7>70*nHKcye{;bD< zGBOnk%1-t0w$|!$b^Ku1fL;c32#?YdW5@L~Mz=MK_}?d+aJ|L*M?i@TkZ-YuRg__C zgBY>v17oh(uYO+t>2w>!(v=zyR}1s`W#)1cnbX7axb|}GlN!pwC9}-5#fgLZC#(m~ zM7Q{vR-nuuhqNpcj;Rmy_|Mkpcx=P)2>ruPfl_*S;uK}O#e`2k2W2Mpf>bbTi~a{&WfUCLN0xs(Fb z)P2vmG4UYOI1sP|eEu&0D7#FK-~^!3l2Kb?6j**~?29Yw977RI04bM4ig4B>(ujz@ndFyNG}BGbd;WUoF#}okp~dfW!&~#MGTI;WE-q&3%Xa9tZZ#Nr+)GP3Bn7V+}o zZcr$)I|nREM)$#l;yvTZXrS^+x%AgseJH9xp>yC`+@j-|+B^^?54z;2awqbkCU$58 zBjwKt2NxRZs~to{APo@`c$u;0O9%{zk3lL~qQPPeIP_LQjOg9Fpaw10_x~x(%ePC& z%0Aer(#=HJlUPYV#_UDFDg6P;qXjHyvP8HvILI#=RPi7`JS%Wn|0&uSwGlKtnqAkP zahj`%y*>NuLE(QjYQL&1IM?Fo(FVfB8OWoP`sYtFO;(6od@THgbFvNw1$7(;<O$hewLaOUa3b9*W&ViY9}dY(CTO!IcC`1F?Z? z&DVqtmb#|&H@Il>Z*~Em0SDbD?mIi1AZ*vk)Ho%b8TMrcQ!NyIW-}K62JpM$%F@!7 z9v&xLKW@nIz*lc$tL}TUvf1heB*%{G$RrL_N32ZDNh&CV)(E$vJBqC56%rdk+zD96X^(bTiFr?h?Tf$k>bSvhL#eiR$yp{roD zF3R;PNBm~=O~^@q$f7vj2jC5XZV=2>))bT7Y+{CNp=|$@{-lltlu!>Q~zfF(A&5Bf0K+7^oIL0Su?YDUvLqjtNbrtm$}U@8t{5f2LU?hGNWb8NpQ4Y zzcqaflM2Pn7%)q#=KMQM16$bjkI~w{q$`DBoEG_Fl+?s&Y~byIzd!)`*6~kVlhd6w zkw@R^0SVeNY1CAdvpR{9KmQEhEh!b5bQ?QM(-JOG`MK1lRB6>1^g;E&tWd*UZ$$pR zg+)pnb+X6FaN$yO6<3dXoWZ9n@jH0~Bz!yR8d#Zv0#IRfgHCd}0^sLTe@mkY-+Fg! zysVk|wx2o?*_ZY@_0Hd;Dl)DFezvOsnk#LVu|b`#n=Ze8e`W)@{z$ zxo0Gj`*kE;&sNsyw9X6!Fr_dv5vTWCCJif<79z<>sehfdv$t16mC*{MD69aJ%(;L_ zT#0{jAc=Ivh@4`W2*u3v7b+-gz|RffA?F(DD}VwGh?c_i)){f+%O<0kc!ZyGcT516 z+QS-=;j7~j51X(2z(JJ3?0ZuMzP4MjI=XS%{x7QIlLcdR?lS#oCr592WWD=#8?-KG z$_{`p|A?M>-uVuOt?_0JhYno2$65r_{duRyry}}9f=d{!qy8$c$gYl@9J_9o$9${k zLzLTqnDbaKWfS$9pJKzq55?Rbv9{+EY0dF2$^9}7Tco$eMio3_UG8+$Vr;^+qU;qy z9mB>y6Iwe@uAx(_n~uRdD+h0eX-#|xGWPQ&%ZGDAduH?gKCqyUT93-ZtE-NyAKX=N zk&G@0!<~iI`sv2BJ&u<1>4Ss-<)vd4m}=!9@6BN-*B;it#&_KW14m2N`^Swc%>F&C zlRU`%U=-ZzsXp%s&OI^>hM+f&vGnV{^}Q5;;X@Dl5RH6fm=JZ)?Balc>gIElCm?Q7 z?0n?rQTaa0A`wmp74scz(ua_q$8gmh(a|oUj zf+~8$f9qn)--ih73(SDG1y;Q<9{&Nl{(nJbWjM&sgaw7ClRvzSI=x>} znG5`2NTR96U0jc+!w{q0?ZF+^SuXCYd>X*wo*ssYl{rxp(kQL%D6ws+d~N4;Vz;mL zI0CtH60Y?5;gu4uOH$Zi1-N10e3oA@)WDsyOaw&&JC#%{eO+6V=Xo8JtF>Q0M7SCR zU!K5*m@PZ5;FxIxI+D)x_?6^yPQX1}dlhO298$@FAu_CY08PFtz_w;of_1Ja(2wor zlfOP@`K1m7k-Kp^9h;j`iHf^ZLRHD;1e9k0#z34ICOHgeD{uyt%7xx z*hd;0`q~|+^2#)N7Gd+D;}(EJU5p&yo5GHJpOl*a$z3Ifa&D8QbJrB?|29*nMQux) zSW}C9$}+ftlh&)n5Kndwl$33jziq7pB@Df0{dJdADB9h4ZmDq1ie~E`i^M_ zr}NL8NX&&S@vR>Gp4gD?p?^so$Rk(8T;p13&epoKIa5n`+Hp}yFzAQgG}auS5-gyd zxB-b%eC}`o>_-21xf35UbQN+=5a?+nbi}q_4tVSm)$gV2PElqkUiYu%l_}rq)pv>J z^GvU^cER-3tJK&H4(~kk^z~?~e5+ZK^+l)I;&(1()0pClGeZ_!^6|PkQ}m<%Z#xq~ zv7)fB!yL)qjb~zbD43Xc4ko4%DVi3+91^S%a5A&K!}V5O7Gig9I@)#Wi?8=}IKE!_ zGU(zum+<%oGpC%ce7#{=dV_|9@P(X_cZ!Bwb>dz&Q*NA2j%X;se@;6dDjP9Uh&DC$Y*MWjo+U^+6d%T5o7k?`w<>EG?7DQ%!`?9Rc2y+0L!8bPu&H zHOjpn84am83d?Q#$kG}wv_0Z&H2PupuQ#i%F;(;RlTY`aG$9~dEX<6d*CI(n)pVSz zjloG!EijzpY8%*&*YTP-Vi=5+nD+&lBs$RWW;keD2E=v4uB1Sg?`ddKdGe67@akZd zgwvBY)yn7Au7#BrhDhND2+y{h_{E-!hP;8`em^Xo!;;;R7il|jyODllQqadAi`%Yb z4?4xS0o&Q7$3ZLOfPKB8qLC4guPt>%_2>?ImlS=sIJEN)`hi!bY0?Nu*9aZOii|LG zb+&V)3R+Ip?YgiGOyUY4aV-;Nr|@bEBi_*G0O8JnR`y22&C7DCsDlc3yeA7GKBVDZ%uWTr)t%cc0Ap~^vz{$Jfav?xjcq}03+o>e!UVkSi_EzDH_Q!vPZy#yiC>7IT{8dQT z<>G0UtWD;8%7xG@6ierL*36584;QIX_YS~)o~hlV*(CCo^R>jByYt8RscyexA z)6!RTKVE>96FO<&xd9%XSRltp=1Eh;$xVNC0l~Q4o&m*pg*6?X7TZ%j!u3vk9F31F zy|yqki(N&De?JPW7XKl|TI(+{7v-=bRNP1hAWtlHE6fGHPvtGDA|3V`#*F{+;0e$D zj4H-B_Q(gJAS2rwtm2QP@+?L|XIGREkHIc2GN1Y>_kn{CXNXn9RLSGhxll0}`lTyu z;H+Gh(j0JiQY?@mW1WBF-C>nB2#0&QA z5u<c7)~n}e7BmmWqxiZzNVe(A8Wy~9T5hoNbMHB@tt&WZ|&K{o|jTs7u{I26yy;332k zZJJ3FmjK%3lk(RlpnuZn#SV$x%pLjRD)Q@1zAgU2j+r_*q}f@s&xo^xNVR3=<>ysB z%a0?AYBn(u;Z{)tzPm;5jK9OQ!|vqll+v&Qt6O!u4j7pqmE0W;F3Tg4pj5t)`YH+@xVwt`%8jj~?^o z5KRBPfr2hOQZr8=g`QQ6Y-G4pO~a@0kxl|J&r8aLl8Jb{F(sLgkNoWIO%xH44<8-? z9Alya8Bn-oMGYyCv^9xRD72emsU?J%x(T0(&;MAWj9&DxN?3Q?-Tgy)(QbKj8+Fcp zF@_A`4Z)mP+FWX1^jPAxZqVtSX`N?RooVdyrN^j+pn{$8naK?!h~3`!2Y;NGh8|I) zl2EWaIWf2=&tv`+&bD>T8cO7aOY!Y6#kdRaZSD6)E=6=LFPO$VvxeGl6qQ$~F*&r@ zyA*0a6~+NCe`v_tWuoRRgqt%z85kfQt4GR2Q$c%Ds+cJTt%BN|?kIo106-8{Ha1xx zT~ftxKtG$FAXO3B`j@EuaW+jII*kDi?%z!brtF_Lhu34@o9Cty86l>TIo_m{k2$32 znV@uF5Ivdko^xs1_u`$c?JY_nlzn7Sf$b+Cs)p_lY)EenfBayrS8 zQDUzP?eEZ_ClN(Eu|vjnH;hmWw^+DrMSPVnJotGrpP(Z;AF;DF=6O5vq+h6TB`^I) zqDI1sm41Yo86s$Tk?RhiT>|pzI|I{z$tq+A>t_}ESn@;d38r}T6yfa_0d2_7BTrrH zn*6=+1KM61uYm-^0rGdO4jBOYeMlw%rvM4VO`Deuj4Vhcu?JWIB&%GJ;hC$HjAze6>D~-iuaLMht*Xgq{&_tSXSb5C4`@B>9;N8;dpC zp+!y5Ep%}vSIn^Q9c{<2S2+iItStKvZLydMC=|`;@LOmwhJ)yvio>6TDgrEB;^U8A zPDD7h-NGhi-mv!dh>NpateTsDhX@ftgrHRBHxoudhQ20(CR4hJ9+VUSJ^x= z65P9}v2rT}*fKfM0Z3>)rAKACHb~=wd+lYn*uBmPmzj&0>ukbD4_K+9#j1bD@p8X& z--*M3)OyId&(dQ3v9Ea>*Kk4;&D`mwIm`rY8?6^&({FitoWE=$n#hb-)e*V#C0Lhx z2*@d#&pFLFs3Z&hm!b9Xi*GLyzp~(J5fXk2NnPBai>hrf`6tckw{duDQ-KT31HZUE zoOHxG($=r-N37jgZ2=W6QPW#-LUqky$WAw%2O`>QE4?%0=leZG;fQ=;La&=0_>T)? zazU<49TWqG+2

v)BO;awUf_M{_y&;HbCcz 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�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 z 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

B5)eh9`4@F0edZz?^2xBWnTG^@MKxA>tk- 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

wdDpS@fltibychGijSJgnW*r1RfL3~VWkqj zb`O3bNPnnp0Agj)KmvnD47HpRx;y|W&Zip_Np*#VSwLA3NdsMoLsY=?3$-Qa{L{^?wrMI%G`|eWfD9%n9i0G{Qgfb z`RgqGtKWo+C!v%osvO3*FL`G(x)nN}`|aFfD7uuJ_1)nsbEN^g#v?yO+a`Qx`O~VP zS72Vi))Axu@B-BJwPmZ9iob=Fx|`@02LbVj4(*8jj_MD;GO}!D6~Rac1_xDgRq_sw z*EjHo*1ABtIO458;1#j?TSzk%8li48Tglcf_GaT0r>mNJ4A9Qs>HYbN%vH-oDuks%UKDsI%s?-@mgzcf<=nI64?J5MP{<>=S`Y%LHp1mYAhS=5<*?rwE zEl8g|*_9W|(7onr29xu*<==3d&A}q?@tu+g@($V@k%WhFLi8_iV#qRkNb&<~+wfw%JtPutshvDC3e zThR@UEN3K4XkKsRw&&(XE9ApO6Gdb+V#(b!Y%p7WSvu-x#9S#n?LGewwbA9}<@hcD z!c4_gkS{w|$altyWSo2UI}0+`gy+xgKRP<|TB78b;*RsFDHsbMa{1p+z|X;7TK43F zAP1YsXIa97;y~!iQbR=6Dya_EmhO^asXeZ1;=>%0D9yk0Obh0nYzI>q`|=P-TZYUZ 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