fleet-framework 0.3.2__tar.gz → 1.1.0__tar.gz
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.
- fleet_framework-1.1.0/PKG-INFO +116 -0
- fleet_framework-1.1.0/README.md +70 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/pyproject.toml +11 -1
- fleet_framework-1.1.0/src/fleet/cli.py +1088 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/backend.py +94 -17
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/browser.py +124 -101
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/config.py +10 -1
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/context.py +16 -3
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/contract.py +1 -2
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/local_runner.py +2 -25
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/logging.py +2 -12
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/memory_backend.py +29 -8
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/otel.py +1 -22
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/protocol.py +1 -5
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/sqlite_backend.py +90 -15
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/store.py +17 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/api.py +95 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/app.py +63 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/auth.py +3 -15
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/dashboard/router.py +1 -1
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/metrics_route.py +0 -6
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/ratelimit.py +0 -7
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/worker/agent.py +5 -1
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/worker/reconcile_loop.py +80 -9
- fleet_framework-1.1.0/src/fleet/worker/slot_runner.py +422 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/__init__.py +22 -1
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/browser.py +109 -82
- fleet_framework-1.1.0/src/fleet_browser/cloak.py +61 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/display.py +3 -33
- fleet_framework-1.1.0/src/fleet_browser/fingerprint.py +233 -0
- fleet_framework-1.1.0/src/fleet_browser/human/__init__.py +83 -0
- fleet_framework-1.1.0/src/fleet_browser/human/actions.py +331 -0
- fleet_framework-1.1.0/src/fleet_browser/human/distractors.py +68 -0
- fleet_framework-1.1.0/src/fleet_browser/human/engines/__init__.py +25 -0
- fleet_framework-1.1.0/src/fleet_browser/human/journey.py +232 -0
- fleet_framework-1.1.0/src/fleet_browser/human/motion.py +231 -0
- fleet_framework-1.1.0/src/fleet_browser/human/personality.py +79 -0
- fleet_framework-1.1.0/src/fleet_browser/human/timing.py +37 -0
- fleet_framework-1.1.0/src/fleet_browser/local_host.py +432 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/pool.py +7 -81
- fleet_framework-1.1.0/src/fleet_browser/profile.py +328 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/proxy_extension.py +0 -12
- fleet_framework-1.1.0/src/fleet_browser/smart_router.py +496 -0
- fleet_framework-1.1.0/src/fleet_browser/smart_router_addon.py +393 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/solver.py +1 -14
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/stealth.py +3 -17
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_cloudflare/bypasser.py +6 -2
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_cloudflare/harvest.py +74 -15
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_cloudflare/replay.py +2 -20
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_cloudflare/solver.py +0 -5
- fleet_framework-1.1.0/src/fleet_content/__init__.py +14 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_content/automation.py +2 -17
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_content/contracts.py +6 -12
- fleet_framework-1.1.0/src/fleet_detect/__init__.py +16 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_detect/contracts.py +1 -13
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_detect/detect.py +1 -6
- fleet_framework-1.1.0/src/fleet_framework.egg-info/PKG-INFO +116 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_framework.egg-info/SOURCES.txt +31 -1
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_framework.egg-info/entry_points.txt +2 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_framework.egg-info/requires.txt +4 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_framework.egg-info/top_level.txt +2 -0
- fleet_framework-1.1.0/src/fleet_headers/__init__.py +16 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_headers/profiles.py +2 -13
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_jobs/__init__.py +0 -1
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_jobs/automation.py +1 -9
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_marketplace/__init__.py +0 -8
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_marketplace/automation.py +1 -5
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_marketplace/contracts.py +10 -19
- fleet_framework-1.1.0/src/fleet_news/__init__.py +15 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_news/automation.py +2 -20
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_place/__init__.py +0 -6
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_place/automation.py +2 -10
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_place/contracts.py +1 -4
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_provider_evomi/__init__.py +2 -4
- fleet_framework-1.1.0/src/fleet_provider_flameproxies/__init__.py +93 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_serp/__init__.py +0 -7
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_serp/automation.py +2 -16
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_social/__init__.py +0 -7
- fleet_framework-1.1.0/src/fleet_social/automation.py +27 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_social/contracts.py +13 -15
- fleet_framework-1.1.0/src/fleet_storefront/__init__.py +16 -0
- fleet_framework-1.1.0/src/fleet_storefront/app.py +112 -0
- fleet_framework-1.1.0/src/fleet_storefront/auth.py +80 -0
- fleet_framework-1.1.0/src/fleet_storefront/billing/__init__.py +15 -0
- fleet_framework-1.1.0/src/fleet_storefront/billing/apify_credit.py +124 -0
- fleet_framework-1.1.0/src/fleet_storefront/billing/base.py +59 -0
- fleet_framework-1.1.0/src/fleet_storefront/billing/memory.py +73 -0
- fleet_framework-1.1.0/src/fleet_storefront/catalog.py +59 -0
- fleet_framework-1.1.0/src/fleet_storefront/models.py +114 -0
- fleet_framework-1.1.0/src/fleet_storefront/routes/__init__.py +4 -0
- fleet_framework-1.1.0/src/fleet_storefront/routes/admin.py +197 -0
- fleet_framework-1.1.0/src/fleet_storefront/routes/dashboard.py +21 -0
- fleet_framework-1.1.0/src/fleet_storefront/routes/public.py +156 -0
- fleet_framework-1.1.0/src/fleet_storefront/store/__init__.py +4 -0
- fleet_framework-1.1.0/src/fleet_storefront/store/base.py +62 -0
- fleet_framework-1.1.0/src/fleet_storefront/store/sqlite.py +398 -0
- fleet_framework-1.1.0/src/fleet_storefront/templates/dashboard.html +300 -0
- fleet_framework-1.1.0/src/fleet_storefront/waiter.py +45 -0
- fleet_framework-0.3.2/PKG-INFO +0 -166
- fleet_framework-0.3.2/README.md +0 -124
- fleet_framework-0.3.2/src/fleet/cli.py +0 -518
- fleet_framework-0.3.2/src/fleet/worker/slot_runner.py +0 -268
- fleet_framework-0.3.2/src/fleet_browser/cloak.py +0 -120
- fleet_framework-0.3.2/src/fleet_browser/fingerprint.py +0 -332
- fleet_framework-0.3.2/src/fleet_browser/smart_router.py +0 -830
- fleet_framework-0.3.2/src/fleet_content/__init__.py +0 -24
- fleet_framework-0.3.2/src/fleet_detect/__init__.py +0 -26
- fleet_framework-0.3.2/src/fleet_framework.egg-info/PKG-INFO +0 -166
- fleet_framework-0.3.2/src/fleet_headers/__init__.py +0 -28
- fleet_framework-0.3.2/src/fleet_news/__init__.py +0 -21
- fleet_framework-0.3.2/src/fleet_social/automation.py +0 -44
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/LICENSE +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/setup.cfg +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/automation.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/country_presets.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/events.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/metrics.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/primitives.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/proxy.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/core/reconcile.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/broadcaster.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/dashboard/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/dashboard/static/style.css +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/dashboard/templates/index.html +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/master/ws_router.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/worker/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet/worker/ws_client.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_browser/cert.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_cloudflare/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_framework.egg-info/dependency_links.txt +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_jobs/contracts.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_news/contracts.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_provider_dataimpulse/__init__.py +0 -0
- {fleet_framework-0.3.2 → fleet_framework-1.1.0}/src/fleet_serp/contracts.py +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fleet-framework
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: generic distributed-automation framework — master/worker, browser pool, anti-bot helpers, and abstract automation contracts (SERP, content, news, place, marketplace, jobs, social)
|
|
5
|
+
Author: Sarper AVCI
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sarperavci/fleet
|
|
8
|
+
Project-URL: Repository, https://github.com/sarperavci/fleet
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: fastapi>=0.115.0
|
|
13
|
+
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
14
|
+
Requires-Dist: pydantic>=2.7.0
|
|
15
|
+
Requires-Dist: websockets>=12.0
|
|
16
|
+
Requires-Dist: httpx>=0.27.0
|
|
17
|
+
Requires-Dist: redis>=5.0.0
|
|
18
|
+
Requires-Dist: jinja2>=3.1.0
|
|
19
|
+
Requires-Dist: psutil>=5.9.0
|
|
20
|
+
Requires-Dist: click>=8.1.0
|
|
21
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
22
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
23
|
+
Requires-Dist: lxml>=5.1.0
|
|
24
|
+
Requires-Dist: cryptography>=42.0.0
|
|
25
|
+
Provides-Extra: browser
|
|
26
|
+
Requires-Dist: cloakbrowser>=0.3; extra == "browser"
|
|
27
|
+
Requires-Dist: cryptography>=42.0.0; extra == "browser"
|
|
28
|
+
Requires-Dist: mitmproxy>=11.0; extra == "browser"
|
|
29
|
+
Requires-Dist: curl_cffi>=0.7; extra == "browser"
|
|
30
|
+
Requires-Dist: pyvirtualdisplay>=3.0; extra == "browser"
|
|
31
|
+
Requires-Dist: uaforger>=0.1.5; extra == "browser"
|
|
32
|
+
Provides-Extra: cloudflare
|
|
33
|
+
Requires-Dist: fleet-framework[browser]; extra == "cloudflare"
|
|
34
|
+
Provides-Extra: cloak
|
|
35
|
+
Requires-Dist: fleet-framework[browser]; extra == "cloak"
|
|
36
|
+
Provides-Extra: otel
|
|
37
|
+
Requires-Dist: opentelemetry-api>=1.27.0; extra == "otel"
|
|
38
|
+
Requires-Dist: opentelemetry-sdk>=1.27.0; extra == "otel"
|
|
39
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27.0; extra == "otel"
|
|
40
|
+
Provides-Extra: test
|
|
41
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
42
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "test"
|
|
43
|
+
Provides-Extra: all
|
|
44
|
+
Requires-Dist: fleet-framework[browser,cloak,cloudflare,otel]; extra == "all"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
# Fleet
|
|
48
|
+
|
|
49
|
+
A framework for running Python automations across a fleet of machines. You write the automation once; Fleet hands it out to your workers, keeps them running, restarts the ones that fall over, and ships their output where you want it to go.
|
|
50
|
+
|
|
51
|
+
One process, the master, runs on one host. Many workers, one per machine, do the actual work. Output from one workload can feed another across hosts; you don't write the plumbing.
|
|
52
|
+
|
|
53
|
+
Battle-tested in the wild as the brains behind a Cloudflare Turnstile-solving farm.
|
|
54
|
+
|
|
55
|
+
## What it is
|
|
56
|
+
|
|
57
|
+
Fleet is two pieces: a master and some workers.
|
|
58
|
+
|
|
59
|
+
The master runs on one machine. It's where you set what to do and read what got done. Workers run on every other machine in your fleet. They check in with the master, get instructions, and do the work.
|
|
60
|
+
|
|
61
|
+
The work itself is a small Python class you write. Ship it as a pip package, install it on the machines, and Fleet finds it on its own.
|
|
62
|
+
|
|
63
|
+
## What's in the box
|
|
64
|
+
|
|
65
|
+
- One master, many workers. Change config in one place, every worker follows.
|
|
66
|
+
- Workers heal themselves. A crashed task is restarted on the next tick.
|
|
67
|
+
- Workloads hand output to each other across machines, no glue code.
|
|
68
|
+
- Optional Chromium pool for anything that needs a real browser.
|
|
69
|
+
- Auth, a small dashboard, and observability hooks. All wired up.
|
|
70
|
+
|
|
71
|
+
## Getting started
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install fleet-framework
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Then write your automation as a Python class. Roughly 30 lines:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import asyncio
|
|
81
|
+
import httpx
|
|
82
|
+
from fleet.core import BaseConfig, ContinuousAutomation, register
|
|
83
|
+
|
|
84
|
+
class PingerConfig(BaseConfig):
|
|
85
|
+
url: str
|
|
86
|
+
interval_seconds: float = 5.0
|
|
87
|
+
|
|
88
|
+
@register("pinger")
|
|
89
|
+
class Pinger(ContinuousAutomation[PingerConfig]):
|
|
90
|
+
Config = PingerConfig
|
|
91
|
+
|
|
92
|
+
async def run_slot(self, ctx):
|
|
93
|
+
async with httpx.AsyncClient(proxy=ctx.proxy) as client:
|
|
94
|
+
while not ctx.shutdown.is_set():
|
|
95
|
+
r = await client.get(ctx.config.url)
|
|
96
|
+
await ctx.emit({"status": r.status_code})
|
|
97
|
+
await asyncio.sleep(ctx.config.interval_seconds)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Full walkthrough — master, worker, config, output — at <http://fleet.hackmap.win/getting-started/quickstart>.
|
|
101
|
+
|
|
102
|
+
## Documentation
|
|
103
|
+
|
|
104
|
+
Full docs live at **<http://fleet.hackmap.win/>**.
|
|
105
|
+
|
|
106
|
+
- [Introduction](http://fleet.hackmap.win/)
|
|
107
|
+
- [Installation](http://fleet.hackmap.win/getting-started/installation) · [Quickstart](http://fleet.hackmap.win/getting-started/quickstart) · [Your first automation](http://fleet.hackmap.win/getting-started/first-automation)
|
|
108
|
+
- [Architecture](http://fleet.hackmap.win/concepts/architecture) · [Automations](http://fleet.hackmap.win/concepts/automations) · [Primitives](http://fleet.hackmap.win/concepts/primitives)
|
|
109
|
+
- [Continuous automations](http://fleet.hackmap.win/guides/continuous-automation) · [Batch automations](http://fleet.hackmap.win/guides/batch-automation) · [Inter-automation comms](http://fleet.hackmap.win/guides/inter-automation)
|
|
110
|
+
- [Browser-based automations](http://fleet.hackmap.win/guides/browser-automations) · [Deployment](http://fleet.hackmap.win/guides/deployment)
|
|
111
|
+
- [REST API](http://fleet.hackmap.win/reference/rest-api) · [WebSocket protocol](http://fleet.hackmap.win/reference/ws-protocol) · [CLI](http://fleet.hackmap.win/reference/cli)
|
|
112
|
+
- [Auth](http://fleet.hackmap.win/operations/auth) · [Observability](http://fleet.hackmap.win/operations/observability) · [Troubleshooting](http://fleet.hackmap.win/operations/troubleshooting)
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Fleet
|
|
2
|
+
|
|
3
|
+
A framework for running Python automations across a fleet of machines. You write the automation once; Fleet hands it out to your workers, keeps them running, restarts the ones that fall over, and ships their output where you want it to go.
|
|
4
|
+
|
|
5
|
+
One process, the master, runs on one host. Many workers, one per machine, do the actual work. Output from one workload can feed another across hosts; you don't write the plumbing.
|
|
6
|
+
|
|
7
|
+
Battle-tested in the wild as the brains behind a Cloudflare Turnstile-solving farm.
|
|
8
|
+
|
|
9
|
+
## What it is
|
|
10
|
+
|
|
11
|
+
Fleet is two pieces: a master and some workers.
|
|
12
|
+
|
|
13
|
+
The master runs on one machine. It's where you set what to do and read what got done. Workers run on every other machine in your fleet. They check in with the master, get instructions, and do the work.
|
|
14
|
+
|
|
15
|
+
The work itself is a small Python class you write. Ship it as a pip package, install it on the machines, and Fleet finds it on its own.
|
|
16
|
+
|
|
17
|
+
## What's in the box
|
|
18
|
+
|
|
19
|
+
- One master, many workers. Change config in one place, every worker follows.
|
|
20
|
+
- Workers heal themselves. A crashed task is restarted on the next tick.
|
|
21
|
+
- Workloads hand output to each other across machines, no glue code.
|
|
22
|
+
- Optional Chromium pool for anything that needs a real browser.
|
|
23
|
+
- Auth, a small dashboard, and observability hooks. All wired up.
|
|
24
|
+
|
|
25
|
+
## Getting started
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install fleet-framework
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then write your automation as a Python class. Roughly 30 lines:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import asyncio
|
|
35
|
+
import httpx
|
|
36
|
+
from fleet.core import BaseConfig, ContinuousAutomation, register
|
|
37
|
+
|
|
38
|
+
class PingerConfig(BaseConfig):
|
|
39
|
+
url: str
|
|
40
|
+
interval_seconds: float = 5.0
|
|
41
|
+
|
|
42
|
+
@register("pinger")
|
|
43
|
+
class Pinger(ContinuousAutomation[PingerConfig]):
|
|
44
|
+
Config = PingerConfig
|
|
45
|
+
|
|
46
|
+
async def run_slot(self, ctx):
|
|
47
|
+
async with httpx.AsyncClient(proxy=ctx.proxy) as client:
|
|
48
|
+
while not ctx.shutdown.is_set():
|
|
49
|
+
r = await client.get(ctx.config.url)
|
|
50
|
+
await ctx.emit({"status": r.status_code})
|
|
51
|
+
await asyncio.sleep(ctx.config.interval_seconds)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Full walkthrough — master, worker, config, output — at <http://fleet.hackmap.win/getting-started/quickstart>.
|
|
55
|
+
|
|
56
|
+
## Documentation
|
|
57
|
+
|
|
58
|
+
Full docs live at **<http://fleet.hackmap.win/>**.
|
|
59
|
+
|
|
60
|
+
- [Introduction](http://fleet.hackmap.win/)
|
|
61
|
+
- [Installation](http://fleet.hackmap.win/getting-started/installation) · [Quickstart](http://fleet.hackmap.win/getting-started/quickstart) · [Your first automation](http://fleet.hackmap.win/getting-started/first-automation)
|
|
62
|
+
- [Architecture](http://fleet.hackmap.win/concepts/architecture) · [Automations](http://fleet.hackmap.win/concepts/automations) · [Primitives](http://fleet.hackmap.win/concepts/primitives)
|
|
63
|
+
- [Continuous automations](http://fleet.hackmap.win/guides/continuous-automation) · [Batch automations](http://fleet.hackmap.win/guides/batch-automation) · [Inter-automation comms](http://fleet.hackmap.win/guides/inter-automation)
|
|
64
|
+
- [Browser-based automations](http://fleet.hackmap.win/guides/browser-automations) · [Deployment](http://fleet.hackmap.win/guides/deployment)
|
|
65
|
+
- [REST API](http://fleet.hackmap.win/reference/rest-api) · [WebSocket protocol](http://fleet.hackmap.win/reference/ws-protocol) · [CLI](http://fleet.hackmap.win/reference/cli)
|
|
66
|
+
- [Auth](http://fleet.hackmap.win/operations/auth) · [Observability](http://fleet.hackmap.win/operations/observability) · [Troubleshooting](http://fleet.hackmap.win/operations/troubleshooting)
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fleet-framework"
|
|
7
|
-
version = "
|
|
7
|
+
version = "1.1.0"
|
|
8
8
|
description = "generic distributed-automation framework — master/worker, browser pool, anti-bot helpers, and abstract automation contracts (SERP, content, news, place, marketplace, jobs, social)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -27,6 +27,9 @@ dependencies = [
|
|
|
27
27
|
# "AttributeError: 'build_ext' object has no attribute 'cython_sources'".
|
|
28
28
|
# Anchoring at 6.0.2 stops the walk before it gets there.
|
|
29
29
|
"pyyaml>=6.0.2",
|
|
30
|
+
"beautifulsoup4>=4.12.0",
|
|
31
|
+
"lxml>=5.1.0",
|
|
32
|
+
"cryptography>=42.0.0",
|
|
30
33
|
]
|
|
31
34
|
|
|
32
35
|
[project.optional-dependencies]
|
|
@@ -50,6 +53,10 @@ browser = [
|
|
|
50
53
|
# hand. Headed-on-Xvfb beats stock headless for anti-bot fingerprint
|
|
51
54
|
# stability; pyvirtualdisplay shells out to /usr/bin/Xvfb under the hood.
|
|
52
55
|
"pyvirtualdisplay>=3.0",
|
|
56
|
+
# Statistically-weighted UA + Sec-CH-UA generator (real market-share
|
|
57
|
+
# data). Package name on PyPI is `uaforger`; it installs the `uaforge`
|
|
58
|
+
# module. Older PyPI `uaforge` is an unrelated abandoned project.
|
|
59
|
+
"uaforger>=0.1.5",
|
|
53
60
|
]
|
|
54
61
|
cloudflare = [
|
|
55
62
|
"fleet-framework[browser]",
|
|
@@ -74,6 +81,7 @@ all = [
|
|
|
74
81
|
|
|
75
82
|
[project.scripts]
|
|
76
83
|
fleet = "fleet.cli:cli"
|
|
84
|
+
fleet-serp-plus-scheduler = "fleet_serp_plus.scheduler_cli:main"
|
|
77
85
|
|
|
78
86
|
[project.entry-points."fleet.solvers"]
|
|
79
87
|
cloudflare = "fleet_cloudflare:CloudflareSolver"
|
|
@@ -81,6 +89,7 @@ cloudflare = "fleet_cloudflare:CloudflareSolver"
|
|
|
81
89
|
[project.entry-points."fleet.providers.proxy"]
|
|
82
90
|
dataimpulse = "fleet_provider_dataimpulse:DataimpulseProvider"
|
|
83
91
|
evomi = "fleet_provider_evomi:EvomiProvider"
|
|
92
|
+
flameproxies = "fleet_provider_flameproxies:FlameproxiesProvider"
|
|
84
93
|
|
|
85
94
|
[project.urls]
|
|
86
95
|
Homepage = "https://github.com/sarperavci/fleet"
|
|
@@ -92,6 +101,7 @@ include = ["fleet*"]
|
|
|
92
101
|
|
|
93
102
|
[tool.setuptools.package-data]
|
|
94
103
|
"fleet.master.dashboard" = ["templates/**/*", "static/**/*"]
|
|
104
|
+
"fleet_storefront" = ["templates/**/*"]
|
|
95
105
|
|
|
96
106
|
[tool.ruff]
|
|
97
107
|
line-length = 100
|