mirror of
https://github.com/ThePhaseless/Byparr.git
synced 2025-03-15 09:50:20 +08:00
kill old processes
This commit is contained in:
parent
36f8262ad7
commit
709c9b6ef6
17
README.md
17
README.md
@ -2,10 +2,13 @@
|
||||
|
||||
An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) as a drop-in replacement, build with [seleniumbase](https://seleniumbase.io/) and [FastAPI](https://fastapi.tiangolo.com).
|
||||
|
||||
> [!WARNING]
|
||||
> [!CAUTION]
|
||||
> From now on, Byparr will clear all chrome processes longer than specified in `MAX_CHROME_LIFETIME` environment variable (default is 300 seconds). To disable this behavior, set `MAX_CHROME_LIFETIME` to `0`.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Due to recent challenge changes, this software does not guarantee that the Cloudflare challenge will be bypassed. Cloudflare likely requires valid network traffic originating from the user’s public IP address to mark a connection as legitimate. While this tool may bypass the initial browser check, it does not ensure that requests will consistently pass Cloudflare's validation. More testing and data are required to understand how Cloudflare identifies connections and requests as valid. Invalid requests will result in Byparr's looping and eventually time-outing.
|
||||
|
||||
> [!WARNING]
|
||||
> [!IMPORTANT]
|
||||
> Support for NAS devices (like Synology) is minimal. Please report issues, but do not expect it to be fixed quickly. The only ARM device I have is a free Ampere Oracle VM, so I can only test ARM support on that. See [#22](https://github.com/ThePhaseless/Byparr/issues/22) and [#3](https://github.com/ThePhaseless/Byparr/issues/3)
|
||||
|
||||
> [!NOTE]
|
||||
@ -27,15 +30,7 @@ An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) a
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
byparr:
|
||||
image: ghcr.io/thephaseless/byparr:latest
|
||||
environment:
|
||||
- LOG_LEVEL=INFO # optional
|
||||
ports:
|
||||
- "8191:8191" # Optional if needed to make make requests/check docs on host
|
||||
```
|
||||
See `docker-compose.yaml`
|
||||
|
||||
### Docker
|
||||
|
||||
|
@ -6,5 +6,6 @@ services:
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
- LOG_LEVEL=INFO
|
||||
- MAX_CHROME_LIFETIME=300
|
||||
ports:
|
||||
- "8191:8191"
|
||||
|
14
main.py
14
main.py
@ -12,10 +12,11 @@ from sbase import SB, BaseCase
|
||||
|
||||
import src
|
||||
import src.utils
|
||||
from src.utils import consts
|
||||
import src.utils.consts
|
||||
from src.models.requests import LinkRequest, LinkResponse, Solution
|
||||
from src.utils import logger
|
||||
from src.utils.consts import LOG_LEVEL
|
||||
from src.utils.consts import LOG_LEVEL, kill_chromium_processes
|
||||
|
||||
app = FastAPI(debug=LOG_LEVEL == logging.DEBUG, log_level=LOG_LEVEL)
|
||||
|
||||
@ -25,18 +26,19 @@ cookies = []
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
"""Redirect to /docs."""
|
||||
logger.info("Redirecting to /docs")
|
||||
logger.debug("Redirecting to /docs")
|
||||
return RedirectResponse(url="/docs", status_code=301)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
"""Health check endpoint."""
|
||||
logger.info("Health check")
|
||||
|
||||
health_check_request = read_item(
|
||||
LinkRequest.model_construct(url="https://prowlarr.servarr.com/v1/ping")
|
||||
)
|
||||
if consts.MAX_CHROME_LIFETIME>0:
|
||||
kill_chromium_processes()
|
||||
|
||||
if health_check_request.solution.status != HTTPStatus.OK:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
@ -66,9 +68,9 @@ def read_item(request: LinkRequest) -> LinkResponse:
|
||||
source = sb.get_page_source()
|
||||
source_bs = BeautifulSoup(source, "html.parser")
|
||||
title_tag = source_bs.title
|
||||
logger.info(f"Got webpage: {request.url}")
|
||||
logger.debug(f"Got webpage: {request.url}")
|
||||
if title_tag and title_tag.string in src.utils.consts.CHALLENGE_TITLES:
|
||||
logger.info("Challenge detected")
|
||||
logger.debug("Challenge detected")
|
||||
sb.uc_gui_click_captcha()
|
||||
logger.info("Clicked captcha")
|
||||
|
||||
|
@ -10,6 +10,7 @@ readme = "README.md"
|
||||
dependencies = [
|
||||
"beautifulsoup4==4.12.3",
|
||||
"fastapi[standard]==0.115.6",
|
||||
"psutil==6.1.0",
|
||||
"pyautogui==0.9.54",
|
||||
"pydantic==2.10.3",
|
||||
"seleniumbase==4.33.10",
|
||||
|
@ -1,5 +1,10 @@
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
||||
import psutil
|
||||
|
||||
from src.utils import logger
|
||||
|
||||
|
||||
def get_version_from_env():
|
||||
@ -21,12 +26,38 @@ def get_version_from_env():
|
||||
|
||||
return version_env.removeprefix("v")
|
||||
|
||||
def kill_chromium_processes():
|
||||
# Define the prefix and time threshold
|
||||
prefix = "chromium"
|
||||
time_threshold = 300 # 5 minutes in seconds
|
||||
|
||||
# Get the current time
|
||||
current_time = time.time()
|
||||
|
||||
# Iterate through all processes
|
||||
for proc in psutil.process_iter(['pid', 'name', 'create_time']):
|
||||
try:
|
||||
# Extract process details
|
||||
pid = proc.info['pid']
|
||||
name:str = proc.info['name']
|
||||
create_time = proc.info['create_time']
|
||||
|
||||
# Check if the process name starts with the prefix and has been running longer than the threshold
|
||||
if name and name.startswith(prefix) and (current_time - create_time > time_threshold):
|
||||
logger.info(f"Terminating process {name} (PID: {pid}) running for {int(current_time - create_time)} seconds")
|
||||
psutil.Process(pid).terminate() # Terminate the process
|
||||
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||
# Ignore processes that no longer exist or can't be accessed
|
||||
pass
|
||||
|
||||
LOG_LEVEL = os.getenv("LOG_LEVEL") or "INFO"
|
||||
LOG_LEVEL = logging.getLevelNamesMapping()[LOG_LEVEL.upper()]
|
||||
|
||||
VERSION = get_version_from_env() or "unknown"
|
||||
|
||||
MAX_CHROME_LIFETIME= int(os.getenv("MAX_CHROME_LIFETIME", 300))
|
||||
|
||||
|
||||
CHALLENGE_TITLES = [
|
||||
# Cloudflare
|
||||
|
17
uv.lock
generated
17
uv.lock
generated
@ -66,6 +66,7 @@ source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "beautifulsoup4" },
|
||||
{ name = "fastapi", extra = ["standard"] },
|
||||
{ name = "psutil" },
|
||||
{ name = "pyautogui" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "seleniumbase" },
|
||||
@ -90,6 +91,7 @@ test = [
|
||||
requires-dist = [
|
||||
{ name = "beautifulsoup4", specifier = "==4.12.3" },
|
||||
{ name = "fastapi", extras = ["standard"], specifier = "==0.115.6" },
|
||||
{ name = "psutil", specifier = ">=6.1.0" },
|
||||
{ name = "pyautogui", specifier = "==0.9.54" },
|
||||
{ name = "pydantic", specifier = "==2.10.3" },
|
||||
{ name = "seleniumbase", specifier = "==4.33.10" },
|
||||
@ -594,6 +596,21 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psutil"
|
||||
version = "6.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/26/10/2a30b13c61e7cf937f4adf90710776b7918ed0a9c434e2c38224732af310/psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a", size = 508565 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/01/9e/8be43078a171381953cfee33c07c0d628594b5dbfc5157847b85022c2c1b/psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688", size = 247762 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/cb/313e80644ea407f04f6602a9e23096540d9dc1878755f3952ea8d3d104be/psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e", size = 248777 },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/8e/bcbe2025c587b5d703369b6a75b65d41d1367553da6e3f788aff91eaf5bd/psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38", size = 284259 },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/4d/8245e6f76a93c98aab285a43ea71ff1b171bcd90c9d238bf81f7021fb233/psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b", size = 287255 },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/c2/d034856ac47e3b3cdfa9720d0e113902e615f4190d5d1bdb8df4b2015fb2/psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a", size = 288804 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/55/5389ed243c878725feffc0d6a3bc5ef6764312b6fc7c081faaa2cfa7ef37/psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e", size = 250386 },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/91/87fa6f060e649b1e1a7b19a4f5869709fbf750b7c8c262ee776ec32f3028/psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be", size = 254228 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyautogui"
|
||||
version = "0.9.54"
|
||||
|
Loading…
x
Reference in New Issue
Block a user