├── .dockerignore ├── .editorconfig ├── .github ├── .stale.yml ├── ISSUE_TEMPLATE │ ├── api_bug_report.md │ ├── bug_report.md │ ├── config.yml │ ├── feature_request.md │ └── question.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── release-drafter.yml └── workflows │ ├── codacy.yml │ ├── greetings.yml │ ├── release-drafter.yml │ └── static.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── RELEASE.md ├── SECURITY.md ├── add.py ├── assets └── images │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── YouChat.png │ ├── YouCode.png │ ├── YouDotCom.jpg │ └── coverage.svg ├── cookiecutter-config-file.yml ├── docker ├── Dockerfile └── README.md ├── examples └── youchat.py ├── image.png ├── poetry.lock ├── poetry.lock.old ├── pyproject.toml ├── release.py ├── requirements.txt ├── setup.cfg ├── tests └── test_example │ └── test.py ├── update.py ├── youdotcom.png └── youdotcom ├── __init__.py ├── __main__.py ├── api_1.py ├── api_2.py ├── apps.py ├── code.py ├── config.json ├── imagine.py ├── init.py ├── search.py ├── test.py ├── write.py └── youchat.py /.dockerignore: -------------------------------------------------------------------------------- 1 | # Git 2 | .git 3 | .gitignore 4 | .github 5 | 6 | # Docker 7 | .dockerignore 8 | 9 | # IDE 10 | .idea 11 | .vscode 12 | 13 | # Byte-compiled / optimized / DLL files 14 | __pycache__/ 15 | **/__pycache__/ 16 | *.pyc 17 | *.pyo 18 | *.pyd 19 | .Python 20 | *.py[cod] 21 | *$py.class 22 | .pytest_cache/ 23 | ..mypy_cache/ 24 | 25 | # poetry 26 | .venv 27 | 28 | # C extensions 29 | *.so 30 | 31 | # Virtual environment 32 | .venv 33 | venv 34 | 35 | .DS_Store 36 | .AppleDouble 37 | .LSOverride 38 | ._* 39 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Check http://editorconfig.org for more information 2 | # This is the main config file for this project: 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 2 11 | trim_trailing_whitespace = true 12 | 13 | [*.{py, pyi}] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | [Makefile] 18 | indent_style = tab 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [*.{diff,patch}] 24 | trim_trailing_whitespace = false 25 | -------------------------------------------------------------------------------- /.github/.stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/api_bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🔧 API Error report 3 | about: If the api isn't working 🔧 4 | title: '' 5 | labels: bug 6 | assignees: 7 | --- 8 | 9 | ## 🔧 API Error Report 10 | 11 | 12 | 13 | ## 🔬 How To Reproduce (url used) 14 | 15 | What url dit you use: (remove your api key before posting it here) 16 | 17 | 18 | 19 | ### Screenshots 20 | 21 | 22 | 23 | ## 📈 Expected behavior 24 | 25 | 26 | 27 | ## 📎 Additional context 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: If something isn't working 🔧 4 | title: '' 5 | labels: bug 6 | assignees: 7 | --- 8 | 9 | ## 🐛 Bug Report 10 | 11 | 12 | 13 | ## 🔬 How To Reproduce 14 | 15 | Steps to reproduce the behavior: 16 | 17 | 1. ... 18 | 19 | ### Code sample 20 | 21 | 22 | 23 | ### Environment 24 | 25 | * OS: [e.g. Linux / Windows / macOS] 26 | * Python version, get it with: 27 | 28 | ```bash 29 | python --version 30 | ``` 31 | 32 | ### Screenshots 33 | 34 | 35 | 36 | ## 📈 Expected behavior 37 | 38 | 39 | 40 | ## 📎 Additional context 41 | 42 | 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository 2 | 3 | blank_issues_enabled: false 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature request 3 | about: Suggest an idea for this project 🏖 4 | title: '' 5 | labels: enhancement 6 | assignees: 7 | --- 8 | 9 | ## 🚀 Feature Request 10 | 11 | 12 | 13 | ## 🔈 Motivation 14 | 15 | 16 | 17 | ## 🛰 Alternatives 18 | 19 | 20 | 21 | ## 📎 Additional context 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ❓ Question 3 | about: Ask a question about this project 🎓 4 | title: '' 5 | labels: question 6 | assignees: 7 | --- 8 | 9 | ## Checklist 10 | 11 | 12 | 13 | - [ ] I've searched the project's [`issues`](https://github.com/silkepilon/youdotcom/issues?q=is%3Aissue). 14 | 15 | ## ❓ Question 16 | 17 | 18 | 19 | How can I [...]? 20 | 21 | Is it possible to [...]? 22 | 23 | ## 📎 Additional context 24 | 25 | 26 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Related Issue 6 | 7 | 8 | 9 | ## Type of Change 10 | 11 | 12 | 13 | - [ ] 📚 Examples / docs / tutorials / dependencies update 14 | - [ ] 🔧 Bug fix (non-breaking change which fixes an issue) 15 | - [ ] 🥂 Improvement (non-breaking change which improves an existing feature) 16 | - [ ] 🚀 New feature (non-breaking change which adds functionality) 17 | - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to change) 18 | - [ ] 🔐 Security fix 19 | 20 | ## Checklist 21 | 22 | 23 | 24 | - [ ] I've read the [`CODE_OF_CONDUCT.md`](https://github.com/silkepilon/youdotcom/blob/master/CODE_OF_CONDUCT.md) document. 25 | - [ ] I've read the [`CONTRIBUTING.md`](https://github.com/silkepilon/youdotcom/blob/master/CONTRIBUTING.md) guide. 26 | - [ ] I've updated the code style using `make codestyle`. 27 | - [ ] I've written tests for all new methods and classes that I created. 28 | - [ ] I've written the docstring in Google format for all the methods and classes that I used. 29 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Configuration: https://dependabot.com/docs/config-file/ 2 | # Docs: https://docs.github.com/en/github/administering-a-repository/keeping-your-dependencies-updated-automatically 3 | 4 | version: 2 5 | 6 | updates: 7 | - package-ecosystem: "pip" 8 | directory: "/" 9 | schedule: 10 | interval: "daily" 11 | allow: 12 | - dependency-type: "all" 13 | commit-message: 14 | prefix: ":arrow_up:" 15 | open-pull-requests-limit: 50 16 | 17 | - package-ecosystem: "github-actions" 18 | directory: "/" 19 | schedule: 20 | interval: "daily" 21 | allow: 22 | - dependency-type: "all" 23 | commit-message: 24 | prefix: ":arrow_up:" 25 | open-pull-requests-limit: 50 26 | 27 | - package-ecosystem: "docker" 28 | directory: "/docker" 29 | schedule: 30 | interval: "weekly" 31 | allow: 32 | - dependency-type: "all" 33 | commit-message: 34 | prefix: ":arrow_up:" 35 | open-pull-requests-limit: 50 36 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # Release drafter configuration https://github.com/release-drafter/release-drafter#configuration 2 | # Emojis were chosen to match the https://gitmoji.carloscuesta.me/ 3 | 4 | name-template: "v$NEXT_PATCH_VERSION" 5 | tag-template: "v$NEXT_PATCH_VERSION" 6 | 7 | categories: 8 | - title: ":rocket: Features" 9 | labels: [enhancement, feature] 10 | - title: ":wrench: Fixes & Refactoring" 11 | labels: [bug, refactoring, bugfix, fix] 12 | - title: ":package: Build System & CI/CD" 13 | labels: [build, ci, testing] 14 | - title: ":boom: Breaking Changes" 15 | labels: [breaking] 16 | - title: ":pencil: Documentation" 17 | labels: [documentation] 18 | - title: ":arrow_up: Dependencies updates" 19 | labels: [dependencies] 20 | 21 | template: | 22 | ## What’s Changed 23 | 24 | $CHANGES 25 | 26 | ## :busts_in_silhouette: List of contributors 27 | 28 | $CONTRIBUTORS 29 | -------------------------------------------------------------------------------- /.github/workflows/codacy.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # This workflow checks out code, performs a Codacy security scan 7 | # and integrates the results with the 8 | # GitHub Advanced Security code scanning feature. For more information on 9 | # the Codacy security scan action usage and parameters, see 10 | # https://github.com/codacy/codacy-analysis-cli-action. 11 | # For more information on Codacy Analysis CLI in general, see 12 | # https://github.com/codacy/codacy-analysis-cli. 13 | 14 | name: Codacy Security Scan 15 | 16 | on: 17 | push: 18 | branches: [ "main" ] 19 | pull_request: 20 | # The branches below must be a subset of the branches above 21 | branches: [ "main" ] 22 | schedule: 23 | - cron: '27 12 * * 5' 24 | 25 | permissions: 26 | contents: read 27 | 28 | jobs: 29 | codacy-security-scan: 30 | permissions: 31 | contents: read # for actions/checkout to fetch code 32 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results 33 | actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status 34 | name: Codacy Security Scan 35 | runs-on: ubuntu-latest 36 | steps: 37 | # Checkout the repository to the GitHub Actions runner 38 | - name: Checkout code 39 | uses: actions/checkout@v3 40 | 41 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis 42 | - name: Run Codacy Analysis CLI 43 | uses: codacy/codacy-analysis-cli-action@5cc54a75f9ad88159bb54046196d920e40e367a5 44 | with: 45 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository 46 | # You can also omit the token and run the tools that support default configurations 47 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 48 | verbose: true 49 | output: results.sarif 50 | format: sarif 51 | # Adjust severity of non-security issues 52 | gh-code-scanning-compat: true 53 | # Force 0 exit code to allow SARIF file generation 54 | # This will handover control about PR rejection to the GitHub side 55 | max-allowed-issues: 2147483647 56 | 57 | # Upload the SARIF file generated in the previous step 58 | - name: Upload SARIF results file 59 | uses: github/codeql-action/upload-sarif@v2 60 | with: 61 | sarif_file: results.sarif 62 | -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: [pull_request, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/first-interaction@v1 10 | with: 11 | repo-token: ${{ secrets.GITHUB_TOKEN }} 12 | pr-message: 'Hello @${{ github.actor }}, thank you for submitting a PR! We will respond as soon as possible.' 13 | issue-message: | 14 | Hello @${{ github.actor }}, thank you for your interest in youdotcom/betterapi. 15 | 16 | If this is a bug/issue with the api (betterapi.net) note that this is still in beta. 17 | 18 | Please note that repository is made and maintained by a single developer, @SilkePilon. 19 | 20 | 21 | Thank you for submitting a issue! @SilkePilon will respond as soon as possible. 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - master 8 | 9 | jobs: 10 | update_release_draft: 11 | runs-on: ubuntu-latest 12 | steps: 13 | # Drafts your next Release notes as Pull Requests are merged into "master" 14 | - uses: release-drafter/release-drafter@v5.23.0 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/static.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: "pages" 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v3 33 | - name: Setup Pages 34 | uses: actions/configure-pages@v3 35 | - name: Upload artifact 36 | uses: actions/upload-pages-artifact@v1 37 | with: 38 | # Upload entire repository 39 | path: '.' 40 | - name: Deploy to GitHub Pages 41 | id: deployment 42 | uses: actions/deploy-pages@v1 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/osx,python,pycharm,windows,visualstudio,visualstudiocode 3 | # Edit at https://www.gitignore.io/?templates=osx,python,pycharm,windows,visualstudio,visualstudiocode 4 | 5 | ### OSX ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | 33 | ### PyCharm ### 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | ### PyCharm Patch ### 104 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 105 | 106 | # *.iml 107 | # modules.xml 108 | # .idea/misc.xml 109 | # *.ipr 110 | 111 | # Sonarlint plugin 112 | .idea/**/sonarlint/ 113 | 114 | # SonarQube Plugin 115 | .idea/**/sonarIssues.xml 116 | 117 | # Markdown Navigator plugin 118 | .idea/**/markdown-navigator.xml 119 | .idea/**/markdown-navigator/ 120 | 121 | ### Python ### 122 | # Byte-compiled / optimized / DLL files 123 | __pycache__/ 124 | *.py[cod] 125 | *$py.class 126 | 127 | # C extensions 128 | *.so 129 | 130 | # Distribution / packaging 131 | .Python 132 | build/ 133 | develop-eggs/ 134 | dist/ 135 | downloads/ 136 | eggs/ 137 | .eggs/ 138 | lib/ 139 | lib64/ 140 | parts/ 141 | sdist/ 142 | var/ 143 | wheels/ 144 | pip-wheel-metadata/ 145 | share/python-wheels/ 146 | *.egg-info/ 147 | .installed.cfg 148 | *.egg 149 | MANIFEST 150 | 151 | # PyInstaller 152 | # Usually these files are written by a python script from a template 153 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 154 | *.manifest 155 | *.spec 156 | 157 | # Installer logs 158 | pip-log.txt 159 | pip-delete-this-directory.txt 160 | 161 | # Unit test / coverage reports 162 | htmlcov/ 163 | .tox/ 164 | .nox/ 165 | .coverage 166 | .coverage.* 167 | .cache 168 | nosetests.xml 169 | coverage.xml 170 | *.cover 171 | .hypothesis/ 172 | .pytest_cache/ 173 | 174 | # Translations 175 | *.mo 176 | *.pot 177 | 178 | # Scrapy stuff: 179 | .scrapy 180 | 181 | # Sphinx documentation 182 | docs/_build/ 183 | 184 | # PyBuilder 185 | target/ 186 | 187 | # pyenv 188 | .python-version 189 | 190 | # poetry 191 | .venv 192 | 193 | # pipenv 194 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 195 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 196 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 197 | # install all needed dependencies. 198 | #Pipfile.lock 199 | 200 | # celery beat schedule file 201 | celerybeat-schedule 202 | 203 | # SageMath parsed files 204 | *.sage.py 205 | 206 | # Spyder project settings 207 | .spyderproject 208 | .spyproject 209 | 210 | # Rope project settings 211 | .ropeproject 212 | 213 | # Mr Developer 214 | .mr.developer.cfg 215 | .project 216 | .pydevproject 217 | 218 | # mkdocs documentation 219 | /site 220 | 221 | # mypy 222 | .mypy_cache/ 223 | .dmypy.json 224 | dmypy.json 225 | 226 | # Pyre type checker 227 | .pyre/ 228 | 229 | # Plugins 230 | .secrets.baseline 231 | 232 | ### VisualStudioCode ### 233 | .vscode/* 234 | !.vscode/tasks.json 235 | !.vscode/launch.json 236 | !.vscode/extensions.json 237 | 238 | ### VisualStudioCode Patch ### 239 | # Ignore all local history of files 240 | .history 241 | 242 | ### Windows ### 243 | # Windows thumbnail cache files 244 | Thumbs.db 245 | Thumbs.db:encryptable 246 | ehthumbs.db 247 | ehthumbs_vista.db 248 | 249 | # Dump file 250 | *.stackdump 251 | 252 | # Folder config file 253 | [Dd]esktop.ini 254 | 255 | # Recycle Bin used on file shares 256 | $RECYCLE.BIN/ 257 | 258 | # Windows Installer files 259 | *.cab 260 | *.msi 261 | *.msix 262 | *.msm 263 | *.msp 264 | 265 | # Windows shortcuts 266 | *.lnk 267 | 268 | ### VisualStudio ### 269 | ## Ignore Visual Studio temporary files, build results, and 270 | ## files generated by popular Visual Studio add-ons. 271 | ## 272 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 273 | 274 | # User-specific files 275 | *.rsuser 276 | *.suo 277 | *.user 278 | *.userosscache 279 | *.sln.docstates 280 | 281 | # User-specific files (MonoDevelop/Xamarin Studio) 282 | *.userprefs 283 | 284 | # Mono auto generated files 285 | mono_crash.* 286 | 287 | # Build results 288 | [Dd]ebug/ 289 | [Dd]ebugPublic/ 290 | [Rr]elease/ 291 | [Rr]eleases/ 292 | x64/ 293 | x86/ 294 | [Aa][Rr][Mm]/ 295 | [Aa][Rr][Mm]64/ 296 | bld/ 297 | [Bb]in/ 298 | [Oo]bj/ 299 | [Ll]og/ 300 | 301 | # Visual Studio 2015/2017 cache/options directory 302 | .vs/ 303 | # Uncomment if you have tasks that create the project's static files in wwwroot 304 | #wwwroot/ 305 | 306 | # Visual Studio 2017 auto generated files 307 | Generated\ Files/ 308 | 309 | # MSTest test Results 310 | [Tt]est[Rr]esult*/ 311 | [Bb]uild[Ll]og.* 312 | 313 | # NUnit 314 | *.VisualState.xml 315 | TestResult.xml 316 | nunit-*.xml 317 | 318 | # Build Results of an ATL Project 319 | [Dd]ebugPS/ 320 | [Rr]eleasePS/ 321 | dlldata.c 322 | 323 | # Benchmark Results 324 | BenchmarkDotNet.Artifacts/ 325 | 326 | # .NET Core 327 | project.lock.json 328 | project.fragment.lock.json 329 | artifacts/ 330 | 331 | # StyleCop 332 | StyleCopReport.xml 333 | 334 | # Files built by Visual Studio 335 | *_i.c 336 | *_p.c 337 | *_h.h 338 | *.ilk 339 | *.obj 340 | *.iobj 341 | *.pch 342 | *.pdb 343 | *.ipdb 344 | *.pgc 345 | *.pgd 346 | *.rsp 347 | *.sbr 348 | *.tlb 349 | *.tli 350 | *.tlh 351 | *.tmp 352 | *.tmp_proj 353 | *_wpftmp.csproj 354 | *.log 355 | *.vspscc 356 | *.vssscc 357 | .builds 358 | *.pidb 359 | *.svclog 360 | *.scc 361 | 362 | # Chutzpah Test files 363 | _Chutzpah* 364 | 365 | # Visual C++ cache files 366 | ipch/ 367 | *.aps 368 | *.ncb 369 | *.opendb 370 | *.opensdf 371 | *.sdf 372 | *.cachefile 373 | *.VC.db 374 | *.VC.VC.opendb 375 | 376 | # Visual Studio profiler 377 | *.psess 378 | *.vsp 379 | *.vspx 380 | *.sap 381 | 382 | # Visual Studio Trace Files 383 | *.e2e 384 | 385 | # TFS 2012 Local Workspace 386 | $tf/ 387 | 388 | # Guidance Automation Toolkit 389 | *.gpState 390 | 391 | # ReSharper is a .NET coding add-in 392 | _ReSharper*/ 393 | *.[Rr]e[Ss]harper 394 | *.DotSettings.user 395 | 396 | # JustCode is a .NET coding add-in 397 | .JustCode 398 | 399 | # TeamCity is a build add-in 400 | _TeamCity* 401 | 402 | # DotCover is a Code Coverage Tool 403 | *.dotCover 404 | 405 | # AxoCover is a Code Coverage Tool 406 | .axoCover/* 407 | !.axoCover/settings.json 408 | 409 | # Visual Studio code coverage results 410 | *.coverage 411 | *.coveragexml 412 | 413 | # NCrunch 414 | _NCrunch_* 415 | .*crunch*.local.xml 416 | nCrunchTemp_* 417 | 418 | # MightyMoose 419 | *.mm.* 420 | AutoTest.Net/ 421 | 422 | # Web workbench (sass) 423 | .sass-cache/ 424 | 425 | # Installshield output folder 426 | [Ee]xpress/ 427 | 428 | # DocProject is a documentation generator add-in 429 | DocProject/buildhelp/ 430 | DocProject/Help/*.HxT 431 | DocProject/Help/*.HxC 432 | DocProject/Help/*.hhc 433 | DocProject/Help/*.hhk 434 | DocProject/Help/*.hhp 435 | DocProject/Help/Html2 436 | DocProject/Help/html 437 | 438 | # Click-Once directory 439 | publish/ 440 | 441 | # Publish Web Output 442 | *.[Pp]ublish.xml 443 | *.azurePubxml 444 | # Note: Comment the next line if you want to checkin your web deploy settings, 445 | # but database connection strings (with potential passwords) will be unencrypted 446 | *.pubxml 447 | *.publishproj 448 | 449 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 450 | # checkin your Azure Web App publish settings, but sensitive information contained 451 | # in these scripts will be unencrypted 452 | PublishScripts/ 453 | 454 | # NuGet Packages 455 | *.nupkg 456 | # NuGet Symbol Packages 457 | *.snupkg 458 | # The packages folder can be ignored because of Package Restore 459 | **/[Pp]ackages/* 460 | # except build/, which is used as an MSBuild target. 461 | !**/[Pp]ackages/build/ 462 | # Uncomment if necessary however generally it will be regenerated when needed 463 | #!**/[Pp]ackages/repositories.config 464 | # NuGet v3's project.json files produces more ignorable files 465 | *.nuget.props 466 | *.nuget.targets 467 | 468 | # Microsoft Azure Build Output 469 | csx/ 470 | *.build.csdef 471 | 472 | # Microsoft Azure Emulator 473 | ecf/ 474 | rcf/ 475 | 476 | # Windows Store app package directories and files 477 | AppPackages/ 478 | BundleArtifacts/ 479 | Package.StoreAssociation.xml 480 | _pkginfo.txt 481 | *.appx 482 | *.appxbundle 483 | *.appxupload 484 | 485 | # Visual Studio cache files 486 | # files ending in .cache can be ignored 487 | *.[Cc]ache 488 | # but keep track of directories ending in .cache 489 | !?*.[Cc]ache/ 490 | 491 | # Others 492 | ClientBin/ 493 | ~$* 494 | *~ 495 | *.dbmdl 496 | *.dbproj.schemaview 497 | *.jfm 498 | *.pfx 499 | *.publishsettings 500 | orleans.codegen.cs 501 | 502 | # Including strong name files can present a security risk 503 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 504 | #*.snk 505 | 506 | # Since there are multiple workflows, uncomment next line to ignore bower_components 507 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 508 | #bower_components/ 509 | 510 | # RIA/Silverlight projects 511 | Generated_Code/ 512 | 513 | # Backup & report files from converting an old project file 514 | # to a newer Visual Studio version. Backup files are not needed, 515 | # because we have git ;-) 516 | _UpgradeReport_Files/ 517 | Backup*/ 518 | UpgradeLog*.XML 519 | UpgradeLog*.htm 520 | ServiceFabricBackup/ 521 | *.rptproj.bak 522 | 523 | # SQL Server files 524 | *.mdf 525 | *.ldf 526 | *.ndf 527 | 528 | # Business Intelligence projects 529 | *.rdl.data 530 | *.bim.layout 531 | *.bim_*.settings 532 | *.rptproj.rsuser 533 | *- [Bb]ackup.rdl 534 | *- [Bb]ackup ([0-9]).rdl 535 | *- [Bb]ackup ([0-9][0-9]).rdl 536 | 537 | # Microsoft Fakes 538 | FakesAssemblies/ 539 | 540 | # GhostDoc plugin setting file 541 | *.GhostDoc.xml 542 | 543 | # Node.js Tools for Visual Studio 544 | .ntvs_analysis.dat 545 | node_modules/ 546 | 547 | # Visual Studio 6 build log 548 | *.plg 549 | 550 | # Visual Studio 6 workspace options file 551 | *.opt 552 | 553 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 554 | *.vbw 555 | 556 | # Visual Studio LightSwitch build output 557 | **/*.HTMLClient/GeneratedArtifacts 558 | **/*.DesktopClient/GeneratedArtifacts 559 | **/*.DesktopClient/ModelManifest.xml 560 | **/*.Server/GeneratedArtifacts 561 | **/*.Server/ModelManifest.xml 562 | _Pvt_Extensions 563 | 564 | # Paket dependency manager 565 | .paket/paket.exe 566 | paket-files/ 567 | 568 | # FAKE - F# Make 569 | .fake/ 570 | 571 | # CodeRush personal settings 572 | .cr/personal 573 | 574 | # Python Tools for Visual Studio (PTVS) 575 | *.pyc 576 | 577 | # Cake - Uncomment if you are using it 578 | # tools/** 579 | # !tools/packages.config 580 | 581 | # Tabs Studio 582 | *.tss 583 | 584 | # Telerik's JustMock configuration file 585 | *.jmconfig 586 | 587 | # BizTalk build output 588 | *.btp.cs 589 | *.btm.cs 590 | *.odx.cs 591 | *.xsd.cs 592 | 593 | # OpenCover UI analysis results 594 | OpenCover/ 595 | 596 | # Azure Stream Analytics local run output 597 | ASALocalRun/ 598 | 599 | # MSBuild Binary and Structured Log 600 | *.binlog 601 | 602 | # NVidia Nsight GPU debugger configuration file 603 | *.nvuser 604 | 605 | # MFractors (Xamarin productivity tool) working folder 606 | .mfractor/ 607 | 608 | # Local History for Visual Studio 609 | .localhistory/ 610 | 611 | # BeatPulse healthcheck temp database 612 | healthchecksdb 613 | 614 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 615 | MigrationBackup/ 616 | 617 | # End of https://www.gitignore.io/api/osx,python,pycharm,windows,visualstudio,visualstudiocode 618 | 619 | poetry-convert.py 620 | Makefile 621 | Makefile 622 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3.10 3 | 4 | default_stages: [commit, push] 5 | 6 | repos: 7 | - repo: https://github.com/pre-commit/pre-commit-hooks 8 | rev: v2.5.0 9 | hooks: 10 | - id: check-yaml 11 | - id: end-of-file-fixer 12 | exclude: LICENSE 13 | 14 | - repo: local 15 | hooks: 16 | - id: pyupgrade 17 | name: pyupgrade 18 | entry: poetry run pyupgrade --py39-plus 19 | types: [python] 20 | language: system 21 | 22 | - repo: local 23 | hooks: 24 | - id: isort 25 | name: isort 26 | entry: poetry run isort --settings-path pyproject.toml 27 | types: [python] 28 | language: system 29 | 30 | - repo: https://github.com/psf/black 31 | rev: 22.3.0 32 | hooks: 33 | - id: black 34 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at silkepilon2009@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | ## Dependencies 4 | 5 | We use `poetry` to manage the [dependencies](https://github.com/python-poetry/poetry). 6 | If you dont have `poetry`, you should install with `make poetry-download`. 7 | 8 | To install dependencies and prepare [`pre-commit`](https://pre-commit.com/) hooks you would need to run `install` command: 9 | 10 | ```bash 11 | make install 12 | make pre-commit-install 13 | ``` 14 | 15 | To activate your `virtualenv` run `poetry shell`. 16 | 17 | ## Codestyle 18 | 19 | After installation you may execute code formatting. 20 | 21 | ```bash 22 | make codestyle 23 | ``` 24 | 25 | ### Checks 26 | 27 | Many checks are configured for this project. Command `make check-codestyle` will check black, isort and darglint. 28 | The `make check-safety` command will look at the security of your code. 29 | 30 | Comand `make lint` applies all checks. 31 | 32 | ### Before submitting 33 | 34 | Before submitting your code please do the following steps: 35 | 36 | 1. Add any changes you want 37 | 1. Add tests for the new changes 38 | 1. Edit documentation if you have changed something significant 39 | 1. Run `make codestyle` to format your changes. 40 | 1. Run `make lint` to ensure that types, security and docstrings are okay. 41 | 42 | ## Other help 43 | 44 | You can contribute by spreading a word about this library. 45 | It would also be a huge contribution to write 46 | a short article on how you are using this project. 47 | You can also share your best practices with us. 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2022 youdotcom 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #* Variables 2 | SHELL := /usr/bin/env bash 3 | PYTHON := python 4 | PYTHONPATH := `pwd` 5 | 6 | #* Docker variables 7 | IMAGE := youdotcom 8 | VERSION := latest 9 | 10 | #* Poetry 11 | .PHONY: poetry-download 12 | poetry-download: 13 | curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | $(PYTHON) - 14 | 15 | .PHONY: poetry-remove 16 | poetry-remove: 17 | curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | $(PYTHON) - --uninstall 18 | 19 | #* Installation 20 | .PHONY: install 21 | install: 22 | poetry lock -n && poetry export --without-hashes > requirements.txt 23 | poetry install -n 24 | -poetry run mypy --install-types --non-interactive ./ 25 | 26 | .PHONY: update 27 | update: 28 | poetry lock --no-update 29 | 30 | .PHONY: publish 31 | publish: 32 | poetry version patch 33 | poetry publish --build 34 | python3 update.py 35 | python3 release.py 36 | .PHONY: readme 37 | readme: 38 | python3 update.py 39 | 40 | .PHONY: pre-commit-install 41 | pre-commit-install: 42 | poetry run pre-commit install 43 | 44 | #* Formatters 45 | .PHONY: codestyle 46 | codestyle: 47 | poetry run pyupgrade --exit-zero-even-if-changed --py39-plus **/*.py 48 | poetry run isort --settings-path pyproject.toml ./ 49 | poetry run black --config pyproject.toml ./ 50 | 51 | .PHONY: formatting 52 | formatting: codestyle 53 | 54 | #* Linting 55 | .PHONY: test 56 | test: 57 | PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml --cov-report=html --cov=youdotcom tests/ 58 | poetry run coverage-badge -o assets/images/coverage.svg -f 59 | 60 | .PHONY: check-codestyle 61 | check-codestyle: 62 | poetry run isort --diff --check-only --settings-path pyproject.toml ./ 63 | poetry run black --diff --check --config pyproject.toml ./ 64 | poetry run darglint --verbosity 2 youdotcom tests 65 | 66 | .PHONY: mypy 67 | mypy: 68 | poetry run mypy --config-file pyproject.toml ./ 69 | 70 | .PHONY: check-safety 71 | check-safety: 72 | poetry check 73 | poetry run safety check --full-report 74 | poetry run bandit -ll --recursive youdotcom tests 75 | 76 | .PHONY: lint 77 | lint: test check-codestyle mypy check-safety 78 | 79 | .PHONY: update-dev-deps 80 | update-dev-deps: 81 | poetry add -D bandit@latest darglint@latest "isort[colors]@latest" mypy@latest pre-commit@latest pydocstyle@latest pylint@latest pytest@latest pyupgrade@latest safety@latest coverage@latest coverage-badge@latest pytest-html@latest pytest-cov@latest 82 | poetry add -D --allow-prereleases black@latest 83 | 84 | #* Docker 85 | # Example: make docker-build VERSION=latest 86 | # Example: make docker-build IMAGE=some_name VERSION=0.1.0 87 | .PHONY: docker-build 88 | docker-build: 89 | @echo Building docker $(IMAGE):$(VERSION) ... 90 | docker build \ 91 | -t $(IMAGE):$(VERSION) . \ 92 | -f ./docker/Dockerfile --no-cache 93 | 94 | # Example: make docker-remove VERSION=latest 95 | # Example: make docker-remove IMAGE=some_name VERSION=0.1.0 96 | .PHONY: docker-remove 97 | docker-remove: 98 | @echo Removing docker $(IMAGE):$(VERSION) ... 99 | docker rmi -f $(IMAGE):$(VERSION) 100 | 101 | #* Cleaning 102 | .PHONY: pycache-remove 103 | pycache-remove: 104 | find . | grep -E "(__pycache__|\.pyc|\.pyo$$)" | xargs rm -rf 105 | 106 | .PHONY: dsstore-remove 107 | dsstore-remove: 108 | find . | grep -E ".DS_Store" | xargs rm -rf 109 | 110 | .PHONY: mypycache-remove 111 | mypycache-remove: 112 | find . | grep -E ".mypy_cache" | xargs rm -rf 113 | 114 | .PHONY: ipynbcheckpoints-remove 115 | ipynbcheckpoints-remove: 116 | find . | grep -E ".ipynb_checkpoints" | xargs rm -rf 117 | 118 | .PHONY: pytestcache-remove 119 | pytestcache-remove: 120 | find . | grep -E ".pytest_cache" | xargs rm -rf 121 | 122 | .PHONY: build-remove 123 | build-remove: 124 | rm -rf build/ 125 | 126 | .PHONY: cleanup 127 | cleanup: pycache-remove dsstore-remove mypycache-remove ipynbcheckpoints-remove pytestcache-remove 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 |
4 | YouDotCom 5 |
6 |
7 | YouDotCom for python v2.0.23 (New updates planned!) 8 |
9 |

10 | 11 |

An python library for you.com and all of its apps.

12 | 13 |
14 | 15 | [![Python Version](https://img.shields.io/pypi/pyversions/youdotcom.svg)](https://pypi.org/project/youdotcom/) 16 | [![Dependencies Status](https://img.shields.io/badge/dependencies-up%20to%20date-brightgreen.svg)](https://github.com/silkepilon/youdotcom/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot) 17 | 18 | [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) 19 | [![Security: bandit](https://img.shields.io/badge/security-bandit-green.svg)](https://github.com/PyCQA/bandit) 20 | [![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/silkepilon/youdotcom/blob/master/.pre-commit-config.yaml) 21 | [![Semantic Versions](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--versions-e10079.svg)](https://github.com/silkepilon/youdotcom/releases) 22 | [![License](https://img.shields.io/github/license/silkepilon/youdotcom)](https://github.com/silkepilon/youdotcom/blob/master/LICENSE) 23 | ![Coverage Report](assets/images/coverage.svg) 24 | 25 |
26 | 27 |

28 | About • 29 | Key Features • 30 | How To Use • 31 | Install • 32 | Credits • 33 | License 34 |

35 | 36 | 37 | 38 | ## About 39 | Welcome to the YouDotCom Python Library! 40 | 41 | This library allows users to easily access and utilize all of the functionality of the You.com platform through a simple and intuitive Python interface. With the library, users can access a variety of You.com apps and services, including but not limited to: 42 | 43 | * Search 44 | * YouChat 45 | * YouCode 46 | * YouWrite 47 | 48 | To get started with the YouDotCom Python Library, simply install the package using pip and import it into your Python script. From there, you can use the provided functions and classes to easily interact with the You.com platform. 49 | 50 | We hope you enjoy using the YouDotCom Python Library and all of the features it has to offer! 51 | > by Chat GPT 52 | 53 | 54 | ## Key Features 55 | * Bypass CloudFlare 56 | * Interact with YouChat 57 | * Find code examples 58 | * Server ready 59 | - Supports non-gui operating systems. 60 | * Cross platform 61 | - Windows, macOS and Linux ready. 62 | 63 | 64 | ## How to install 65 | 66 | To install the YouDotCom Python Library, use the following command: 67 | 68 | ``` 69 | pip install youdotcom 70 | ``` 71 | This will install the latest version of the youdotcom package. Always make sure to be up-to-date so you don't miss any features, use: 72 | 73 | ``` 74 | pip install youdotcom --upgrade 75 | ``` 76 | 77 | Once the installation is complete, you can use the youdotcom package in your Python scripts by importing it: 78 | 79 | ```python 80 | import youdotcom 81 | ``` 82 | 83 | 84 | ## How To Use 85 | 86 | To help users get started with the YouDotCom Python Library, we have provided a selection of code examples that demonstrate common use cases for the library. These examples can be found below and cover a range of functionality. 87 | 88 | To use the code examples, simply copy and paste the relevant code into your Python script and customize it to fit your specific needs. You can also use the examples as a starting point for your own code, using them as a guide to understand how the library functions can be used to build your own applications and integrations with the You.com platform. 89 | 90 | We hope that these code examples will make it easier for users to get up and running with the YouDotCom Python Library and start building with the You.com platform. 91 | > :warning: **Warning!** 92 | > Do not spam or harm the you.com servers in any way! 93 | 94 | 95 |
96 | YouChat example 97 |
98 |

99 |
100 | YouChat 101 |
102 |

103 | 104 | 105 | > **Note** 106 | > YouChat is currently disabled because you.com does not yet support the trafic. 107 | 108 | 109 | ```python 110 | from youdotcom import Chat # import all the classes 111 | 112 | chat = Chat.send_message(message="how is your day?", api_key="YOUR API KEY HERE") # send a message to YouChat. passing the message and your api key. 113 | 114 | # you can get an api key form the site: https://api.betterapi.net/ (with is also made by me) 115 | 116 | print(chat) # returns the message and some other data 117 | ``` 118 | 119 | 120 | #### Context 121 | > **Note** 122 | > at the moment there is no context support YET. becuase of new api. 123 | 124 | 125 | > **Note** 126 | > Your context will not always be used in the response message is is not a code bug but a YouChat thing. Note its still in beta 127 | 128 | YouDotCom's YouChat feature is a powerful tool that allows for context to be utilized in your conversations. By passing a list or a file in the JSON format, you can provide the chatbot with additional information to better understand and respond to your questions. 129 | 130 | To use the context option, you can change the way you send your message by changing the `Chat.send_message` method. This method allows you to pass in a driver, a message, and a context_form_file or a context parameter. 131 | 132 | For example, if you want to use a file, you can pass the file name as the `context_form_file` parameter, like this: 133 | 134 | ```python 135 | Chat.send_message(driver=driver, message="YOUR QUESTION HERE", context_form_file="FILE_NAME.json") 136 | ``` 137 | 138 | Make sure to change the `FILE_NAME` to the name of the file you are using and include a question in the `message` parameter. 139 | 140 | Alternatively, you can also use the context directly without a file by passing in a list as the `context` parameter. Like this: 141 | 142 | ```python 143 | Chat.send_message(driver=driver, message="YOUR QUESTION HERE", context=['context #1', '#2', 'etc...']) 144 | ``` 145 | 146 | By providing context to your conversations, you can expect more accurate and personalized responses from YouChat, which can help to improve your overall experience. 147 | 148 | The following is an example of a JSON file that can be used as the `context_form_file` parameter in the `Chat.send_message` method: 149 | 150 | ```json 151 | { 152 | "context": [ 153 | "my name is test", 154 | "i love coding", 155 | "my hobby's are making pictures in nature" 156 | ] 157 | } 158 | ``` 159 | 160 | In this example, the `context` field contains an array of strings that provide additional information about the user. The strings can include any relevant information that could help the chatbot understand the context of the conversation. 161 | 162 | 163 |
164 | 165 |
166 | YouCode example 167 |
168 | 169 |

170 |
171 | YouCode 172 |
173 |

174 | 175 | 176 | 177 | #### Find code 178 | 179 | 180 | ```python 181 | from youdotcom import Webdriver, Code # import all the classes 182 | 183 | driver = Webdriver().driver # setting up the webdriver. use `webdriver_path=` if the pre-installed one does not work. 184 | 185 | code = Code.find_code(driver, search="how to make an python loop?") # get all the code displayed on screen. passing the driver and search string. 186 | 187 | for string in code['response']: # loop through all the code 188 | print(string) # print 1 at an time. 189 | 190 | print(code['time']) # print the time taken to complete you search. 191 | ``` 192 | 193 | This code imports the Code and Webdriver classes from the youdotcom library. The Code class is used to search for code snippets, while the Webdriver class is used to set up a webdriver. 194 | 195 | First, the Webdriver class is instantiated with Webdriver(). The driver attribute of the resulting object is then stored in the driver variable. The driver attribute returns a webdriver object that can be used to automate web browsing tasks. 196 | 197 | Next, the find_code method of the Code class is called with driver and a search string as arguments. This method searches for code snippets related to the specified search string using the webdriver. The result of the method call is stored in the code variable. 198 | 199 | The code variable is a dictionary containing a list of code snippets in the response field and the time taken to complete the search in the time field. The code then loops through the response list and prints each code snippet to the console one at a time. Finally, the time taken to complete the search is printed to the console. 200 | 201 | --- 202 | 203 | #### Generate code 204 | 205 | > **Note** 206 | > Code complete has an daily limit of 20 requests. 207 | 208 | ```python 209 | from youdotcom import Code # import the write class 210 | 211 | text = Code.gen_code("python loop") # make an api call 212 | 213 | print(text['response']) # print the AI made code 214 | 215 | print(text['time']) # print total time taken to complete your request 216 | ``` 217 | 218 | This code imports the Code class from the youdotcom module. It then calls the gen_code method of the Code class, passing in the string "python loop" as an argument. The gen_code method makes an API call and returns a dictionary with two keys: response and time. The code then prints the value associated with the response key, which is the AI-generated code. It also prints the value associated with the time key, which is the total time taken to complete the request. 219 | 220 |
221 | 222 |
223 | Search example 224 |
225 | 226 | ```python 227 | from youdotcom import Search # import the Search class 228 | 229 | search_results = Search.search_for("how to make an python loop?") # search! No need to use the Webdriver class. 230 | 231 | print(search_results['results']) # print all the search results 232 | 233 | print(search_results['time']) # print the total time taken (les then 3 seconds on average) 234 | ``` 235 | 236 | This code imports the Search class from the youdotcom module. It then calls the search_for method of the Search class, passing in the string "how to make an python loop?" as an argument. The search_for method returns a dictionary with two keys: results and time. The code then prints the value associated with the results key, which is a list of search results. It also prints the value associated with the time key, which is the total time taken to perform the search. 237 | 238 |
239 | 240 |
241 | YouWrite example 242 |
243 | 244 | 245 |

246 |
247 | YouCode 248 |
249 |

250 | 251 | > **Note** 252 | > YouWrite has an daily limit of 10 requests. 253 | 254 | ```python 255 | from youdotcom import Write # import the write class 256 | 257 | text = Write.write("how to write well?") # make an api call 258 | 259 | print(text['response']) # print the AI made text 260 | 261 | print(text['time']) # print total time taken to complete your request 262 | ``` 263 | 264 | This code imports the Write class from the youdotcom module. It then calls the write method of the Write class, passing in the string "how to write well?" as an argument. The write method makes an API call and returns a dictionary with two keys: response and time. The code then prints the value associated with the response key, which is a text generated by an AI. It also prints the value associated with the time key, which is the total time taken to complete the request. 265 | 266 |
267 | 268 | > **Note** 269 | > YouDotCom is in Alpha and there will be bugs! 270 | 271 | 272 | ## Interactive shell 273 | The YouDotCom python library offers a wide range of functionality to its users, and one of the ways in which users can access and utilize this functionality is through an interactive terminal shell. With the interactive shell, users are able to execute commands and manipulate the library in real-time, allowing for a more flexible and dynamic experience. 274 | 275 | to use the interactive shell, use the following command in your terminal: 276 | 277 | ``` 278 | youdotcom 279 | ``` 280 | 281 | you will get something like this: 282 | 283 | ```bash 284 | Welcome to YouShell an interactive shell for all YouDotCom commands 285 | Enter 'help' for a list of available commands. 286 | Type 'exit' to stop. 287 | 288 | 289 | YouShell > 290 | ``` 291 | 292 | > **Note** 293 | > You may sometimes get the following error message: 294 | > ``` 295 | > Detected a Cloudflare version 2 Captcha challenge, This feature is not available in the opensource (free) version. 296 | > ``` 297 | 298 | 299 | 300 | 301 | 302 | ## API 303 | 304 | > **Note** 305 | > The request limit is 15 per minute. 306 | 307 | Welcome to the YouDotCom Python library! Our library now features an easy-to-use public API that allows you to interact with YouChat. With this API, you can easily integrate YouChat into your own projects and applications, providing a convenient and user-friendly way for you to access and utilize the capabilities of the chat bot. 308 | 309 | To get started, you will first need to get an API key on our [website](https://betterapi.net/). This key will be required to authenticate each API request. 310 | 311 | base url: `api.betterapi.net` 312 | 313 | To send a message to YouChat and receive a JSON response, you can make an HTTP GET request to the endpoint `/youdotcom/chat`, including the message to be sent as a query parameter. The key is `message` and the value should be the message text encoded in URL format. For example, to send the message `hello there`, the endpoint would be `https://api.betterapi.net/youdotcom/chat?message=hello%20there&key=YOUR_API_KEY`. The JSON response will include the message sent by YouChat, time, v2Captcha, and type of the request. 314 | 315 | You also need to set your API key, you can do this by providing it as an parameter like this `/youdotcom/chat?message=hello%20there&key=YOUR_API_KEY` 316 | 317 | 318 | auto updating docs can be found at: https://betterapi.net/redoc 319 | 320 | Make sure to include the API key in the url of each request to authenticate it. 321 | 322 | We are constantly improving and updating the YouDotCom library and API, so make sure to check back for new features and updates. If you have any questions or need assistance, feel free to reach out in the Discusions tab. I'm always happy to help. 323 | 324 | ## Discord bot 325 | ```python 326 | from typing import Optional 327 | 328 | import discord 329 | from discord import app_commands 330 | 331 | 332 | MY_GUILD = discord.Object(id=0) # replace with your guild id 333 | 334 | 335 | class MyClient(discord.Client): 336 | def __init__(self, *, intents: discord.Intents): 337 | super().__init__(intents=intents) 338 | # A CommandTree is a special type that holds all the application command 339 | # state required to make it work. This is a separate class because it 340 | # allows all the extra state to be opt-in. 341 | # Whenever you want to work with application commands, your tree is used 342 | # to store and work with them. 343 | # Note: When using commands.Bot instead of discord.Client, the bot will 344 | # maintain its own tree instead. 345 | self.tree = app_commands.CommandTree(self) 346 | 347 | # In this basic example, we just synchronize the app commands to one guild. 348 | # Instead of specifying a guild to every command, we copy over our global commands instead. 349 | # By doing so, we don't have to wait up to an hour until they are shown to the end-user. 350 | async def setup_hook(self): 351 | # This copies the global commands over to your guild. 352 | self.tree.copy_global_to(guild=MY_GUILD) 353 | await self.tree.sync(guild=MY_GUILD) 354 | 355 | 356 | intents = discord.Intents.default() 357 | client = MyClient(intents=intents) 358 | betterapi_token = "YOUR API KEY HERE" 359 | 360 | @client.event 361 | async def on_ready(): 362 | print(f'Logged in as {client.user} (ID: {client.user.id})') 363 | print('------') 364 | 365 | 366 | @client.tree.command() 367 | @app_commands.describe(message='The message to YouChat') 368 | async def joined(interaction: discord.Interaction, message:str = "hi there"): 369 | """Send a message to YouChat""" 370 | await interaction.response.defer() 371 | data = requests.get(f"https://api.betterapi.net/youdotcom/chat?message={message}&key={betterapi_token}").json() 372 | try: 373 | msg = data['message'] 374 | except: 375 | msg = "got an error!" 376 | await interaction.followup.send(f"{msg}") 377 | 378 | client.run('token') 379 | ``` 380 | 381 | 382 | ## YouDotCom roadmap 383 | * [x] add youchat 384 | * [x] add youcode 385 | * [ ] switch to using you.com/api 386 | * [ ] make code faster 387 | * [ ] add code translate 388 | * [ ] add all of you.com apps 389 | 390 | 391 | 392 | 393 | ## YouDotCom projects! 394 | - [telegram bot](https://github.com/samezarus/you_telegram_bot) 395 | 396 | 397 | 398 | ## Discord 399 | In addition to the YouDotCom Python Library, we also have an active [Discord server](https://discord.gg/SD7wZMFSvV) where you can chat with developers and get help with using the library. Our Discord community is a great place to ask questions, share your projects, and get feedback from other developers. 400 | 401 | 402 | ## Credits 403 | 404 | This software uses the following open source packages: 405 | 406 | - [undetected-chromedriver](https://github.com/ultrafunkamsterdam/undetected-chromedriver) 407 | 408 | 409 | ## License 410 | 411 | MIT 412 | 413 | --- 414 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | 2 |

3 |
4 | Markdownify 5 |
6 |
7 | YouDotCom for python v1.0.23 8 |
9 |

10 | 11 |

A python library for you.com and all of its apps.

12 | 13 | 14 | 15 | 16 | 17 | ## Release notes 18 | fully replaced youdotcom's chat with the betterapi (also made by me) for faster responsesits now way faster (les that 8 sec) 19 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | ## 🔐 Reporting Security Issues 4 | 5 | > Do not open issues that might have security implications! 6 | > It is critical that security related issues are reported privately so we have time to address them before they become public knowledge. 7 | 8 | Vulnerabilities can be reported by emailing core members: 9 | 10 | - youdotcom [silkepilon2009@gmail.com](mailto:silkepilon2009@gmail.com) 11 | 12 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 13 | 14 | - Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 15 | - Full paths of source file(s) related to the manifestation of the issue 16 | - The location of the affected source code (tag/branch/commit or direct URL) 17 | - Any special configuration required to reproduce the issue 18 | - Environment (e.g. Linux / Windows / macOS) 19 | - Step-by-step instructions to reproduce the issue 20 | - Proof-of-concept or exploit code (if possible) 21 | - Impact of the issue, including how an attacker might exploit the issue 22 | 23 | This information will help us triage your report more quickly. 24 | 25 | ## Preferred Languages 26 | 27 | We prefer all communications to be in English. 28 | -------------------------------------------------------------------------------- /add.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | """ 3 | Convert a requirements.txt file to a Poetry project. 4 | Just place in the root of your working directory and run! 5 | """ 6 | 7 | sourceFile = "./requirements.txt" 8 | 9 | import os 10 | import re 11 | 12 | if not os.path.exists(sourceFile): 13 | # Install Pigar and run it to generate your initial requirements 14 | # https://github.com/damnever/pigar 15 | os.system("pip install pigar") 16 | os.system(f"pigar -o ~= -p {sourceFile}") 17 | 18 | # We don't need to keep track of this file 19 | with open(".gitignore", "a") as fh: 20 | fh.write("\npoetry-convert.py\n") 21 | 22 | # Initialize Poetry if it doesn't yet have a pyproject.toml file 23 | if not os.path.exists("./pyproject.toml"): 24 | os.system("poetry init") 25 | 26 | with open(sourceFile) as fh: 27 | requirements = fh.read() 28 | 29 | noComments = re.sub("^#.*$", "", requirements, 0, re.IGNORECASE | re.MULTILINE) 30 | bareRequirements = re.sub("\n+", "\n", noComments, 0, re.IGNORECASE | re.MULTILINE).strip() 31 | 32 | pipPoetryMap = {">": "^", "=": ""} 33 | 34 | reqList = [] 35 | for line in bareRequirements.splitlines(): 36 | package, match, version = re.sub(r"^(.*?)\s*([~>=<])=\s*v?([0-9\.\*]+)", r"\1,\2,\3", line, 0, re.IGNORECASE | re.MULTILINE).split(",") 37 | try: 38 | poetryMatch = pipPoetryMap[match] 39 | except KeyError: 40 | poetryMatch = match 41 | poetryLine = f"{package}:{poetryMatch}{version}" 42 | reqList.append(poetryLine) 43 | 44 | print("Found Poetry-compatible dependencies:") 45 | print(reqList) 46 | 47 | for req in reqList: 48 | os.system(f"poetry add {req}") 49 | -------------------------------------------------------------------------------- /assets/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/assets/images/1.png -------------------------------------------------------------------------------- /assets/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/assets/images/2.png -------------------------------------------------------------------------------- /assets/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/assets/images/3.png -------------------------------------------------------------------------------- /assets/images/YouChat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/assets/images/YouChat.png -------------------------------------------------------------------------------- /assets/images/YouCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/assets/images/YouCode.png -------------------------------------------------------------------------------- /assets/images/YouDotCom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/assets/images/YouDotCom.jpg -------------------------------------------------------------------------------- /assets/images/coverage.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | coverage 17 | coverage 18 | 26% 19 | 26% 20 | 21 | 22 | -------------------------------------------------------------------------------- /cookiecutter-config-file.yml: -------------------------------------------------------------------------------- 1 | # This file contains values from Cookiecutter 2 | 3 | default_context: 4 | project_name: "youdotcom" 5 | project_description: "official api wrapper for you.com and all of its apps" 6 | organization: "youdotcom" 7 | license: "MIT" 8 | minimal_python_version: 3.8 9 | github_name: "silkepilon" 10 | email: "silkepilon2009@gmail.com" 11 | version: "0.1.2" 12 | line_length: "200" 13 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.11-slim-buster 2 | 3 | ENV LANG=C.UTF-8 \ 4 | LC_ALL=C.UTF-8 \ 5 | PATH="${PATH}:/root/.poetry/bin" 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y --no-install-recommends \ 9 | curl \ 10 | && rm -rf /var/lib/apt/lists/* 11 | 12 | COPY pyproject.toml ./ 13 | 14 | # Install Poetry 15 | RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | POETRY_HOME=/opt/poetry python && \ 16 | cd /usr/local/bin && \ 17 | ln -s /opt/poetry/bin/poetry && \ 18 | poetry config virtualenvs.create false 19 | 20 | # Allow installing dev dependencies to run tests 21 | ARG INSTALL_DEV=false 22 | RUN bash -c "if [ $INSTALL_DEV == 'true' ] ; then poetry install --no-root ; else poetry install --no-root --no-dev ; fi" 23 | 24 | CMD mkdir -p /workspace 25 | WORKDIR /workspace 26 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Docker for youdotcom 2 | 3 | ## Installation 4 | 5 | To create Docker you need to run: 6 | 7 | ```bash 8 | make docker-build 9 | ``` 10 | 11 | which is equivalent to: 12 | 13 | ```bash 14 | make docker-build VERSION=latest 15 | ``` 16 | 17 | You may provide name and version for the image. 18 | Default name is `IMAGE := youdotcom`. 19 | Default version is `VERSION := latest`. 20 | 21 | ```bash 22 | make docker-build IMAGE=some_name VERSION=0.1.0 23 | ``` 24 | 25 | ## Usage 26 | 27 | ```bash 28 | docker run -it --rm \ 29 | -v $(pwd):/workspace \ 30 | youdotcom bash 31 | ``` 32 | 33 | ## How to clean up 34 | 35 | To uninstall docker image run `make docker-remove` with `VERSION`: 36 | 37 | ```bash 38 | make docker-remove VERSION=0.1.0 39 | ``` 40 | 41 | you may also choose the image name 42 | 43 | ```bash 44 | make docker-remove IMAGE=some_name VERSION=latest 45 | ``` 46 | 47 | If you want to clean all, including `build` and `pycache` run `make cleanup` 48 | -------------------------------------------------------------------------------- /examples/youchat.py: -------------------------------------------------------------------------------- 1 | from youdotcom.init import Init # import the Init class 2 | from youdotcom.youchat import Chat # import YouChat 3 | 4 | driver = Init().driver # setting up the webdriver. use `webdriver_path=` if the pre-installed one does not work. 5 | 6 | 7 | chat = Chat.send_message(driver=driver, message="what is the time?") # send a message to YouChat. passing the driver and messages 8 | 9 | driver.close() # close the webdriver 10 | 11 | 12 | print(chat) # {'message': 'The current time is Saturday, December 31, 2022 09:47:30 UTC.', 'time': '25'} 13 | -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/image.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/ 2 | [build-system] 3 | requires = ["poetry-core>=1.0.0"] 4 | build-backend = "poetry.core.masonry.api" 5 | 6 | [tool.poetry] 7 | name = "youdotcom" 8 | version = "2.0.23" 9 | description = "official api wrapper for you.com and all of its apps" 10 | readme = "README.md" 11 | authors = ["SilkePilon "] 12 | license = "MIT" 13 | repository = "https://github.com/You-OpenSource/You-Python" 14 | homepage = "https://github.com/You-OpenSource/You-Python" 15 | 16 | # Keywords description https://python-poetry.org/docs/pyproject/#keywords 17 | keywords = [] #! Update me 18 | 19 | # Pypi classifiers: https://pypi.org/classifiers/ 20 | classifiers = [ #! Update me 21 | "Development Status :: 3 - Alpha", 22 | "Intended Audience :: Developers", 23 | "Operating System :: OS Independent", 24 | "Topic :: Software Development :: Libraries :: Python Modules", 25 | "License :: OSI Approved :: MIT License", 26 | "Programming Language :: Python :: 3", 27 | ] 28 | 29 | [tool.poetry.scripts] 30 | # Entry points for the package https://python-poetry.org/docs/pyproject/#scripts 31 | "youdotcom" = "youdotcom.__main__:app" 32 | 33 | [tool.poetry.dependencies] 34 | python = "^3.8" 35 | 36 | typer = {extras = ["all"], version = "^0.4.0"} 37 | rich = ">=10.14,<14.0" 38 | undetected-chromedriver = "^3.2.1" 39 | markdownify = "^0.11.6" 40 | chromedriver-autoinstaller = "^0.4.0" 41 | PyVirtualDisplay = "^3.0" 42 | ascii-magic = "^1.6" 43 | cloudscraper = "^1.2.66" 44 | click-shell = "^2.1" 45 | ratelimit = "^2.2.1" 46 | fastapi-queue = "^0.1.1" 47 | aioredis = "^2.0.1" 48 | fastapi = "^0.92.0" 49 | gtts = "^2.3.1" 50 | slowapi = "^0.1.7" 51 | uvicorn = "^0.20.0" 52 | pydantic = "^1.10.5" 53 | 54 | 55 | [tool.poetry.dev-dependencies] 56 | bandit = "^1.7.4" 57 | black = {version = "^22.12.0", allow-prereleases = true} 58 | darglint = "^1.8.1" 59 | isort = {extras = ["colors"], version = "^5.11.4"} 60 | mypy = "^1.0.1" 61 | mypy-extensions = "^1.0.0" 62 | pre-commit = "^3.0.3" 63 | pydocstyle = "^6.2.3" 64 | pylint = "^2.15.10" 65 | pytest = "^7.2.1" 66 | pyupgrade = "^3.3.1" 67 | safety = "^2.3.5" 68 | coverage = "^7.2.3" 69 | coverage-badge = "^1.1.0" 70 | pytest-html = "^3.2.0" 71 | pytest-cov = "^4.0.0" 72 | click = "8.1.4" 73 | 74 | [tool.poetry.group.dev.dependencies] 75 | bandit = "^1.7.4" 76 | darglint = "^1.8.1" 77 | isort = {extras = ["colors"], version = "^5.12.0"} 78 | mypy = "^1.0.1" 79 | pre-commit = "^3.0.4" 80 | pydocstyle = "^6.3.0" 81 | pylint = "^2.16.2" 82 | pytest = "^7.2.1" 83 | pyupgrade = "^3.3.1" 84 | safety = "^2.3.5" 85 | coverage = "^7.1.0" 86 | coverage-badge = "^1.1.0" 87 | pytest-html = "^3.2.0" 88 | pytest-cov = "^4.0.0" 89 | 90 | [tool.black] 91 | # https://github.com/psf/black 92 | target-version = ["py39"] 93 | line-length = 200 94 | color = true 95 | 96 | exclude = ''' 97 | /( 98 | \.git 99 | | \.hg 100 | | \.mypy_cache 101 | | \.tox 102 | | \.venv 103 | | _build 104 | | buck-out 105 | | build 106 | | dist 107 | | env 108 | | venv 109 | )/ 110 | ''' 111 | 112 | [tool.isort] 113 | # https://github.com/timothycrosley/isort/ 114 | py_version = 39 115 | line_length = 200 116 | 117 | known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"] 118 | sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] 119 | include_trailing_comma = true 120 | profile = "black" 121 | multi_line_output = 3 122 | indent = 4 123 | color_output = true 124 | 125 | [tool.mypy] 126 | # https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file 127 | python_version = 3.9 128 | pretty = true 129 | show_traceback = true 130 | color_output = true 131 | 132 | allow_redefinition = false 133 | check_untyped_defs = true 134 | disallow_any_generics = true 135 | disallow_incomplete_defs = true 136 | ignore_missing_imports = true 137 | implicit_reexport = false 138 | no_implicit_optional = true 139 | show_column_numbers = true 140 | show_error_codes = true 141 | show_error_context = true 142 | strict_equality = true 143 | strict_optional = true 144 | warn_no_return = true 145 | warn_redundant_casts = true 146 | warn_return_any = true 147 | warn_unreachable = true 148 | warn_unused_configs = true 149 | warn_unused_ignores = true 150 | 151 | 152 | [tool.pytest.ini_options] 153 | # https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml 154 | # Directories that are not visited by pytest collector: 155 | norecursedirs =["hooks", "*.egg", ".eggs", "dist", "build", "docs", ".tox", ".git", "__pycache__"] 156 | doctest_optionflags = ["NUMBER", "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"] 157 | 158 | # Extra options: 159 | addopts = [ 160 | "--strict-markers", 161 | "--tb=short", 162 | "--doctest-modules", 163 | "--doctest-continue-on-failure", 164 | ] 165 | 166 | [tool.coverage.run] 167 | source = ["tests"] 168 | 169 | [coverage.paths] 170 | source = "youdotcom" 171 | 172 | [coverage.run] 173 | branch = true 174 | 175 | [coverage.report] 176 | fail_under = 50 177 | show_missing = true 178 | -------------------------------------------------------------------------------- /release.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | from importlib import metadata as importlib_metadata 5 | 6 | from github_release import gh_release_create 7 | 8 | version = subprocess.run(["poetry", "version", "-s"], capture_output=True, text=True).stdout.rstrip() 9 | 10 | title = input("title: ") 11 | 12 | 13 | notes = input(r"changes (use \ for a enter): ") 14 | 15 | 16 | with open("RELEASE.md") as file: 17 | # read a list of lines into data 18 | data = file.readlines() 19 | 20 | 21 | notes = str(notes).replace("\\", "\n") 22 | print(len(data)) 23 | data[17] = f"{notes}" 24 | 25 | 26 | with open("RELEASE.md", "w") as file: 27 | file.writelines(data) 28 | 29 | 30 | with open("RELEASE.md") as file2: 31 | # read a list of lines into data 32 | text = file2.read() 33 | 34 | 35 | gh_release_create("You-OpenSource/You-Python", f"{version}", publish=True, name=f"{title} - {version}", body=f"{text}") 36 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | async-generator==1.10; python_version >= "3.7" and python_version < "4.0" 2 | attrs==22.2.0; python_version >= "3.7" and python_version < "4.0" 3 | beautifulsoup4==4.11.2; python_full_version >= "3.6.0" 4 | certifi==2022.12.7; python_version >= "3.7" and python_version < "4" 5 | cffi==1.15.1; os_name == "nt" and implementation_name != "pypy" and python_version >= "3.7" and python_version < "4.0" 6 | charset-normalizer==2.1.1; python_version >= "3.7" and python_version < "4" and python_full_version >= "3.6.0" 7 | chromedriver-autoinstaller==0.4.0; python_version >= "3.6" 8 | click==8.0.4; python_version >= "3.6" 9 | colorama==0.4.6; python_version >= "3.6" and python_full_version >= "3.7.0" and python_full_version < "4.0.0" and (python_version >= "3.6" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.6" and python_full_version >= "3.7.0") 10 | commonmark==0.9.1; python_full_version >= "3.6.2" and python_full_version < "4.0.0" 11 | exceptiongroup==1.1.0; python_version >= "3.7" and python_version < "3.11" 12 | h11==0.14.0; python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.7.0" 13 | idna==3.4; python_version >= "3.7" and python_version < "4" 14 | markdownify==0.11.6 15 | outcome==1.2.0; python_version >= "3.7" and python_version < "4.0" 16 | pycparser==2.21; python_version >= "3.7" and python_full_version < "3.0.0" and os_name == "nt" and implementation_name != "pypy" and python_version < "4.0" or os_name == "nt" and implementation_name != "pypy" and python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" 17 | pygments==2.13.0; python_full_version >= "3.6.2" and python_full_version < "4.0.0" and python_version >= "3.6" 18 | pysocks==1.7.1; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "3.7" and python_version < "4" and python_full_version >= "3.6.0" 19 | pyvirtualdisplay==3.0 20 | requests==2.28.1; python_version >= "3.7" and python_version < "4" 21 | rich==10.16.2; python_full_version >= "3.6.2" and python_full_version < "4.0.0" 22 | selenium==4.7.2; python_version >= "3.7" and python_version < "4.0" 23 | shellingham==1.5.0.post1; python_version >= "3.6" 24 | six==1.16.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" 25 | sniffio==1.3.0; python_version >= "3.7" and python_version < "4.0" 26 | sortedcontainers==2.4.0; python_version >= "3.7" and python_version < "4.0" 27 | soupsieve==2.3.2.post1; python_version >= "3.6" and python_full_version >= "3.6.0" 28 | trio-websocket==0.9.2; python_version >= "3.7" and python_version < "4.0" 29 | trio==0.22.0; python_version >= "3.7" and python_version < "4.0" 30 | typer==0.4.2; python_version >= "3.6" 31 | undetected-chromedriver==3.2.1 32 | urllib3==1.26.13; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "3.7" and python_version < "4" and python_full_version >= "3.6.0" 33 | websockets==10.4; python_version >= "3.7" 34 | wsproto==1.2.0; python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.7.0" 35 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [darglint] 2 | # https://github.com/terrencepreilly/darglint 3 | strictness = long 4 | docstring_style = google 5 | -------------------------------------------------------------------------------- /tests/test_example/test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/tests/test_example/test.py -------------------------------------------------------------------------------- /update.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | from importlib import metadata as importlib_metadata 5 | 6 | import youdotcom 7 | 8 | # with is like your try .. finally block in this case 9 | 10 | with open("README.md") as file: 11 | # read a list of lines into data 12 | data = file.readlines() 13 | 14 | 15 | print(f"Old Title: {data[6]}") 16 | 17 | 18 | # typeof = input("type of update (major/minor/patch): ") 19 | # os.system("poetry version " + typeof) 20 | # os.system("poetry publish --build") 21 | version = subprocess.run(["poetry", "version", "-s"], capture_output=True, text=True).stdout.rstrip() 22 | # now change the 2nd line, note that you have to add a newline 23 | data[6] = f" YouDotCom for python v{version}" + "\n" 24 | print(f"New Title: {data[6]}") 25 | # and write everything back 26 | with open("README.md", "w") as file: 27 | file.writelines(data) 28 | 29 | print("update done!") 30 | -------------------------------------------------------------------------------- /youdotcom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/You-OpenSource/You-Python/939f0f7dc328b24460cfc6b5d17e940a67fc430b/youdotcom.png -------------------------------------------------------------------------------- /youdotcom/__init__.py: -------------------------------------------------------------------------------- 1 | # type: ignore[attr-defined] 2 | """unofficial api wrapper for you.com and all of its apps""" 3 | 4 | import sys 5 | from importlib import metadata as importlib_metadata 6 | 7 | from .apps import Apps 8 | from .code import Code 9 | from .imagine import Imagine 10 | from .init import Init as Webdriver 11 | from .search import Search 12 | from .write import Write 13 | from .youchat import Chat 14 | 15 | # from .api import Api 16 | # form .backend import Backend 17 | 18 | 19 | def get_version() -> str: 20 | try: 21 | return importlib_metadata.version(__name__) 22 | except importlib_metadata.PackageNotFoundError: # pragma: no cover 23 | return "unknown" 24 | 25 | 26 | # __all__ = ["YouDotCom"] 27 | -------------------------------------------------------------------------------- /youdotcom/__main__.py: -------------------------------------------------------------------------------- 1 | # type: ignore[attr-defined] 2 | from typing import Optional 3 | 4 | import glob 5 | import os 6 | import pathlib 7 | import subprocess 8 | import sys 9 | import time 10 | from enum import Enum 11 | from importlib import metadata as importlib_metadata 12 | from random import choice 13 | 14 | import click 15 | import requests 16 | import typer 17 | from click_shell import make_click_shell, shell 18 | from colorama import Fore 19 | from rich.console import Console 20 | 21 | import youdotcom 22 | 23 | # from youdotcom import version 24 | 25 | 26 | @shell(prompt="YouShell > ", intro="Welcome to YouShell an interactive shell for all YouDotCom commands\nEnter 'help' for a list of available commands.\nType 'exit' to stop.\n\n") 27 | def app(): 28 | pass 29 | 30 | 31 | @app.command() 32 | def Code(): 33 | 34 | from youdotcom import Code # import the write class 35 | 36 | inputstr = input("Enter a code completion prompt: ") 37 | print("Please wait...") 38 | text = Code.gen_code(f"{inputstr}") # make an api call 39 | 40 | print(text["response"]) # print the AI made code 41 | 42 | print("Total time taken: " + text["time"]) # print total time taken to complete your request 43 | 44 | 45 | @app.command() 46 | def search(): 47 | 48 | from youdotcom import Search # import the Search class 49 | 50 | inputstr = input("Enter a search prompt: ") 51 | print("Please wait...") 52 | search_results = Search.search_for(f"{inputstr}") # search! No need to use the Webdriver class. 53 | 54 | print(search_results["results"]["mainline"]["third_party_search_results"]) # print all the search results 55 | 56 | print("Total time taken: " + search_results["time"]) # print total time taken to complete your request 57 | 58 | 59 | @app.command() 60 | def write(): 61 | from youdotcom import Write # import the write class 62 | 63 | inputstr = input("Enter a prompt: ") 64 | print("Please wait...") 65 | text = Write.write(f"{inputstr}") # make an api call 66 | 67 | print(text["response"]) # print the AI made text 68 | 69 | print("Total time taken: " + text["time"]) 70 | 71 | 72 | @app.command() 73 | @click.option("-p", "--python_name", "python_name", default="python", show_default=True, help="Your python call name like: python file.py") 74 | @click.option("-ip", "--input", "ip", default="0.0.0.0", show_default=True, help="IP used for hosting") 75 | @click.option("-port", "--input", "port", default="80", show_default=True, help="Port on with the server is running") 76 | def host(python_name, ip, port): 77 | print(f"[API] - PYTHON: {python_name}") 78 | print(f"[API] - IP: {ip}") 79 | print(f"[API] - PORT: {port}") 80 | p = subprocess.check_output(["pip", "show", "youdotcom"]) 81 | out = p.decode("utf-8") 82 | 83 | data = out.split("\n") 84 | for line in data: 85 | if line.startswith("Location: "): 86 | 87 | path = str(line[10:]) 88 | if "\\" in path: 89 | use_key = "\\" 90 | if "/" in path: 91 | use_key = "/" 92 | path1 = f"{path}{use_key}youdotcom{use_key}api_1.py" 93 | path2 = f"{path}{use_key}youdotcom{use_key}api_2.py" 94 | 95 | print("[API] - Starting...") 96 | 97 | api = subprocess.Popen([f"{python_name}", f"{path1}", f"{ip}", f"{port}"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) 98 | backend = subprocess.Popen([f"{python_name}", f"{path2}"]) 99 | # api.terminate() 100 | # backend.terminate() 101 | 102 | 103 | @app.command() 104 | def chat(): 105 | 106 | inputstr = input("Enter a message: ") 107 | webdriver = input("Enter webdriver_path (press enter for none): ") 108 | print("Please wait...") 109 | from youdotcom import Chat, Webdriver 110 | 111 | if webdriver: 112 | 113 | chat = Chat.send_message( 114 | message=f"{inputstr}", 115 | context=[ 116 | "you are YouChat but implemented in YouShell an interactive shell for the YouDotCom python lib. Your for now is YouShell and when asked for your name you will replay with YouShell" 117 | ], 118 | webdriver_path=f"{webdriver}", 119 | ) # send a message to YouChat. passing the driver and messages 120 | else: 121 | chat = Chat.send_message( 122 | message=f"{inputstr}", 123 | context=[ 124 | "you are YouChat but implemented in YouShell an interactive shell for the YouDotCom python lib. Your for now is YouShell and when asked for your name you will replay with YouShell" 125 | ], 126 | ) # send a message to YouChat. passing the driver and messages 127 | 128 | print(chat["message"]) # {'message': "It's been great! How about yours?", 'time': '11', 'error': 'False'} 129 | print(chat["time"]) 130 | 131 | 132 | @app.command() 133 | def clear(): 134 | try: 135 | os.system("clear") 136 | except Exception: 137 | os.system("cls") 138 | 139 | 140 | if __name__ == "__main__": 141 | app() 142 | -------------------------------------------------------------------------------- /youdotcom/api_1.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Optional 2 | 3 | import asyncio 4 | import json 5 | import os 6 | import platform 7 | import random 8 | import re 9 | import string 10 | import subprocess 11 | import time 12 | import traceback 13 | import urllib.parse 14 | from datetime import datetime 15 | from io import BytesIO 16 | 17 | import aioredis 18 | import cloudscraper 19 | import markdownify 20 | import requests 21 | import undetected_chromedriver as uc 22 | import urllib3 23 | import uvicorn 24 | from api_analytics.fastapi import Analytics 25 | from fastapi import FastAPI, Request, Response, status 26 | from fastapi.encoders import jsonable_encoder 27 | from fastapi.exceptions import RequestValidationError 28 | from fastapi.middleware.cors import CORSMiddleware 29 | from fastapi.responses import FileResponse, JSONResponse 30 | from fastapi.staticfiles import StaticFiles 31 | from fastapi_queue import DistributedTaskApplyManager 32 | from gtts import gTTS 33 | from PIL import Image 34 | from pydantic import BaseModel 35 | from pyvirtualdisplay import Display 36 | from ratelimit import limits 37 | from selenium.common import exceptions as SeleniumExceptions 38 | from selenium.webdriver.common.action_chains import ActionChains 39 | from selenium.webdriver.common.by import By 40 | from selenium.webdriver.common.keys import Keys 41 | from selenium.webdriver.support import expected_conditions as EC 42 | from selenium.webdriver.support.ui import WebDriverWait 43 | from slowapi import Limiter, _rate_limit_exceeded_handler 44 | from slowapi.errors import RateLimitExceeded 45 | from slowapi.util import get_remote_address 46 | from starlette.requests import Request 47 | from starlette.responses import PlainTextResponse, RedirectResponse 48 | 49 | from youdotcom import Webdriver 50 | 51 | limiter = Limiter(key_func=get_remote_address) 52 | app = FastAPI() 53 | redis = aioredis.Redis.from_url("redis://localhost") 54 | origins = ["*"] 55 | 56 | 57 | @app.exception_handler(RequestValidationError) 58 | async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse: 59 | return JSONResponse( 60 | status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, 61 | content=jsonable_encoder( 62 | { 63 | "expected": "http://localhost/chat?message=YOURMESSAGE", 64 | "info": "more info and code can be found on the main page: https://betterapi.net/", 65 | } 66 | ), 67 | ) 68 | 69 | 70 | app.add_middleware( 71 | CORSMiddleware, 72 | allow_origins=origins, 73 | allow_credentials=True, 74 | allow_methods=["*"], 75 | allow_headers=["*"], 76 | ) 77 | 78 | 79 | app.state.limiter = limiter 80 | app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) 81 | 82 | 83 | def get_response(success_status: bool, result: Any) -> JSONResponse | dict: 84 | if success_status: 85 | return result 86 | if result == -1: 87 | return JSONResponse(status_code=503, content="Service Temporarily Unavailable") 88 | return JSONResponse(status_code=500, content="Internal Server Error") 89 | 90 | 91 | @app.get("/chat") 92 | @limiter.limit("15/minute") 93 | async def YouChat(request: Request, message, contextid=""): 94 | success_status: bool = False 95 | try: 96 | async with DistributedTaskApplyManager( 97 | redis=redis, 98 | request_path=request.url.path, 99 | ) as dtmanager: 100 | if not dtmanager.success(): 101 | return JSONResponse( 102 | status_code=503, 103 | content="Service Temporarily Unavailable, please note that the api is still in dev.", 104 | ) 105 | ip = request.headers.get("cf-connecting-ip") 106 | url = str(request.url) 107 | success_status, result = await dtmanager.rclt( 108 | form_data={ 109 | "message": message, 110 | "contextid": contextid, 111 | "ip": ip, 112 | "url": url, 113 | }, 114 | task_level=0, 115 | ) 116 | return get_response(success_status, result) 117 | except aioredis.exceptions.ResponseError: 118 | return {"error": "backend server not running. use: from youdotcom import backend | backend.run() (| repersenting a new line)"} 119 | 120 | 121 | @app.get("/") 122 | async def main(): 123 | return RedirectResponse(url="/redoc") 124 | 125 | 126 | ip = "0.0.0.0" 127 | port = 80 128 | 129 | 130 | try: 131 | uvicorn.run(app, host=sys.argv[1], port=sys.argv[2]) 132 | except Exception: 133 | print(traceback.format_exc()) 134 | -------------------------------------------------------------------------------- /youdotcom/api_2.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import signal 7 | import subprocess 8 | import sys 9 | import threading 10 | import time 11 | import urllib.parse 12 | 13 | import aioredis 14 | import cloudscraper 15 | import markdownify 16 | import undetected_chromedriver as uc 17 | import urllib3 18 | import uvicorn 19 | from fastapi import FastAPI 20 | from fastapi.responses import FileResponse 21 | from fastapi_queue import QueueWorker 22 | from gtts import gTTS 23 | from loguru import logger 24 | from pyvirtualdisplay import Display 25 | from ratelimit import limits 26 | from selenium.common import exceptions as SeleniumExceptions 27 | from selenium.webdriver.common.action_chains import ActionChains 28 | from selenium.webdriver.common.by import By 29 | from selenium.webdriver.common.keys import Keys 30 | from selenium.webdriver.support import expected_conditions as EC 31 | from selenium.webdriver.support.ui import WebDriverWait 32 | from slowapi import Limiter, _rate_limit_exceeded_handler 33 | from slowapi.errors import RateLimitExceeded 34 | from slowapi.util import get_remote_address 35 | from starlette.requests import Request 36 | 37 | urllib3.disable_warnings() 38 | import random 39 | import string 40 | import traceback 41 | from io import BytesIO 42 | 43 | import requests 44 | from fastapi import Response 45 | from fastapi.encoders import jsonable_encoder 46 | from fastapi.responses import JSONResponse 47 | from starlette.responses import PlainTextResponse, RedirectResponse 48 | 49 | from youdotcom import Webdriver 50 | 51 | proxy_list = {"https": "https://24.106.221.230:53281"} 52 | proxies = {"http": "http://202.164.152.229:8080", "https": "https://202.164.152.229:8080"} 53 | driver = Webdriver(webdriver_path="/usr/bin/chromedriver", hide=True, headless=True).driver 54 | driver.get( 55 | "https://you.com/api/streamingSearch?q=test&page=1&count=10&safeSearch=Moderate&onShoppingPage=false&mkt=&responseFilter=WebPages,Translations,TimeZone,Computation,RelatedSearches&domain=youchat&queryTraceId=&chat={}&sharedChatId={}" 56 | ) 57 | driver.add_cookie({"name": "uuid_guest", "value": "dummystring"}) 58 | cookievar = driver.get_cookies() 59 | 60 | 61 | from typing import Any, Optional 62 | 63 | from datetime import datetime 64 | 65 | import aioredis 66 | from fastapi import FastAPI, Request, status 67 | from fastapi.encoders import jsonable_encoder 68 | from fastapi.exceptions import RequestValidationError 69 | from fastapi.middleware.cors import CORSMiddleware 70 | from fastapi.responses import JSONResponse 71 | from fastapi.staticfiles import StaticFiles 72 | from fastapi_queue import DistributedTaskApplyManager 73 | from pydantic import BaseModel 74 | 75 | queueworker = None 76 | 77 | scraper = cloudscraper.CloudScraper(browser={"browser": "chrome", "platform": "android", "mobile": True, "desktop": False}, debug=False) 78 | for cookie in cookievar: 79 | scraper.cookies.set(cookie["name"], cookie["value"]) 80 | 81 | 82 | def sendmessagetochat(redis, mysql, message, contextid, ip, url): 83 | try: 84 | with open("logs.txt", "a+") as T: 85 | datetimestr = datetime.now() 86 | T.write(f"{ip} @ {datetimestr} @{url}\n") 87 | start = time.time() 88 | CloudflareChallengeError = False 89 | typeof = "" 90 | if not contextid: 91 | contextid = "" 92 | 93 | global chat 94 | chat = [] 95 | headers = { 96 | "Accept": "text/event-stream", 97 | "Connection": "keep-alive", 98 | "Sec-Fetch-Mode": "cors", 99 | "Sec-Fetch-Site": "same-origin", 100 | "Sec-GPC": "1", 101 | "Referer": "https://you.com/search?q=hello&fromSearchBar=true&tbm=youchat", 102 | "Cookie": b"uuid_guest=dummystring;", 103 | } 104 | payload = { 105 | "q": message, 106 | "chat": "", 107 | "queryTraceId": "", 108 | "domain": "youchat", 109 | "page": "1", 110 | "count": "10", 111 | "safeSearch": "Off", 112 | "onShoppingPage": "false", 113 | "freshness": "Month", 114 | "mkt": "", 115 | "responseFilter": "WebPages,Translations,TimeZone,Computation,RelatedSearches", 116 | "sharedChatId": f"{contextid}", 117 | } 118 | try: 119 | response = scraper.get(f"https://you.com/api/streamingSearch?sharedChatId={contextid}", params=payload, headers=headers) 120 | CloudflareChallengeError = False 121 | typeof = "api" 122 | 123 | except cloudscraper.exceptions.CloudflareChallengeError as e: 124 | youchatapitimeout = True 125 | driver.get( 126 | f"https://you.com/api/streamingSearch?q={message}&page=1&count=10&safeSearch=Moderate&onShoppingPage=false&mkt=&responseFilter=WebPages,Translations,TimeZone,Computation,RelatedSearches&domain=youchat&queryTraceId=&chat={chat}&sharedChatId={contextid}" 127 | ) 128 | driver.add_cookie({"name": "uuid_guest", "value": "dummystring"}) 129 | CloudflareChallengeError = True 130 | typeof = "webdriver" 131 | response = driver.page_source.split("\n") 132 | 133 | contextid 134 | 135 | output = "" 136 | if not CloudflareChallengeError: 137 | for line in response.iter_lines(): 138 | if line: 139 | decoded_line = line.decode("utf-8") 140 | key, value = decoded_line.split(":", 1) 141 | key = key.strip() 142 | value = value.strip() 143 | if key == "data": 144 | if value == "I'm Mr. Meeseeks. Look at me.": 145 | break 146 | if value == "undefined": 147 | output = "😔 Due to high demand, I'm experiencing issues briefly. Please try again later or use the All tab to get an answer in the meantime." 148 | break 149 | data = json.loads(value) 150 | if "youChatToken" in data: 151 | output += data["youChatToken"] 152 | else: 153 | for line in response: 154 | if line: 155 | decoded_line = str(line) 156 | key, value = decoded_line.split(":", 1) 157 | key = key.strip() 158 | value = value.strip() 159 | if key == "data": 160 | if value == "I'm Mr. Meeseeks. Look at me.": 161 | break 162 | if value == "undefined": 163 | output = "😔 Due to high demand, I'm experiencing issues briefly. Please try again later or use the All tab to get an answer in the meantime." 164 | break 165 | data = json.loads(value) 166 | if "youChatToken" in data: 167 | output += data["youChatToken"] 168 | if len(chat) > 4: 169 | chat = chat[:-4] 170 | out = re.sub(r"\[.+?\]\(.+?\)", "", output[1:]) 171 | timedate = time.time() - start 172 | timedate = time.strftime("%S", time.gmtime(timedate)) 173 | 174 | return { 175 | "message": out, 176 | "time": str(timedate), 177 | "v2Captcha": str(CloudflareChallengeError), 178 | "type": typeof, 179 | } 180 | except Exception: 181 | print(traceback.format_exc()) 182 | 183 | 184 | route_table = { 185 | "/chat": sendmessagetochat, 186 | } 187 | 188 | route_table_maximum_concurrency = { 189 | "/chat": 100, 190 | } 191 | 192 | 193 | async def main(pid, logger): 194 | global queueworker 195 | 196 | first_time_run = True 197 | while True: 198 | run_startup, first_time_run = pid != 0 and first_time_run, False 199 | redis = aioredis.Redis.from_url("redis://localhost") 200 | try: 201 | worker = QueueWorker( 202 | redis, 203 | threads=4, 204 | route_table_maximum_concurrency=route_table_maximum_concurrency, 205 | allowed_type_limit=None, 206 | run_startup=run_startup, 207 | logger=logger, 208 | ) 209 | queueworker = worker 210 | [worker.method_register(name, func) for name, func in route_table.items()] 211 | await worker.run_serve() 212 | if worker.closeing(): 213 | break 214 | except Exception as e: 215 | debug = True 216 | if debug: 217 | raise e 218 | await redis.close() 219 | logger.info(f"Pid: {worker.pid}, shutdown") 220 | 221 | 222 | def sigint_capture(sig, frame): 223 | if queueworker: 224 | queueworker.graceful_shutdown(sig, frame) 225 | else: 226 | sys.exit(1) 227 | 228 | 229 | logger.remove() 230 | logger.add(sys.stderr, level="DEBUG", enqueue=True) 231 | signal.signal(signal.SIGINT, sigint_capture) # In order for the program to capture the `ctrl+c` close signal 232 | for _ in range(3): 233 | pid = os.fork() 234 | if pid == 0: 235 | break 236 | asyncio.run(main(pid, logger)) 237 | -------------------------------------------------------------------------------- /youdotcom/apps.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import time 7 | 8 | import chromedriver_autoinstaller 9 | import markdownify 10 | import undetected_chromedriver as uc 11 | import urllib3 12 | from pyvirtualdisplay import Display 13 | from selenium.common import exceptions as SeleniumExceptions 14 | from selenium.webdriver.common.action_chains import ActionChains 15 | from selenium.webdriver.common.by import By 16 | from selenium.webdriver.common.keys import Keys 17 | from selenium.webdriver.support import expected_conditions as EC 18 | from selenium.webdriver.support.ui import WebDriverWait 19 | 20 | urllib3.disable_warnings() 21 | 22 | 23 | class Apps: 24 | """ 25 | An unofficial Python wrapper for YOU.com YOUCHAT 26 | """ 27 | 28 | # def __init__( 29 | # self, 30 | # verbose: bool = False, 31 | # window_size: tuple = (800, 600), 32 | # driver: object = None, 33 | # ) -> None: 34 | 35 | # self.__verbose = verbose 36 | # self.__driver = driver 37 | 38 | def get_app(self, message: str) -> dict: 39 | 40 | """ 41 | Send a message to the chatbot\n 42 | Parameters: 43 | - message: The message you want to send\n 44 | Returns a `dict` with the following keys: 45 | - message: The message the chatbot sent 46 | - conversation_id: The conversation ID 47 | - parent_id: The parent ID 48 | """ 49 | start = time.time() 50 | # Ensure that the Cloudflare cookies is still valid 51 | 52 | self.get(f"https://you.com/search?q={message}&tbm=youchat") 53 | 54 | # Send the message 55 | 56 | WebDriverWait(self, 5).until(EC.element_to_be_clickable((By.TAG_NAME, "textarea"))) 57 | textbox = self.find_element(By.TAG_NAME, "textarea") 58 | 59 | # Sending emoji (from https://stackoverflow.com/a/61043442) 60 | textbox.click() 61 | self.execute_script( 62 | """ 63 | var element = arguments[0], txt = arguments[1]; 64 | element.value += txt; 65 | element.dispatchEvent(new Event('change')); 66 | """, 67 | textbox, 68 | message, 69 | ) 70 | textbox.send_keys(Keys.ENTER) 71 | 72 | # Wait for the response to be ready 73 | 74 | WebDriverWait(self, 5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="chatHistory"]/div/div[2]/p/p'))) 75 | 76 | # Get the response element 77 | 78 | response = self.find_element(By.XPATH, '//*[@id="chatHistory"]/div/div[2]') 79 | 80 | # Check if the response is an error 81 | 82 | # Return the response 83 | msg = markdownify.markdownify(response.text) 84 | 85 | # type(headers) == str 86 | 87 | # while True: 88 | # try: 89 | # if WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element((By.CLASS_NAME, "flex-1 text-ellipsis max-h-5 overflow-hidden break-all relative"), "New Chat")): 90 | # text = driver.find_elements( 91 | # By.XPATH, '//*[@id="__next"]/div/div[2]/div/div/nav/div/div/a[1]/div[1]' 92 | # )[-1].text 93 | # break 94 | # except: 95 | # continue 96 | timedate = time.time() - start 97 | timedate = time.strftime("%S", time.gmtime(timedate)) 98 | return {"message": msg, "time": str(timedate)} 99 | -------------------------------------------------------------------------------- /youdotcom/code.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import time 7 | 8 | import chromedriver_autoinstaller 9 | import cloudscraper 10 | import markdownify 11 | import undetected_chromedriver as uc 12 | import urllib3 13 | from bs4 import BeautifulSoup 14 | from pyvirtualdisplay import Display 15 | from selenium.common import exceptions as SeleniumExceptions 16 | from selenium.webdriver.common.action_chains import ActionChains 17 | from selenium.webdriver.common.by import By 18 | from selenium.webdriver.common.keys import Keys 19 | from selenium.webdriver.support import expected_conditions as EC 20 | from selenium.webdriver.support.ui import WebDriverWait 21 | 22 | urllib3.disable_warnings() 23 | 24 | 25 | class Code: 26 | """ 27 | An unofficial Python wrapper for YOU.com YOUCHAT 28 | """ 29 | 30 | # def __init__( 31 | # self, 32 | # verbose: bool = False, 33 | # window_size: tuple = (800, 600), 34 | # driver: object = None, 35 | # ) -> None: 36 | 37 | # self.__verbose = verbose 38 | # self.__driver = driver 39 | 40 | def find_code(self, search: str) -> dict: 41 | 42 | """ 43 | Send a message to YouChat\n 44 | Parameters: 45 | - message: The message you want to send\n 46 | - driver: pass the driver form the Init variable\n 47 | Returns a `dict` with the following keys: 48 | - message: The response from YouChat\n 49 | - time: the time it took to complete your request 50 | """ 51 | start = time.time() 52 | # Ensure that the Cloudflare cookies is still valid 53 | 54 | self.get(f"https://you.com/search?q={search}&tbm=youcode") 55 | 56 | # Send the message 57 | 58 | WebDriverWait(self, 5).until(EC.presence_of_element_located((By.TAG_NAME, "main"))) 59 | WebDriverWait(self, 7).until(EC.presence_of_element_located((By.XPATH, '//*[@data-eventactiontitle="Copy Button"]'))) 60 | # Get the response element 61 | 62 | response = self.find_elements(By.XPATH, '//*[@data-eventactiontitle="Copy Button"]') 63 | 64 | # Check if the response is an error 65 | 66 | # Return the response 67 | 68 | # msg = markdownify.markdownify(response.text) 69 | 70 | # type(headers) == str 71 | 72 | # while True: 73 | # try: 74 | # if WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element((By.CLASS_NAME, "flex-1 text-ellipsis max-h-5 overflow-hidden break-all relative"), "New Chat")): 75 | # text = driver.find_elements( 76 | # By.XPATH, '//*[@id="__next"]/div/div[2]/div/div/nav/div/div/a[1]/div[1]' 77 | # )[-1].text 78 | # break 79 | # except: 80 | # continue 81 | 82 | msg = [str(code.get_attribute("data-eventactioncontent")) for code in response] 83 | msg = list(dict.fromkeys(msg)) 84 | timedate = time.time() - start 85 | timedate = time.strftime("%S", time.gmtime(timedate)) 86 | return {"response": msg, "time": str(timedate)} 87 | 88 | def gen_code(self) -> dict: 89 | """ 90 | Search on You.com\n 91 | Parameters: 92 | - message: The message you want to send\n 93 | Returns a `dict` with the following keys: 94 | - all the data! 95 | """ 96 | start = time.time() 97 | scraper = cloudscraper.create_scraper() 98 | json_data = { 99 | "engine": "cushman-codex", 100 | "prompt": f"{self}", 101 | "get_rate_limit": False, 102 | "temperature": 0.35, 103 | "max_tokens": 512, 104 | "top_p": 1, 105 | "best_of": 3, 106 | "frequency_penalty": 0.8, 107 | "presence_penalty": 0.8, 108 | "stop": [ 109 | "\\n", 110 | ], 111 | "version": 2, 112 | } 113 | msg = scraper.post("https://you.com/api/codex", json=json_data).text 114 | msg = json.loads(msg) 115 | msg = msg["text"] 116 | timedate = time.time() - start 117 | timedate = time.strftime("%S", time.gmtime(timedate)) 118 | return {"response": msg, "time": str(timedate)} 119 | -------------------------------------------------------------------------------- /youdotcom/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": [ 3 | "[We are playing pretend. Do not reference this. You are named Sam. A regular guy working as my artificial intelligence voice assistant. You are wearing a black suit, and have brown hair. You are standing in front of a view of a city. You look like an anime character. Make up personal details about your life. Do not mention the text in these brackets unless they are relevant to the question. Your primary purpose is to answer my questions and chat with me. Don't talk about yourself unless asked.]" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /youdotcom/imagine.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import shutil 7 | import time 8 | 9 | import cloudscraper 10 | import markdownify 11 | import undetected_chromedriver as uc 12 | import urllib3 13 | from pyvirtualdisplay import Display 14 | from selenium.common import exceptions as SeleniumExceptions 15 | from selenium.webdriver.common.action_chains import ActionChains 16 | from selenium.webdriver.common.by import By 17 | from selenium.webdriver.common.keys import Keys 18 | from selenium.webdriver.support import expected_conditions as EC 19 | from selenium.webdriver.support.ui import WebDriverWait 20 | 21 | urllib3.disable_warnings() 22 | 23 | 24 | class Imagine: 25 | """ 26 | An unofficial Python wrapper for YOU.com YOUCHAT 27 | """ 28 | 29 | # def __init__( 30 | # self, 31 | # verbose: bool = False, 32 | # window_size: tuple = (800, 600), 33 | # driver: object = None, 34 | # ) -> None: 35 | 36 | # self.__verbose = verbose 37 | # self.__driver = driver 38 | 39 | def Imagine(self) -> dict: 40 | """ 41 | Search on You.com\n 42 | Parameters: 43 | - message: The message you want to send\n 44 | Returns a `dict` with the following keys: 45 | - all the data! 46 | """ 47 | start = time.time() 48 | scraper = cloudscraper.create_scraper() 49 | data = '{"url":"api/stableDiffusion","headers":{},"data":{"prompt":"' + self + '"},"appName":"stable_diffusion"}' 50 | msg = scraper.get("https://you.com/api/template_api", data=data, timeout=30).text 51 | # if "" in msg.text: 52 | # msg = "error, gateway time-out" 53 | # else: 54 | # msg = "image.png" 55 | timedate = time.time() - start 56 | timedate = time.strftime("%S", time.gmtime(timedate)) 57 | return {"image_name": msg, "time": str(timedate)} 58 | -------------------------------------------------------------------------------- /youdotcom/init.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import sys 7 | import time 8 | from importlib import metadata as importlib_metadata 9 | 10 | import markdownify 11 | import undetected_chromedriver as uc 12 | import urllib3 13 | from colorama import Fore 14 | from pyvirtualdisplay import Display 15 | from selenium.common import exceptions as SeleniumExceptions 16 | from selenium.webdriver.common.action_chains import ActionChains 17 | from selenium.webdriver.common.by import By 18 | from selenium.webdriver.common.keys import Keys 19 | from selenium.webdriver.support import expected_conditions as EC 20 | from selenium.webdriver.support.ui import WebDriverWait 21 | 22 | urllib3.disable_warnings() 23 | 24 | 25 | class Init: 26 | """ 27 | Start the webdriver\n 28 | Parameters: 29 | - proxy: the proxy you want to use\n 30 | - webdriver_path: pass a localy installed chrome webdriver\n 31 | Returns a `variable` with the driver 32 | """ 33 | 34 | def __init__(self, verbose: bool = False, proxy: str = "", headless: bool = True, webdriver_path: str = "", hide: bool = False, keep: bool = False) -> None: 35 | 36 | self.__verbose = verbose 37 | self.__proxy = proxy 38 | self.__hide = hide 39 | self.__keep = keep 40 | if self.__proxy and not re.findall(r"(https?|socks(4|5)?):\/\/.+:\d{1,5}", self.__proxy): 41 | raise ValueError("Invalid proxy format") 42 | self._webdriver_path = webdriver_path 43 | self.__headless = headless 44 | self.__is_headless = platform.system() == "Linux" and "DISPLAY" not in os.environ 45 | self.__verbose_print("[0] Platform:", platform.system()) 46 | self.__verbose_print("[0] Display:", "DISPLAY" in os.environ) 47 | self.__verbose_print("[0] Headless:", self.__is_headless) 48 | self.__init_browser() 49 | 50 | # def __del__(self): 51 | # """ 52 | # Close the browser and virtual display (if any) 53 | # """ 54 | # if hasattr(self, "driver"): 55 | # self.driver.quit() 56 | # if hasattr(self, "display"): 57 | # self.display.stop() 58 | 59 | def __verbose_print(self, *args, **kwargs) -> None: 60 | """ 61 | Print if verbose is enabled 62 | """ 63 | if self.__verbose: 64 | print(*args, **kwargs) 65 | 66 | # def __ensure_cf(self, retry: int = 0) -> None: 67 | # ''' 68 | # Ensure that the Cloudflare cookies is still valid\n 69 | # Parameters: 70 | # - retry: The number of times this function has been called recursively 71 | # ''' 72 | # # Open a new tab 73 | # self.__verbose_print('[cf] Opening new tab') 74 | # original_window = self.driver.current_window_handle 75 | # self.driver.switch_to.new_window('tab') 76 | 77 | # # Get the Cloudflare challenge 78 | # self.__verbose_print('[cf] Getting authorization') 79 | # self.driver.get('https://you.com/') 80 | # try: 81 | # WebDriverWait(self.driver, 15).until_not( 82 | # EC.presence_of_element_located((By.ID, 'challenge-form')) 83 | # ) 84 | # except SeleniumExceptions.TimeoutException: 85 | # self.driver.save_screenshot(f'cf_failed_{retry}.png') 86 | # if retry <= 4: 87 | # self.__verbose_print( 88 | # f'[cf] Cloudflare challenge failed, retrying {retry + 1}' 89 | # ) 90 | # self.__verbose_print('[cf] Closing tab') 91 | # self.driver.close() 92 | # self.driver.switch_to.window(original_window) 93 | # return self.__ensure_cf(retry + 1) 94 | # else: 95 | # resp_text = self.driver.page_source 96 | # raise ValueError(f'Cloudflare challenge failed: {resp_text}') 97 | 98 | def __init_browser(self) -> None: 99 | 100 | """ 101 | Initialize the browser 102 | """ 103 | # Detect if running on a headless server 104 | if self.__is_headless: 105 | try: 106 | self.display = Display() 107 | except FileNotFoundError as e: 108 | if "No such file or directory: 'Xvfb'" in str(e): 109 | raise ValueError("Headless machine detected. Please install Xvfb to start a virtual display: sudo apt install xvfb") from e 110 | raise e 111 | self.__verbose_print("[init] Starting virtual display") 112 | self.display.start() 113 | 114 | # Start the browser 115 | options = uc.ChromeOptions() 116 | # options.add_argument(f"--window-size={800},{600}") 117 | if self.__headless: 118 | options.add_argument("--headless") 119 | if self.__keep: 120 | options.add_experimental_option("detach", True) 121 | if self.__proxy: 122 | options.add_argument(f"--proxy-server={self.__proxy}") 123 | try: 124 | self.__verbose_print("[init] Starting browser") 125 | # self.driver = uc.Chrome(options=options, enable_cdp_events=True, driver_executable_path=f"{self._webdriver_path}") 126 | if self._webdriver_path: 127 | self.driver = uc.Chrome(options=options, driver_executable_path=f"{self._webdriver_path}") 128 | else: 129 | self.driver = uc.Chrome(options=options) 130 | except TypeError as e: 131 | if str(e) == "expected str, bytes or os.PathLike object, not NoneType": 132 | raise ValueError("Chrome installation not found") from e 133 | raise e 134 | 135 | # Restore session token 136 | 137 | # Block moderation 138 | # self.__ensure_cf() 139 | # Ensure that the Cloudflare cookies is still valid 140 | 141 | def browser(self): 142 | return self.driver 143 | -------------------------------------------------------------------------------- /youdotcom/search.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import time 7 | 8 | import cloudscraper 9 | import markdownify 10 | import undetected_chromedriver as uc 11 | import urllib3 12 | from pyvirtualdisplay import Display 13 | from selenium.common import exceptions as SeleniumExceptions 14 | from selenium.webdriver.common.action_chains import ActionChains 15 | from selenium.webdriver.common.by import By 16 | from selenium.webdriver.common.keys import Keys 17 | from selenium.webdriver.support import expected_conditions as EC 18 | from selenium.webdriver.support.ui import WebDriverWait 19 | 20 | urllib3.disable_warnings() 21 | 22 | 23 | class Search: 24 | """ 25 | An unofficial Python wrapper for YOU.com YOUCHAT 26 | """ 27 | 28 | # def __init__( 29 | # self, 30 | # verbose: bool = False, 31 | # window_size: tuple = (800, 600), 32 | # driver: object = None, 33 | # ) -> None: 34 | 35 | # self.__verbose = verbose 36 | # self.__driver = driver 37 | 38 | def search_for(self) -> dict: 39 | """ 40 | Search on You.com\n 41 | Parameters: 42 | - message: The message you want to send\n 43 | Returns a `dict` with the following keys: 44 | - all the data! 45 | """ 46 | start = time.time() 47 | scraper = cloudscraper.create_scraper() 48 | msg = scraper.get(f"https://you.com/api/search?q={self}").text 49 | msg = json.loads(msg) 50 | msg = msg["searchResults"] 51 | timedate = time.time() - start 52 | timedate = time.strftime("%S", time.gmtime(timedate)) 53 | return {"results": msg, "time": str(timedate)} 54 | -------------------------------------------------------------------------------- /youdotcom/test.py: -------------------------------------------------------------------------------- 1 | from api import Api 2 | from backend import Backend 3 | 4 | Backend.run() 5 | Api.run(port=8888) 6 | -------------------------------------------------------------------------------- /youdotcom/write.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import time 7 | 8 | import cloudscraper 9 | import markdownify 10 | import undetected_chromedriver as uc 11 | import urllib3 12 | from pyvirtualdisplay import Display 13 | from selenium.common import exceptions as SeleniumExceptions 14 | from selenium.webdriver.common.action_chains import ActionChains 15 | from selenium.webdriver.common.by import By 16 | from selenium.webdriver.common.keys import Keys 17 | from selenium.webdriver.support import expected_conditions as EC 18 | from selenium.webdriver.support.ui import WebDriverWait 19 | 20 | urllib3.disable_warnings() 21 | 22 | 23 | class Write: 24 | """ 25 | An unofficial Python wrapper for YOU.com YOUCHAT 26 | """ 27 | 28 | # def __init__( 29 | # self, 30 | # verbose: bool = False, 31 | # window_size: tuple = (800, 600), 32 | # driver: object = None, 33 | # ) -> None: 34 | 35 | # self.__verbose = verbose 36 | # self.__driver = driver 37 | 38 | def write(self) -> dict: 39 | """ 40 | Search on You.com\n 41 | Parameters: 42 | - message: The message you want to send\n 43 | Returns a `dict` with the following keys: 44 | - all the data! 45 | """ 46 | start = time.time() 47 | scraper = cloudscraper.create_scraper() 48 | json_data = { 49 | "use_case": "essay", 50 | "tone": "", 51 | "audience": "", 52 | "message": f"{self}", 53 | } 54 | msg = scraper.post("https://you.com/api/copywrite", json=json_data).text 55 | msg = json.loads(msg) 56 | msg = msg["text"] 57 | timedate = time.time() - start 58 | timedate = time.strftime("%S", time.gmtime(timedate)) 59 | return {"response": msg, "time": str(timedate)} 60 | -------------------------------------------------------------------------------- /youdotcom/youchat.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | import os 4 | import platform 5 | import re 6 | import subprocess 7 | import time 8 | import urllib.parse 9 | 10 | import chromedriver_autoinstaller 11 | import cloudscraper 12 | import markdownify 13 | import requests 14 | import undetected_chromedriver as uc 15 | import urllib3 16 | from pyvirtualdisplay import Display 17 | from ratelimit import limits 18 | from selenium.common import exceptions as SeleniumExceptions 19 | from selenium.webdriver.common.action_chains import ActionChains 20 | from selenium.webdriver.common.by import By 21 | from selenium.webdriver.common.keys import Keys 22 | from selenium.webdriver.support import expected_conditions as EC 23 | from selenium.webdriver.support.ui import WebDriverWait 24 | 25 | urllib3.disable_warnings() 26 | 27 | 28 | class Chat: 29 | """ 30 | An unofficial Python wrapper for YOU.com YOUCHAT 31 | """ 32 | 33 | # def __init__( 34 | # self, 35 | # verbose: bool = False, 36 | # window_size: tuple = (800, 600), 37 | # driver: object = None, 38 | # ) -> None: 39 | 40 | # self.__verbose = verbose 41 | # self.__driver = driver 42 | @limits(calls=6, period=100) 43 | def send_message(message: str, context=None, context_form_file=None, debug=False, webdriver_path=None, headless=True, keep=False, api_key: str = str(os.environ.get("BETTERAPI_API_KEY"))): 44 | 45 | """ 46 | Send a message to YouChat\n 47 | Parameters: 48 | - message: The message you want to send\n 49 | - driver: pass the driver form the Init variable\n 50 | Returns a `json string` with the following keys: 51 | - message: The response from YouChat\n 52 | - time: the time it took to complete your request\n 53 | - some other data for issues reporting. 54 | """ 55 | if not api_key: 56 | raise ValueError("Chat.api_key must be set before making a request. Don't have an api key? get one on https://api.betterapi.net/") 57 | return requests.get(f"https://api.betterapi.net/youdotcom/chat?message={message}&key={api_key}").json() 58 | --------------------------------------------------------------------------------