├── .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 |
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 | [](https://pypi.org/project/youdotcom/)
16 | [](https://github.com/silkepilon/youdotcom/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot)
17 |
18 | [](https://github.com/psf/black)
19 | [](https://github.com/PyCQA/bandit)
20 | [](https://github.com/silkepilon/youdotcom/blob/master/.pre-commit-config.yaml)
21 | [](https://github.com/silkepilon/youdotcom/releases)
22 | [](https://github.com/silkepilon/youdotcom/blob/master/LICENSE)
23 | 
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 |
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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------