webscout 8.2.9__py3-none-any.whl → 2026.1.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- webscout/AIauto.py +524 -251
- webscout/AIbase.py +247 -319
- webscout/AIutel.py +68 -703
- webscout/Bard.py +1072 -1026
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/__init__.py +20 -12
- webscout/Extra/GitToolkit/gitapi/gist.py +142 -0
- webscout/Extra/GitToolkit/gitapi/organization.py +91 -0
- webscout/Extra/GitToolkit/gitapi/repository.py +308 -195
- webscout/Extra/GitToolkit/gitapi/search.py +162 -0
- webscout/Extra/GitToolkit/gitapi/trending.py +236 -0
- webscout/Extra/GitToolkit/gitapi/user.py +128 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +82 -62
- webscout/Extra/YTToolkit/README.md +443 -375
- webscout/Extra/YTToolkit/YTdownloader.py +953 -957
- webscout/Extra/YTToolkit/__init__.py +3 -3
- webscout/Extra/YTToolkit/transcriber.py +595 -476
- webscout/Extra/YTToolkit/ytapi/README.md +230 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +22 -6
- webscout/Extra/YTToolkit/ytapi/captions.py +190 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +302 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +178 -118
- webscout/Extra/YTToolkit/ytapi/hashtag.py +120 -0
- webscout/Extra/YTToolkit/ytapi/https.py +89 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -8
- webscout/Extra/YTToolkit/ytapi/query.py +143 -40
- webscout/Extra/YTToolkit/ytapi/shorts.py +122 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +68 -63
- webscout/Extra/YTToolkit/ytapi/suggestions.py +97 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +66 -62
- webscout/Extra/YTToolkit/ytapi/video.py +403 -232
- webscout/Extra/__init__.py +2 -3
- webscout/Extra/gguf.py +1298 -684
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +28 -28
- webscout/Extra/tempmail/async_utils.py +143 -141
- webscout/Extra/tempmail/base.py +172 -161
- webscout/Extra/tempmail/cli.py +191 -187
- webscout/Extra/tempmail/emailnator.py +88 -84
- webscout/Extra/tempmail/mail_tm.py +378 -361
- webscout/Extra/tempmail/temp_mail_io.py +304 -292
- webscout/Extra/weather.py +196 -194
- webscout/Extra/weather_ascii.py +17 -15
- webscout/Provider/AISEARCH/PERPLEXED_search.py +175 -0
- webscout/Provider/AISEARCH/Perplexity.py +292 -333
- webscout/Provider/AISEARCH/README.md +106 -279
- webscout/Provider/AISEARCH/__init__.py +16 -9
- webscout/Provider/AISEARCH/brave_search.py +298 -0
- webscout/Provider/AISEARCH/iask_search.py +357 -410
- webscout/Provider/AISEARCH/monica_search.py +200 -220
- webscout/Provider/AISEARCH/webpilotai_search.py +242 -255
- webscout/Provider/Algion.py +413 -0
- webscout/Provider/Andi.py +74 -69
- webscout/Provider/Apriel.py +313 -0
- webscout/Provider/Ayle.py +323 -0
- webscout/Provider/ChatSandbox.py +329 -342
- webscout/Provider/ClaudeOnline.py +365 -0
- webscout/Provider/Cohere.py +232 -208
- webscout/Provider/DeepAI.py +367 -0
- webscout/Provider/Deepinfra.py +467 -340
- webscout/Provider/EssentialAI.py +217 -0
- webscout/Provider/ExaAI.py +274 -261
- webscout/Provider/Gemini.py +175 -169
- webscout/Provider/GithubChat.py +385 -369
- webscout/Provider/Gradient.py +286 -0
- webscout/Provider/Groq.py +556 -801
- webscout/Provider/HadadXYZ.py +323 -0
- webscout/Provider/HeckAI.py +392 -375
- webscout/Provider/HuggingFace.py +387 -0
- webscout/Provider/IBM.py +340 -0
- webscout/Provider/Jadve.py +317 -291
- webscout/Provider/K2Think.py +306 -0
- webscout/Provider/Koboldai.py +221 -384
- webscout/Provider/Netwrck.py +273 -270
- webscout/Provider/Nvidia.py +310 -0
- webscout/Provider/OPENAI/DeepAI.py +489 -0
- webscout/Provider/OPENAI/K2Think.py +423 -0
- webscout/Provider/OPENAI/PI.py +463 -0
- webscout/Provider/OPENAI/README.md +890 -952
- webscout/Provider/OPENAI/TogetherAI.py +405 -0
- webscout/Provider/OPENAI/TwoAI.py +255 -357
- webscout/Provider/OPENAI/__init__.py +148 -40
- webscout/Provider/OPENAI/ai4chat.py +348 -293
- webscout/Provider/OPENAI/akashgpt.py +436 -0
- webscout/Provider/OPENAI/algion.py +303 -0
- webscout/Provider/OPENAI/{exachat.py → ayle.py} +365 -444
- webscout/Provider/OPENAI/base.py +253 -249
- webscout/Provider/OPENAI/cerebras.py +296 -0
- webscout/Provider/OPENAI/chatgpt.py +870 -556
- webscout/Provider/OPENAI/chatsandbox.py +233 -173
- webscout/Provider/OPENAI/deepinfra.py +403 -322
- webscout/Provider/OPENAI/e2b.py +2370 -1414
- webscout/Provider/OPENAI/elmo.py +278 -0
- webscout/Provider/OPENAI/exaai.py +452 -417
- webscout/Provider/OPENAI/freeassist.py +446 -0
- webscout/Provider/OPENAI/gradient.py +448 -0
- webscout/Provider/OPENAI/groq.py +380 -364
- webscout/Provider/OPENAI/hadadxyz.py +292 -0
- webscout/Provider/OPENAI/heckai.py +333 -308
- webscout/Provider/OPENAI/huggingface.py +321 -0
- webscout/Provider/OPENAI/ibm.py +425 -0
- webscout/Provider/OPENAI/llmchat.py +253 -0
- webscout/Provider/OPENAI/llmchatco.py +378 -335
- webscout/Provider/OPENAI/meta.py +541 -0
- webscout/Provider/OPENAI/netwrck.py +374 -357
- webscout/Provider/OPENAI/nvidia.py +317 -0
- webscout/Provider/OPENAI/oivscode.py +348 -287
- webscout/Provider/OPENAI/openrouter.py +328 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -172
- webscout/Provider/OPENAI/sambanova.py +397 -0
- webscout/Provider/OPENAI/sonus.py +305 -304
- webscout/Provider/OPENAI/textpollinations.py +370 -339
- webscout/Provider/OPENAI/toolbaz.py +375 -413
- webscout/Provider/OPENAI/typefully.py +419 -355
- webscout/Provider/OPENAI/typliai.py +279 -0
- webscout/Provider/OPENAI/utils.py +314 -318
- webscout/Provider/OPENAI/wisecat.py +359 -387
- webscout/Provider/OPENAI/writecream.py +185 -163
- webscout/Provider/OPENAI/x0gpt.py +462 -365
- webscout/Provider/OPENAI/zenmux.py +380 -0
- webscout/Provider/OpenRouter.py +386 -0
- webscout/Provider/Openai.py +337 -496
- webscout/Provider/PI.py +443 -429
- webscout/Provider/QwenLM.py +346 -254
- webscout/Provider/STT/__init__.py +28 -0
- webscout/Provider/STT/base.py +303 -0
- webscout/Provider/STT/elevenlabs.py +264 -0
- webscout/Provider/Sambanova.py +317 -0
- webscout/Provider/TTI/README.md +69 -82
- webscout/Provider/TTI/__init__.py +37 -7
- webscout/Provider/TTI/base.py +147 -64
- webscout/Provider/TTI/claudeonline.py +393 -0
- webscout/Provider/TTI/magicstudio.py +292 -201
- webscout/Provider/TTI/miragic.py +180 -0
- webscout/Provider/TTI/pollinations.py +331 -221
- webscout/Provider/TTI/together.py +334 -0
- webscout/Provider/TTI/utils.py +14 -11
- webscout/Provider/TTS/README.md +186 -192
- webscout/Provider/TTS/__init__.py +43 -10
- webscout/Provider/TTS/base.py +523 -159
- webscout/Provider/TTS/deepgram.py +286 -156
- webscout/Provider/TTS/elevenlabs.py +189 -111
- webscout/Provider/TTS/freetts.py +218 -0
- webscout/Provider/TTS/murfai.py +288 -113
- webscout/Provider/TTS/openai_fm.py +364 -129
- webscout/Provider/TTS/parler.py +203 -111
- webscout/Provider/TTS/qwen.py +334 -0
- webscout/Provider/TTS/sherpa.py +286 -0
- webscout/Provider/TTS/speechma.py +693 -580
- webscout/Provider/TTS/streamElements.py +275 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TextPollinationsAI.py +331 -308
- webscout/Provider/TogetherAI.py +450 -0
- webscout/Provider/TwoAI.py +309 -475
- webscout/Provider/TypliAI.py +311 -305
- webscout/Provider/UNFINISHED/ChatHub.py +219 -209
- webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +331 -326
- webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +300 -295
- webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +218 -198
- webscout/Provider/UNFINISHED/Qodo.py +481 -0
- webscout/Provider/{MCPCore.py → UNFINISHED/XenAI.py} +330 -315
- webscout/Provider/UNFINISHED/Youchat.py +347 -330
- webscout/Provider/UNFINISHED/aihumanizer.py +41 -0
- webscout/Provider/UNFINISHED/grammerchecker.py +37 -0
- webscout/Provider/UNFINISHED/liner.py +342 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +246 -263
- webscout/Provider/{samurai.py → UNFINISHED/samurai.py} +231 -224
- webscout/Provider/WiseCat.py +256 -233
- webscout/Provider/WrDoChat.py +390 -370
- webscout/Provider/__init__.py +115 -174
- webscout/Provider/ai4chat.py +181 -174
- webscout/Provider/akashgpt.py +330 -335
- webscout/Provider/cerebras.py +397 -290
- webscout/Provider/cleeai.py +236 -213
- webscout/Provider/elmo.py +291 -283
- webscout/Provider/geminiapi.py +343 -208
- webscout/Provider/julius.py +245 -223
- webscout/Provider/learnfastai.py +333 -325
- webscout/Provider/llama3mitril.py +230 -215
- webscout/Provider/llmchat.py +308 -258
- webscout/Provider/llmchatco.py +321 -306
- webscout/Provider/meta.py +996 -801
- webscout/Provider/oivscode.py +332 -309
- webscout/Provider/searchchat.py +316 -292
- webscout/Provider/sonus.py +264 -258
- webscout/Provider/toolbaz.py +359 -353
- webscout/Provider/turboseek.py +332 -266
- webscout/Provider/typefully.py +262 -202
- webscout/Provider/x0gpt.py +332 -299
- webscout/__init__.py +31 -39
- webscout/__main__.py +5 -5
- webscout/cli.py +585 -524
- webscout/client.py +1497 -70
- webscout/conversation.py +140 -436
- webscout/exceptions.py +383 -362
- webscout/litagent/__init__.py +29 -29
- webscout/litagent/agent.py +492 -455
- webscout/litagent/constants.py +60 -60
- webscout/models.py +505 -181
- webscout/optimizers.py +74 -420
- webscout/prompt_manager.py +376 -288
- webscout/sanitize.py +1514 -0
- webscout/scout/README.md +452 -404
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +7 -7
- webscout/scout/core/crawler.py +330 -210
- webscout/scout/core/scout.py +800 -607
- webscout/scout/core/search_result.py +51 -96
- webscout/scout/core/text_analyzer.py +64 -63
- webscout/scout/core/text_utils.py +412 -277
- webscout/scout/core/web_analyzer.py +54 -52
- webscout/scout/element.py +872 -478
- webscout/scout/parsers/__init__.py +70 -69
- webscout/scout/parsers/html5lib_parser.py +182 -172
- webscout/scout/parsers/html_parser.py +238 -236
- webscout/scout/parsers/lxml_parser.py +203 -178
- webscout/scout/utils.py +38 -37
- webscout/search/__init__.py +47 -0
- webscout/search/base.py +201 -0
- webscout/search/bing_main.py +45 -0
- webscout/search/brave_main.py +92 -0
- webscout/search/duckduckgo_main.py +57 -0
- webscout/search/engines/__init__.py +127 -0
- webscout/search/engines/bing/__init__.py +15 -0
- webscout/search/engines/bing/base.py +35 -0
- webscout/search/engines/bing/images.py +114 -0
- webscout/search/engines/bing/news.py +96 -0
- webscout/search/engines/bing/suggestions.py +36 -0
- webscout/search/engines/bing/text.py +109 -0
- webscout/search/engines/brave/__init__.py +19 -0
- webscout/search/engines/brave/base.py +47 -0
- webscout/search/engines/brave/images.py +213 -0
- webscout/search/engines/brave/news.py +353 -0
- webscout/search/engines/brave/suggestions.py +318 -0
- webscout/search/engines/brave/text.py +167 -0
- webscout/search/engines/brave/videos.py +364 -0
- webscout/search/engines/duckduckgo/__init__.py +25 -0
- webscout/search/engines/duckduckgo/answers.py +80 -0
- webscout/search/engines/duckduckgo/base.py +189 -0
- webscout/search/engines/duckduckgo/images.py +100 -0
- webscout/search/engines/duckduckgo/maps.py +183 -0
- webscout/search/engines/duckduckgo/news.py +70 -0
- webscout/search/engines/duckduckgo/suggestions.py +22 -0
- webscout/search/engines/duckduckgo/text.py +221 -0
- webscout/search/engines/duckduckgo/translate.py +48 -0
- webscout/search/engines/duckduckgo/videos.py +80 -0
- webscout/search/engines/duckduckgo/weather.py +84 -0
- webscout/search/engines/mojeek.py +61 -0
- webscout/search/engines/wikipedia.py +77 -0
- webscout/search/engines/yahoo/__init__.py +41 -0
- webscout/search/engines/yahoo/answers.py +19 -0
- webscout/search/engines/yahoo/base.py +34 -0
- webscout/search/engines/yahoo/images.py +323 -0
- webscout/search/engines/yahoo/maps.py +19 -0
- webscout/search/engines/yahoo/news.py +258 -0
- webscout/search/engines/yahoo/suggestions.py +140 -0
- webscout/search/engines/yahoo/text.py +273 -0
- webscout/search/engines/yahoo/translate.py +19 -0
- webscout/search/engines/yahoo/videos.py +302 -0
- webscout/search/engines/yahoo/weather.py +220 -0
- webscout/search/engines/yandex.py +67 -0
- webscout/search/engines/yep/__init__.py +13 -0
- webscout/search/engines/yep/base.py +34 -0
- webscout/search/engines/yep/images.py +101 -0
- webscout/search/engines/yep/suggestions.py +38 -0
- webscout/search/engines/yep/text.py +99 -0
- webscout/search/http_client.py +172 -0
- webscout/search/results.py +141 -0
- webscout/search/yahoo_main.py +57 -0
- webscout/search/yep_main.py +48 -0
- webscout/server/__init__.py +48 -0
- webscout/server/config.py +78 -0
- webscout/server/exceptions.py +69 -0
- webscout/server/providers.py +286 -0
- webscout/server/request_models.py +131 -0
- webscout/server/request_processing.py +404 -0
- webscout/server/routes.py +642 -0
- webscout/server/server.py +351 -0
- webscout/server/ui_templates.py +1171 -0
- webscout/swiftcli/__init__.py +79 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +574 -297
- webscout/swiftcli/core/context.py +98 -104
- webscout/swiftcli/core/group.py +268 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +243 -221
- webscout/swiftcli/decorators/options.py +247 -220
- webscout/swiftcli/decorators/output.py +392 -252
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +134 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +58 -59
- webscout/swiftcli/utils/formatting.py +251 -252
- webscout/swiftcli/utils/parsing.py +368 -267
- webscout/update_checker.py +280 -136
- webscout/utils.py +28 -14
- webscout/version.py +2 -1
- webscout/version.py.bak +3 -0
- webscout/zeroart/__init__.py +218 -135
- webscout/zeroart/base.py +70 -66
- webscout/zeroart/effects.py +155 -101
- webscout/zeroart/fonts.py +1799 -1239
- webscout-2026.1.19.dist-info/METADATA +638 -0
- webscout-2026.1.19.dist-info/RECORD +312 -0
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/entry_points.txt +1 -1
- webscout/DWEBS.py +0 -520
- webscout/Extra/Act.md +0 -309
- webscout/Extra/GitToolkit/gitapi/README.md +0 -110
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/Extra/gguf.md +0 -430
- webscout/Extra/weather.md +0 -281
- webscout/Litlogger/README.md +0 -10
- webscout/Litlogger/__init__.py +0 -15
- webscout/Litlogger/formats.py +0 -4
- webscout/Litlogger/handlers.py +0 -103
- webscout/Litlogger/levels.py +0 -13
- webscout/Litlogger/logger.py +0 -92
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/AISEARCH/felo_search.py +0 -202
- webscout/Provider/AISEARCH/genspark_search.py +0 -324
- webscout/Provider/AISEARCH/hika_search.py +0 -186
- webscout/Provider/AISEARCH/scira_search.py +0 -298
- webscout/Provider/Aitopia.py +0 -316
- webscout/Provider/AllenAI.py +0 -440
- webscout/Provider/Blackboxai.py +0 -791
- webscout/Provider/ChatGPTClone.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Cloudflare.py +0 -324
- webscout/Provider/ExaChat.py +0 -358
- webscout/Provider/Flowith.py +0 -217
- webscout/Provider/FreeGemini.py +0 -250
- webscout/Provider/Glider.py +0 -225
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HuggingFaceChat.py +0 -469
- webscout/Provider/Hunyuan.py +0 -283
- webscout/Provider/LambdaChat.py +0 -411
- webscout/Provider/Llama3.py +0 -259
- webscout/Provider/Nemotron.py +0 -218
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -766
- webscout/Provider/OPENAI/Cloudflare.py +0 -378
- webscout/Provider/OPENAI/FreeGemini.py +0 -283
- webscout/Provider/OPENAI/NEMOTRON.py +0 -232
- webscout/Provider/OPENAI/Qwen3.py +0 -283
- webscout/Provider/OPENAI/api.py +0 -969
- webscout/Provider/OPENAI/c4ai.py +0 -373
- webscout/Provider/OPENAI/chatgptclone.py +0 -494
- webscout/Provider/OPENAI/copilot.py +0 -242
- webscout/Provider/OPENAI/flowith.py +0 -162
- webscout/Provider/OPENAI/freeaichat.py +0 -359
- webscout/Provider/OPENAI/mcpcore.py +0 -389
- webscout/Provider/OPENAI/multichat.py +0 -376
- webscout/Provider/OPENAI/opkfc.py +0 -496
- webscout/Provider/OPENAI/scirachat.py +0 -477
- webscout/Provider/OPENAI/standardinput.py +0 -433
- webscout/Provider/OPENAI/typegpt.py +0 -364
- webscout/Provider/OPENAI/uncovrAI.py +0 -463
- webscout/Provider/OPENAI/venice.py +0 -431
- webscout/Provider/OPENAI/yep.py +0 -382
- webscout/Provider/OpenGPT.py +0 -209
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -290
- webscout/Provider/TTI/aiarta.py +0 -365
- webscout/Provider/TTI/artbit.py +0 -0
- webscout/Provider/TTI/fastflux.py +0 -200
- webscout/Provider/TTI/piclumen.py +0 -203
- webscout/Provider/TTI/pixelmuse.py +0 -225
- webscout/Provider/TTS/gesserit.py +0 -128
- webscout/Provider/TTS/sthir.py +0 -94
- webscout/Provider/TeachAnything.py +0 -229
- webscout/Provider/UNFINISHED/puterjs.py +0 -635
- webscout/Provider/UNFINISHED/test_lmarena.py +0 -119
- webscout/Provider/Venice.py +0 -258
- webscout/Provider/VercelAI.py +0 -253
- webscout/Provider/Writecream.py +0 -246
- webscout/Provider/WritingMate.py +0 -269
- webscout/Provider/asksteve.py +0 -220
- webscout/Provider/chatglm.py +0 -215
- webscout/Provider/copilot.py +0 -425
- webscout/Provider/freeaichat.py +0 -285
- webscout/Provider/granite.py +0 -235
- webscout/Provider/hermes.py +0 -266
- webscout/Provider/koala.py +0 -170
- webscout/Provider/lmarena.py +0 -198
- webscout/Provider/multichat.py +0 -364
- webscout/Provider/scira_chat.py +0 -299
- webscout/Provider/scnet.py +0 -243
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/typegpt.py +0 -289
- webscout/Provider/uncovr.py +0 -368
- webscout/Provider/yep.py +0 -389
- webscout/litagent/Readme.md +0 -276
- webscout/litprinter/__init__.py +0 -59
- webscout/swiftcli/Readme.md +0 -323
- webscout/tempid.py +0 -128
- webscout/webscout_search.py +0 -1184
- webscout/webscout_search_async.py +0 -654
- webscout/yep_search.py +0 -347
- webscout/zeroart/README.md +0 -89
- webscout-8.2.9.dist-info/METADATA +0 -1033
- webscout-8.2.9.dist-info/RECORD +0 -289
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
from typing import Any, Dict, Optional
|
|
2
|
+
from urllib.parse import quote
|
|
3
|
+
|
|
4
|
+
from .utils import request
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class GitSearch:
|
|
8
|
+
"""Class for searching GitHub content without authentication"""
|
|
9
|
+
|
|
10
|
+
BASE_URL = "https://api.github.com/search"
|
|
11
|
+
|
|
12
|
+
def search_repositories(
|
|
13
|
+
self,
|
|
14
|
+
query: str,
|
|
15
|
+
sort: Optional[str] = None,
|
|
16
|
+
order: str = "desc",
|
|
17
|
+
page: int = 1,
|
|
18
|
+
per_page: int = 30
|
|
19
|
+
) -> Dict[str, Any]:
|
|
20
|
+
"""
|
|
21
|
+
Search for repositories.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
query: Search query (e.g., "tetris language:python stars:>100")
|
|
25
|
+
sort: Sort by (stars, forks, help-wanted-issues, updated)
|
|
26
|
+
order: Sort order (asc, desc)
|
|
27
|
+
page: Page number
|
|
28
|
+
per_page: Results per page (max 100)
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Dict with total_count, incomplete_results, and items
|
|
32
|
+
"""
|
|
33
|
+
url = f"{self.BASE_URL}/repositories?q={quote(query)}&page={page}&per_page={per_page}&order={order}"
|
|
34
|
+
if sort:
|
|
35
|
+
url += f"&sort={sort}"
|
|
36
|
+
return request(url)
|
|
37
|
+
|
|
38
|
+
def search_users(
|
|
39
|
+
self,
|
|
40
|
+
query: str,
|
|
41
|
+
sort: Optional[str] = None,
|
|
42
|
+
order: str = "desc",
|
|
43
|
+
page: int = 1,
|
|
44
|
+
per_page: int = 30
|
|
45
|
+
) -> Dict[str, Any]:
|
|
46
|
+
"""
|
|
47
|
+
Search for users.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
query: Search query (e.g., "tom repos:>42 followers:>1000")
|
|
51
|
+
sort: Sort by (followers, repositories, joined)
|
|
52
|
+
order: Sort order (asc, desc)
|
|
53
|
+
page: Page number
|
|
54
|
+
per_page: Results per page (max 100)
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Dict with total_count, incomplete_results, and items
|
|
58
|
+
"""
|
|
59
|
+
url = f"{self.BASE_URL}/users?q={quote(query)}&page={page}&per_page={per_page}&order={order}"
|
|
60
|
+
if sort:
|
|
61
|
+
url += f"&sort={sort}"
|
|
62
|
+
return request(url)
|
|
63
|
+
|
|
64
|
+
def search_topics(
|
|
65
|
+
self,
|
|
66
|
+
query: str,
|
|
67
|
+
page: int = 1,
|
|
68
|
+
per_page: int = 30
|
|
69
|
+
) -> Dict[str, Any]:
|
|
70
|
+
"""
|
|
71
|
+
Search for topics.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
query: Search query
|
|
75
|
+
page: Page number
|
|
76
|
+
per_page: Results per page (max 100)
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Dict with total_count, incomplete_results, and items
|
|
80
|
+
"""
|
|
81
|
+
url = f"{self.BASE_URL}/topics?q={quote(query)}&page={page}&per_page={per_page}"
|
|
82
|
+
return request(url)
|
|
83
|
+
|
|
84
|
+
def search_commits(
|
|
85
|
+
self,
|
|
86
|
+
query: str,
|
|
87
|
+
sort: Optional[str] = None,
|
|
88
|
+
order: str = "desc",
|
|
89
|
+
page: int = 1,
|
|
90
|
+
per_page: int = 30
|
|
91
|
+
) -> Dict[str, Any]:
|
|
92
|
+
"""
|
|
93
|
+
Search for commits.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
query: Search query (e.g., "fix bug repo:owner/repo")
|
|
97
|
+
sort: Sort by (author-date, committer-date)
|
|
98
|
+
order: Sort order (asc, desc)
|
|
99
|
+
page: Page number
|
|
100
|
+
per_page: Results per page (max 100)
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Dict with total_count, incomplete_results, and items
|
|
104
|
+
"""
|
|
105
|
+
url = f"{self.BASE_URL}/commits?q={quote(query)}&page={page}&per_page={per_page}&order={order}"
|
|
106
|
+
if sort:
|
|
107
|
+
url += f"&sort={sort}"
|
|
108
|
+
return request(url)
|
|
109
|
+
|
|
110
|
+
def search_issues(
|
|
111
|
+
self,
|
|
112
|
+
query: str,
|
|
113
|
+
sort: Optional[str] = None,
|
|
114
|
+
order: str = "desc",
|
|
115
|
+
page: int = 1,
|
|
116
|
+
per_page: int = 30
|
|
117
|
+
) -> Dict[str, Any]:
|
|
118
|
+
"""
|
|
119
|
+
Search for issues and pull requests.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
query: Search query (e.g., "bug is:issue is:open label:bug")
|
|
123
|
+
sort: Sort by (comments, reactions, created, updated)
|
|
124
|
+
order: Sort order (asc, desc)
|
|
125
|
+
page: Page number
|
|
126
|
+
per_page: Results per page (max 100)
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Dict with total_count, incomplete_results, and items
|
|
130
|
+
"""
|
|
131
|
+
url = f"{self.BASE_URL}/issues?q={quote(query)}&page={page}&per_page={per_page}&order={order}"
|
|
132
|
+
if sort:
|
|
133
|
+
url += f"&sort={sort}"
|
|
134
|
+
return request(url)
|
|
135
|
+
|
|
136
|
+
def search_labels(
|
|
137
|
+
self,
|
|
138
|
+
repository_id: int,
|
|
139
|
+
query: str,
|
|
140
|
+
sort: Optional[str] = None,
|
|
141
|
+
order: str = "desc",
|
|
142
|
+
page: int = 1,
|
|
143
|
+
per_page: int = 30
|
|
144
|
+
) -> Dict[str, Any]:
|
|
145
|
+
"""
|
|
146
|
+
Search for labels in a repository.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
repository_id: Repository ID to search in
|
|
150
|
+
query: Search query
|
|
151
|
+
sort: Sort by (created, updated)
|
|
152
|
+
order: Sort order (asc, desc)
|
|
153
|
+
page: Page number
|
|
154
|
+
per_page: Results per page (max 100)
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Dict with total_count, incomplete_results, and items
|
|
158
|
+
"""
|
|
159
|
+
url = f"{self.BASE_URL}/labels?repository_id={repository_id}&q={quote(query)}&page={page}&per_page={per_page}&order={order}"
|
|
160
|
+
if sort:
|
|
161
|
+
url += f"&sort={sort}"
|
|
162
|
+
return request(url)
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Any, Dict, List
|
|
3
|
+
from urllib.request import Request, urlopen
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from webscout.litagent.agent import LitAgent
|
|
7
|
+
_USER_AGENT_GENERATOR = LitAgent()
|
|
8
|
+
except ImportError:
|
|
9
|
+
_USER_AGENT_GENERATOR = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Trending:
|
|
13
|
+
"""Class for getting GitHub trending data (scrapes github.com/trending)"""
|
|
14
|
+
|
|
15
|
+
BASE_URL = "https://github.com/trending"
|
|
16
|
+
|
|
17
|
+
def get_repositories(
|
|
18
|
+
self,
|
|
19
|
+
language: str = "",
|
|
20
|
+
since: str = "daily",
|
|
21
|
+
spoken_language: str = ""
|
|
22
|
+
) -> List[Dict[str, Any]]:
|
|
23
|
+
"""
|
|
24
|
+
Get trending repositories.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
language: Programming language filter (e.g., "python", "javascript")
|
|
28
|
+
since: Time range (daily, weekly, monthly)
|
|
29
|
+
spoken_language: Spoken language filter (e.g., "en" for English)
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
List of trending repositories with name, description, stars, forks, etc.
|
|
33
|
+
"""
|
|
34
|
+
url = self.BASE_URL
|
|
35
|
+
if language:
|
|
36
|
+
url += f"/{language}"
|
|
37
|
+
url += f"?since={since}"
|
|
38
|
+
if spoken_language:
|
|
39
|
+
url += f"&spoken_language_code={spoken_language}"
|
|
40
|
+
|
|
41
|
+
html = self._fetch_html(url)
|
|
42
|
+
return self._parse_repos(html)
|
|
43
|
+
|
|
44
|
+
def get_developers(
|
|
45
|
+
self,
|
|
46
|
+
language: str = "",
|
|
47
|
+
since: str = "daily"
|
|
48
|
+
) -> List[Dict[str, Any]]:
|
|
49
|
+
"""
|
|
50
|
+
Get trending developers.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
language: Programming language filter
|
|
54
|
+
since: Time range (daily, weekly, monthly)
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
List of trending developers with username, name, avatar, repo
|
|
58
|
+
"""
|
|
59
|
+
url = f"{self.BASE_URL}/developers"
|
|
60
|
+
if language:
|
|
61
|
+
url += f"/{language}"
|
|
62
|
+
url += f"?since={since}"
|
|
63
|
+
|
|
64
|
+
html = self._fetch_html(url)
|
|
65
|
+
return self._parse_developers(html)
|
|
66
|
+
|
|
67
|
+
def _fetch_html(self, url: str) -> str:
|
|
68
|
+
"""Fetch HTML content from URL."""
|
|
69
|
+
headers = {
|
|
70
|
+
"User-Agent": _USER_AGENT_GENERATOR.random() if _USER_AGENT_GENERATOR else "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
71
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
72
|
+
}
|
|
73
|
+
req = Request(url, headers=headers)
|
|
74
|
+
response = urlopen(req, timeout=30)
|
|
75
|
+
return response.read().decode('utf-8')
|
|
76
|
+
|
|
77
|
+
def _parse_repos(self, html: str) -> List[Dict[str, Any]]:
|
|
78
|
+
"""Parse trending repositories from HTML."""
|
|
79
|
+
repos = []
|
|
80
|
+
|
|
81
|
+
# Find all article elements (repo boxes) - try multiple patterns
|
|
82
|
+
repo_patterns = [
|
|
83
|
+
r'<article class="Box-row"[^>]*>(.*?)</article>',
|
|
84
|
+
r'<article[^>]*class="[^"]*Box-row[^"]*"[^>]*>(.*?)</article>',
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
repo_matches = []
|
|
88
|
+
for pattern in repo_patterns:
|
|
89
|
+
repo_matches = re.findall(pattern, html, re.DOTALL)
|
|
90
|
+
if repo_matches:
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
# If no matches with article, try row-based parsing
|
|
94
|
+
if not repo_matches:
|
|
95
|
+
# Try to find repo links directly
|
|
96
|
+
repo_link_pattern = r'<h2[^>]*>\s*<a[^>]*href="/([^"]+)"[^>]*>'
|
|
97
|
+
link_matches = re.findall(repo_link_pattern, html)
|
|
98
|
+
for link in link_matches:
|
|
99
|
+
if '/' in link and not link.startswith('topics/'):
|
|
100
|
+
parts = link.split('/')
|
|
101
|
+
if len(parts) >= 2:
|
|
102
|
+
repos.append({
|
|
103
|
+
'full_name': link,
|
|
104
|
+
'owner': parts[0],
|
|
105
|
+
'name': parts[1],
|
|
106
|
+
'description': '',
|
|
107
|
+
'language': None,
|
|
108
|
+
'stars': 0,
|
|
109
|
+
'forks': 0
|
|
110
|
+
})
|
|
111
|
+
return repos
|
|
112
|
+
|
|
113
|
+
for repo_html in repo_matches:
|
|
114
|
+
repo = {}
|
|
115
|
+
|
|
116
|
+
# Extract repo name (owner/repo) - try multiple patterns
|
|
117
|
+
name_patterns = [
|
|
118
|
+
r'href="/([^"]+)"[^>]*>\s*<span[^>]*>([^<]+)</span>\s*/\s*<span[^>]*>([^<]+)</span>',
|
|
119
|
+
r'href="/([^/]+/[^"]+)"[^>]*class="[^"]*Link[^"]*"',
|
|
120
|
+
r'<h2[^>]*>\s*<a[^>]*href="/([^"]+)"'
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
for pattern in name_patterns:
|
|
124
|
+
name_match = re.search(pattern, repo_html)
|
|
125
|
+
if name_match:
|
|
126
|
+
full_name = name_match.group(1).strip()
|
|
127
|
+
if '/' in full_name:
|
|
128
|
+
parts = full_name.split('/')
|
|
129
|
+
repo['full_name'] = full_name
|
|
130
|
+
repo['owner'] = parts[0].strip()
|
|
131
|
+
repo['name'] = parts[1].strip() if len(parts) > 1 else ''
|
|
132
|
+
break
|
|
133
|
+
|
|
134
|
+
# Extract description - try multiple patterns
|
|
135
|
+
desc_patterns = [
|
|
136
|
+
r'<p class="[^"]*col-9[^"]*"[^>]*>([^<]+)</p>',
|
|
137
|
+
r'<p class="[^"]*mb-1[^"]*"[^>]*>([^<]+)</p>',
|
|
138
|
+
r'<p[^>]*class="[^"]*text-gray[^"]*"[^>]*>([^<]+)</p>'
|
|
139
|
+
]
|
|
140
|
+
for pattern in desc_patterns:
|
|
141
|
+
desc_match = re.search(pattern, repo_html)
|
|
142
|
+
if desc_match:
|
|
143
|
+
repo['description'] = desc_match.group(1).strip()
|
|
144
|
+
break
|
|
145
|
+
else:
|
|
146
|
+
repo['description'] = ""
|
|
147
|
+
|
|
148
|
+
# Extract language
|
|
149
|
+
lang_patterns = [
|
|
150
|
+
r'<span itemprop="programmingLanguage">([^<]+)</span>',
|
|
151
|
+
r'<span[^>]*>([A-Z][a-z]+(?:\+\+|#)?)</span>\s*</span>'
|
|
152
|
+
]
|
|
153
|
+
for pattern in lang_patterns:
|
|
154
|
+
lang_match = re.search(pattern, repo_html)
|
|
155
|
+
if lang_match:
|
|
156
|
+
repo['language'] = lang_match.group(1).strip()
|
|
157
|
+
break
|
|
158
|
+
else:
|
|
159
|
+
repo['language'] = None
|
|
160
|
+
|
|
161
|
+
# Extract stars - multiple patterns
|
|
162
|
+
stars_patterns = [
|
|
163
|
+
r'href="/[^/]+/[^/]+/stargazers"[^>]*>\s*(?:<svg[^>]*>.*?</svg>)?\s*([\d,]+)',
|
|
164
|
+
r'>\s*([\d,]+)\s*</a>\s*</span>.*?stargazers',
|
|
165
|
+
r'([\d,]+)\s*stars?'
|
|
166
|
+
]
|
|
167
|
+
for pattern in stars_patterns:
|
|
168
|
+
stars_match = re.search(pattern, repo_html, re.DOTALL)
|
|
169
|
+
if stars_match:
|
|
170
|
+
repo['stars'] = int(stars_match.group(1).replace(',', ''))
|
|
171
|
+
break
|
|
172
|
+
else:
|
|
173
|
+
repo['stars'] = 0
|
|
174
|
+
|
|
175
|
+
# Extract forks
|
|
176
|
+
forks_patterns = [
|
|
177
|
+
r'href="/[^/]+/[^/]+/forks"[^>]*>\s*(?:<svg[^>]*>.*?</svg>)?\s*([\d,]+)',
|
|
178
|
+
r'([\d,]+)\s*forks?'
|
|
179
|
+
]
|
|
180
|
+
for pattern in forks_patterns:
|
|
181
|
+
forks_match = re.search(pattern, repo_html, re.DOTALL)
|
|
182
|
+
if forks_match:
|
|
183
|
+
repo['forks'] = int(forks_match.group(1).replace(',', ''))
|
|
184
|
+
break
|
|
185
|
+
else:
|
|
186
|
+
repo['forks'] = 0
|
|
187
|
+
|
|
188
|
+
# Extract stars today/this week/this month
|
|
189
|
+
today_match = re.search(r'([\d,]+)\s+stars?\s+(today|this week|this month)', repo_html)
|
|
190
|
+
if today_match:
|
|
191
|
+
repo['stars_period'] = int(today_match.group(1).replace(',', ''))
|
|
192
|
+
repo['period'] = today_match.group(2)
|
|
193
|
+
|
|
194
|
+
if repo.get('full_name'):
|
|
195
|
+
repos.append(repo)
|
|
196
|
+
|
|
197
|
+
return repos
|
|
198
|
+
|
|
199
|
+
def _parse_developers(self, html: str) -> List[Dict[str, Any]]:
|
|
200
|
+
"""Parse trending developers from HTML."""
|
|
201
|
+
developers = []
|
|
202
|
+
|
|
203
|
+
# Find all article elements (developer boxes)
|
|
204
|
+
dev_pattern = r'<article class="Box-row[^"]*"[^>]*>(.*?)</article>'
|
|
205
|
+
dev_matches = re.findall(dev_pattern, html, re.DOTALL)
|
|
206
|
+
|
|
207
|
+
for dev_html in dev_matches:
|
|
208
|
+
dev = {}
|
|
209
|
+
|
|
210
|
+
# Extract username
|
|
211
|
+
username_match = re.search(r'href="/([^"?]+)"[^>]*class="[^"]*Link[^"]*"', dev_html)
|
|
212
|
+
if username_match:
|
|
213
|
+
dev['username'] = username_match.group(1).strip()
|
|
214
|
+
|
|
215
|
+
# Extract display name
|
|
216
|
+
name_match = re.search(r'<h1 class="[^"]*"[^>]*>\s*<a[^>]*>([^<]+)</a>', dev_html)
|
|
217
|
+
if name_match:
|
|
218
|
+
dev['name'] = name_match.group(1).strip()
|
|
219
|
+
|
|
220
|
+
# Extract avatar
|
|
221
|
+
avatar_match = re.search(r'<img[^>]*class="[^"]*avatar[^"]*"[^>]*src="([^"]+)"', dev_html)
|
|
222
|
+
if avatar_match:
|
|
223
|
+
dev['avatar'] = avatar_match.group(1)
|
|
224
|
+
|
|
225
|
+
# Extract popular repo
|
|
226
|
+
repo_match = re.search(r'<span class="[^"]*css-truncate-target[^"]*"[^>]*>\s*<a href="/([^"]+)"[^>]*>([^<]+)</a>', dev_html)
|
|
227
|
+
if repo_match:
|
|
228
|
+
dev['popular_repo'] = {
|
|
229
|
+
'full_name': repo_match.group(1),
|
|
230
|
+
'name': repo_match.group(2).strip()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if dev.get('username'):
|
|
234
|
+
developers.append(dev)
|
|
235
|
+
|
|
236
|
+
return developers
|
|
@@ -1,96 +1,128 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
""
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from .utils import request
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class User:
|
|
7
|
+
"""Class for interacting with GitHub user data"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, username: str):
|
|
10
|
+
"""
|
|
11
|
+
Initialize user client
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
username: GitHub username
|
|
15
|
+
"""
|
|
16
|
+
if not username:
|
|
17
|
+
raise ValueError("Username is required")
|
|
18
|
+
if not isinstance(username, str):
|
|
19
|
+
raise ValueError("Username must be a string")
|
|
20
|
+
|
|
21
|
+
self.username = username.strip()
|
|
22
|
+
self.base_url = f"https://api.github.com/users/{self.username}"
|
|
23
|
+
|
|
24
|
+
def get_profile(self) -> Dict[str, Any]:
|
|
25
|
+
"""Get user profile information"""
|
|
26
|
+
return request(self.base_url)
|
|
27
|
+
|
|
28
|
+
def get_repositories(self, page: int = 1, per_page: int = 30, repo_type: str = "all") -> List[Dict[str, Any]]:
|
|
29
|
+
"""
|
|
30
|
+
Get user's public repositories
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
page: Page number
|
|
34
|
+
per_page: Items per page
|
|
35
|
+
repo_type: Type of repositories (all/owner/member)
|
|
36
|
+
"""
|
|
37
|
+
url = f"{self.base_url}/repos?page={page}&per_page={per_page}&type={repo_type}"
|
|
38
|
+
return request(url)
|
|
39
|
+
|
|
40
|
+
def get_starred(self, page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
41
|
+
"""Get repositories starred by user"""
|
|
42
|
+
url = f"{self.base_url}/starred?page={page}&per_page={per_page}"
|
|
43
|
+
return request(url)
|
|
44
|
+
|
|
45
|
+
def get_followers(self, page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
46
|
+
"""Get user's followers"""
|
|
47
|
+
url = f"{self.base_url}/followers?page={page}&per_page={per_page}"
|
|
48
|
+
return request(url)
|
|
49
|
+
|
|
50
|
+
def get_following(self, page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
51
|
+
"""Get users followed by this user"""
|
|
52
|
+
url = f"{self.base_url}/following?page={page}&per_page={per_page}"
|
|
53
|
+
return request(url)
|
|
54
|
+
|
|
55
|
+
def get_gists(self, page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
56
|
+
"""Get user's public gists"""
|
|
57
|
+
url = f"{self.base_url}/gists?page={page}&per_page={per_page}"
|
|
58
|
+
return request(url)
|
|
59
|
+
|
|
60
|
+
def get_organizations(self) -> List[Dict[str, Any]]:
|
|
61
|
+
"""Get user's organizations"""
|
|
62
|
+
url = f"{self.base_url}/orgs"
|
|
63
|
+
return request(url)
|
|
64
|
+
|
|
65
|
+
def get_received_events(self, page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
66
|
+
"""Get events received by user"""
|
|
67
|
+
url = f"{self.base_url}/received_events?page={page}&per_page={per_page}"
|
|
68
|
+
return request(url)
|
|
69
|
+
|
|
70
|
+
def get_public_events(self, page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
71
|
+
"""Get user's public events"""
|
|
72
|
+
url = f"{self.base_url}/events/public?page={page}&per_page={per_page}"
|
|
73
|
+
return request(url)
|
|
74
|
+
|
|
75
|
+
def get_starred_gists(self) -> List[Dict[str, Any]]:
|
|
76
|
+
"""Get gists starred by user"""
|
|
77
|
+
url = f"{self.base_url}/starred_gists"
|
|
78
|
+
return request(url)
|
|
79
|
+
|
|
80
|
+
def get_subscriptions(self) -> List[Dict[str, Any]]:
|
|
81
|
+
"""Get repositories user is watching"""
|
|
82
|
+
url = f"{self.base_url}/subscriptions"
|
|
83
|
+
return request(url)
|
|
84
|
+
|
|
85
|
+
def get_hovercard(self) -> Dict[str, Any]:
|
|
86
|
+
"""Get user's hovercard information"""
|
|
87
|
+
url = f"{self.base_url}/hovercard"
|
|
88
|
+
return request(url)
|
|
89
|
+
|
|
90
|
+
def get_installation(self) -> Dict[str, Any]:
|
|
91
|
+
"""Get user's GitHub App installations"""
|
|
92
|
+
url = f"{self.base_url}/installation"
|
|
93
|
+
return request(url)
|
|
94
|
+
|
|
95
|
+
def get_keys(self) -> List[Dict[str, Any]]:
|
|
96
|
+
"""Get user's public SSH keys"""
|
|
97
|
+
url = f"{self.base_url}/keys"
|
|
98
|
+
return request(url)
|
|
99
|
+
|
|
100
|
+
def get_gpg_keys(self) -> List[Dict[str, Any]]:
|
|
101
|
+
"""Get user's public GPG keys"""
|
|
102
|
+
url = f"{self.base_url}/gpg_keys"
|
|
103
|
+
return request(url)
|
|
104
|
+
|
|
105
|
+
def get_social_accounts(self) -> List[Dict[str, Any]]:
|
|
106
|
+
"""
|
|
107
|
+
Get user's social accounts.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
List of social accounts with provider and url
|
|
111
|
+
"""
|
|
112
|
+
url = f"{self.base_url}/social_accounts"
|
|
113
|
+
return request(url)
|
|
114
|
+
|
|
115
|
+
def get_packages(self, package_type: str = "container", page: int = 1, per_page: int = 30) -> List[Dict[str, Any]]:
|
|
116
|
+
"""
|
|
117
|
+
Get user's public packages.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
package_type: Type of package (container, npm, maven, rubygems, nuget, docker)
|
|
121
|
+
page: Page number
|
|
122
|
+
per_page: Results per page (max 100)
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
List of user's packages
|
|
126
|
+
"""
|
|
127
|
+
url = f"{self.base_url}/packages?package_type={package_type}&page={page}&per_page={per_page}"
|
|
128
|
+
return request(url)
|