Compare commits

...
181 Commits
Author SHA1 Message Date
ThePhaseless 332402652d switch to curl 2025-02-28 23:10:09 +01:00
ThePhaseless 061f0d44de fix latest tagging 2025-02-28 19:28:05 +01:00
ThePhaseless b7914268bc readd test 2025-02-28 19:16:47 +01:00
ThePhaseless 2e8ed3fa9b remove apt caching 2025-02-28 19:16:09 +01:00
ThePhaseless 6f6941e423 lowercase registry 2025-02-28 19:01:06 +01:00
ThePhaseless 25ae01ba71 remove artifact upload 2025-02-28 18:46:48 +01:00
ThePhaseless a065b4b7ae remove invalid argument 2025-02-28 18:43:55 +01:00
ThePhaseless 508568ded7 login before push 2025-02-28 18:36:00 +01:00
ThePhaseless 72f54fc0a9 push and then merge 2025-02-28 18:33:30 +01:00
ThePhaseless 1499cfa3df push before merging 2025-02-28 18:16:39 +01:00
ThePhaseless cf46f481e1 fix bash 2025-02-28 18:04:23 +01:00
ThePhaseless c90b0ab91e echo args 2025-02-28 17:53:04 +01:00
ThePhaseless f5e75b451c push all tags into one 2025-02-28 17:43:57 +01:00
ThePhaseless 0fbae3f9dd bump buildkit cache 2025-02-28 17:14:40 +01:00
ThePhaseless 70f99e40fc tweak labels 2025-02-28 17:09:23 +01:00
ThePhaseless 6a56098a33 add platform to apt cache name 2025-02-28 16:28:32 +01:00
ThePhaseless 7dd1dd633f upload apt and uv cache 2025-02-28 16:24:20 +01:00
ThePhaseless e825e588a8 add qemu back 2025-02-28 16:17:54 +01:00
ThePhaseless 43fe522417 [skip ci] allow sha versions 2025-02-28 16:13:28 +01:00
ThePhaseless ad88b7b505 comment out test 2025-02-28 16:11:59 +01:00
ThePhaseless 78deb9ed34 tweaks to tags 2025-02-28 16:11:10 +01:00
renovate[bot] 65f39b4448 Update dependency fastapi to v0.115.9 (#96)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 02:18:00 +00:00
ThePhaseless 565b076c67 cache apt and uv libs 2025-02-28 01:06:25 +01:00
ThePhaseless 0ea76ac000 add ca-certs 2025-02-27 23:29:47 +00:00
ThePhaseless 52f4b6110a docker way to install uv 2025-02-27 23:28:23 +00:00
ThePhaseless 8c9795150e cleanup dockerfile 2025-02-27 23:16:34 +00:00
ThePhaseless 44c3d5b512 dont upgrade packages 2025-02-27 20:31:37 +00:00
ThePhaseless 817610d216 add qemu 2025-02-27 20:20:55 +00:00
ThePhaseless bf1daabaf9 another attempt 2025-02-27 20:07:23 +00:00
ThePhaseless 9445ffc5f6 fix invalidating cache 2025-02-27 19:57:00 +00:00
ThePhaseless 67303951bb add version to container 2025-02-27 19:42:32 +00:00
ThePhaseless 42303d5582 another fix 2025-02-27 19:41:54 +00:00
ThePhaseless 35c6189f6d try fixing new build 2025-02-27 19:10:47 +00:00
ThePhaseless 1e6bd9e656 do not use proxy on tests 2025-02-27 19:10:47 +00:00
ThePhaseless 7bd7925530 log version 2025-02-27 19:10:47 +00:00
renovate[bot] f0dd9517e7 Update dependency ruff to v0.9.8 (#95)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 18:47:33 +00:00
renovate[bot] af72a32870 Update dependency seleniumbase to v4.35.2 (#94)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 02:41:31 +00:00
ThePhaseless d0dea96f63 try new build action 2025-02-26 11:03:46 +01:00
ThePhaseless d7138776a5 better logging 2025-02-26 11:03:46 +01:00
ThePhaseless 7e2c895a11 faster title check 2025-02-26 11:03:46 +01:00
renovate[bot] 29793054f8 Update dependency seleniumbase to v4.35.1 (#89)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 02:46:42 +00:00
renovate[bot] 9fbf4982c8 Update dependency seleniumbase to v4.35.0 (#85)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-21 09:46:27 +00:00
renovate[bot] f60d828914 Update dependency ruff to v0.9.7 (#87)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-21 05:53:27 +00:00
ThePhaseless bdcf756b7e [skip ci] update TODO and fix None as default for Proxy 2025-02-20 22:59:11 +01:00
ThePhaseless 61ef009944 [skip ci] sync tests and build x64 cache 2025-02-20 21:47:15 +00:00
ThePhaseless 02fdfb619a remove psutil 2025-02-20 21:45:53 +00:00
ThePhaseless 978efa7a5b build arm first 2025-02-20 21:34:14 +00:00
ThePhaseless a912a32eea try to fix gha apt error 2025-02-20 21:34:07 +00:00
ThePhaseless b8a3995c8c [skip ci] fix typo and remake Troubleshooting 2025-02-20 21:31:17 +00:00
ThePhaseless 59104a3c6e [skip ci] readd symlink for chromedriver to fix arm64 2025-02-20 21:20:28 +00:00
ThePhaseless a9edd671a2 do not publish test container 2025-02-20 21:00:52 +00:00
ThePhaseless 5c5451785e remove forcing headless and handmade symlink 2025-02-20 20:57:05 +00:00
ThePhaseless 4d11b950a1 add back simultaneous tests 2025-02-20 20:56:24 +00:00
ThePhaseless df161e6d2e gha cache fix 2025-02-20 20:50:11 +00:00
ThePhaseless 8e53210014 fix tests not being skipped properly 2025-02-20 20:37:02 +00:00
ThePhaseless 43cd9297cb fix #86 2025-02-20 20:36:48 +00:00
ThePhaseless 19670c8e06 fix deprecation warning 2025-02-20 20:36:33 +00:00
ThePhaseless eba16fc3de change interval to 15 minutes 2025-02-20 20:36:25 +00:00
ThePhaseless ecbb2ab182 separate files, add gzip, save screenshots on exception, add PROXY support 2025-02-17 23:08:14 +00:00
ThePhaseless 36421b2c1b use 3 retries 2025-02-17 21:55:02 +00:00
renovate[bot] ac953fe704 Update dependency seleniumbase to v4.34.15 (#83)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-14 01:49:47 +00:00
renovate[bot] 30f25acd55 Update dependency seleniumbase to v4.34.14 (#82)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-13 10:36:29 +00:00
renovate[bot] 554347ce6f Update dependency seleniumbase to v4.34.13 (#81)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 07:40:27 +00:00
renovate[bot] 58a486c41d Update dependency ruff to v0.9.6 (#79)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-11 19:54:18 +00:00
renovate[bot] dc80b0cccf Update dependency seleniumbase to v4.34.12 (#78)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-08 09:28:20 +00:00
renovate[bot] 84a70ad35b Update dependency seleniumbase to v4.34.10 (#77)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-08 01:14:19 +00:00
renovate[bot] 6618bcf651 Update dependency seleniumbase to v4.34.9 (#75)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 17:22:47 +00:00
renovate[bot] 620c768375 Update dependency ruff to v0.9.5 (#76)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 01:27:10 +00:00
ThePhaseless 9244768ce4 remove bs4 from direct deps 2025-02-06 18:46:39 +00:00
ThePhaseless 9bd13e19a0 [skip ci] Add Docker as host 2025-02-06 18:39:53 +00:00
ThePhaseless ecd9e0aee2 [skip ci] remove checkbox index 2025-02-06 18:36:47 +00:00
ThePhaseless 78137997e1 [skip ci] use new issue type 2025-02-06 18:36:00 +00:00
ThePhaseless 03c98375f2 remove blank issues 2025-02-06 17:54:25 +00:00
ThePhaseless 4bfb7845dd remove btmet due to dns issue 2025-02-06 17:50:44 +00:00
renovate[bot] d7c22f042e Update dependency seleniumbase to v4.34.6 (#72)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-02 20:50:05 +00:00
renovate[bot] 33a1327f93 Update dependency seleniumbase to v4.34.5 (#71)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-02 00:57:51 +00:00
renovate[bot] e52616934b Update dependency ruff to v0.9.4 (#70)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 01:37:57 +00:00
renovate[bot] 892daccc60 Update dependency fastapi to v0.115.8 (#69)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 22:09:55 +00:00
renovate[bot] 3d91874ddb Update dependency seleniumbase to v4.34.4 (#68)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-29 09:56:16 +00:00
renovate[bot] 3026ed4a41 Update dependency pytest-asyncio to v0.25.3 (#67)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-29 01:24:38 +00:00
ThePhaseless 4b5d82b4f1 remove apt python binaries 2025-01-27 20:56:50 +00:00
ThePhaseless 56d9a4659b update seleniumbase 2025-01-26 19:50:26 +00:00
ThePhaseless 273622c30c use uv as base 2025-01-26 19:50:21 +00:00
renovate[bot] d0b51020a0 Update dependency deptry to v0.23.0 (#66)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-26 12:26:48 +00:00
renovate[bot] d17def34ba Update dependency ruff to v0.9.3 (#64)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 12:59:06 +00:00
renovate[bot] 40a4bf3d8f Update dependency fastapi to v0.115.7 (#63)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 09:49:14 +00:00
renovate[bot] e0bb4115fb Update dependency pydantic to v2.10.6 (#65)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 05:53:35 +00:00
renovate[bot] 9e2d40845c Update dependency pytest-retry to v1.7.0 (#61)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-19 12:26:29 +00:00
renovate[bot] 6c3da87c00 Update dependency ruff to v0.9.2 (#60)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-16 21:39:41 +00:00
ThePhaseless 78d97dfd0d [skip ci] Remove deprecated env 2025-01-16 13:43:10 +01:00
renovate[bot] 4461f5a59a Update dependency seleniumbase to v4.33.15 (#58)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 09:54:19 +00:00
renovate[bot] 7dac738ac5 Update dependency ruff to v0.9.1 (#57)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-11 02:22:06 +00:00
renovate[bot] ead7a09ce2 Update dependency deptry to v0.22.0 (#56)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 18:34:01 +00:00
renovate[bot] bf85a854fa Update dependency seleniumbase to v4.33.14 (#55)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 09:42:44 +00:00
renovate[bot] 9a20451ad9 Update dependency seleniumbase to v4.33.13 (#54)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 02:36:09 +00:00
renovate[bot] 150bf80583 Update dependency ruff to v0.9.0 (#53)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-09 22:05:49 +00:00
renovate[bot] bcce6779cc Update dependency pydantic to v2.10.5 (#52)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-09 17:51:57 +00:00
renovate[bot] cd7e803411 Update dependency pytest-asyncio to v0.25.2 (#51)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 17:52:39 +00:00
renovate[bot] 5dc76167c2 Update dependency ruff to v0.8.6 (#50)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-04 16:55:58 +00:00
renovate[bot] 8ae150fd87 Update dependency ruff to v0.8.5 (#49)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 19:58:26 +00:00
ThePhaseless 0325877e19 [skip ci] clarified xvfb platform requirement 2025-01-02 12:35:30 +00:00
ThePhaseless c4159e5c38 disable headless on docker 2025-01-02 12:29:10 +00:00
ThePhaseless 83169ce019 add headless env 2025-01-02 12:18:21 +00:00
ThePhaseless 1c0929fbc5 check if url is valid 2025-01-02 12:17:43 +00:00
renovate[bot] 9170967455 Update dependency pytest-asyncio to v0.25.1 (#48)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 09:14:41 +00:00
renovate[bot] d5d0bf7923 Update dependency seleniumbase to v4.33.12 (#47)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-25 09:53:33 +00:00
renovate[bot] 17854c70ed Update dependency deptry to v0.21.2 (#45)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 05:22:27 +00:00
renovate[bot] e30954c98c Update dependency psutil to v6.1.1 (#44)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-19 22:35:44 +00:00
renovate[bot] 2556a1bc88 Update dependency ruff to v0.8.4 (#43)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-19 15:40:42 +00:00
renovate[bot] 6c065d4dd3 Update dependency pydantic to v2.10.4 (#42)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 21:51:16 +00:00
ThePhaseless 096eda0fa3 fix utils 2024-12-18 13:32:37 +00:00
ThePhaseless 2ebb1bd820 optional xvfb support 2024-12-18 13:29:00 +00:00
ThePhaseless bf37539890 do not use virtual display 2024-12-17 12:03:53 +00:00
ThePhaseless d7ef83b8c6 add tags info and use latest on stable release 2024-12-17 12:03:36 +00:00
renovate[bot] 1a7cd9d657 Update dependency seleniumbase to v4.33.11 (#41)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 00:47:28 +00:00
renovate[bot] f9387e6942 Update dependency uvicorn to v0.34.0 (#40)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 19:06:58 +00:00
renovate[bot] 9d8c8db979 Update dependency uvicorn to v0.33.0 (#39)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-14 15:46:21 +00:00
renovate[bot] 979e0b4803 Update dependency ruff to v0.8.3 (#38)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-14 04:02:50 +00:00
ThePhaseless 3dbe3c424c fix circular imports 2024-12-13 22:43:29 +00:00
ThePhaseless bbb7c73065 kill old processes 2024-12-13 22:38:47 +00:00
ThePhaseless 9a353b3da2 remove poetry remains 2024-12-13 22:30:58 +00:00
ThePhaseless 140a97003e update packages 2024-12-13 21:12:30 +00:00
ThePhaseless c9e29f578d save cookies between requests 2024-12-12 23:45:24 +00:00
ThePhaseless c37ab51179 combine apt installs to one 2024-12-11 01:04:08 +00:00
ThePhaseless 962db9409c pull before build and test 2024-12-11 01:02:59 +00:00
ThePhaseless 96a9cc7ba9 test, then build 2024-12-11 01:01:00 +00:00
ThePhaseless bf9460b960 delete unused file 2024-12-11 00:52:20 +00:00
ThePhaseless c0547192dd test only on amd64 2024-12-11 00:46:53 +00:00
ThePhaseless 008077076c try using arm builder 2024-12-11 00:44:22 +00:00
ThePhaseless b33444dc48 use matrix for build 2024-12-11 00:40:11 +00:00
ThePhaseless b8c8576e5a github actions shared lib fix 2024-12-11 00:21:07 +00:00
ThePhaseless 905d802a26 add back retires 2024-12-10 23:38:13 +00:00
ThePhaseless f99429fdea update all packages but install only needed 2024-12-10 23:28:29 +00:00
ThePhaseless 1a4ec03587 Merge pull request #37 from ThePhaseless/uv
Uv
2024-12-10 23:50:34 +01:00
ThePhaseless ee2630dce2 enable auto update 2024-12-10 22:48:53 +00:00
ThePhaseless 82130b77c0 fix docker and update readme 2024-12-10 22:48:35 +00:00
ThePhaseless faf7e5e51a migrate to uv 2024-12-10 22:16:30 +00:00
ThePhaseless 597faa48dc add response type 2024-12-10 21:54:39 +00:00
ThePhaseless a28dbbe972 use docker to test 2024-12-10 21:54:29 +00:00
ThePhaseless 82124dee9b force exit on exception 2024-12-10 21:29:20 +00:00
ThePhaseless 0551c7b82b use uv 2024-12-08 16:49:38 +00:00
ThePhaseless b483dba080 [skip ci] Mili to Mega 2024-12-02 10:29:13 +01:00
ThePhaseless 7533d039ac Merge pull request #30 from ThePhaseless/renovate/python-3.x
Update python Docker tag to v3.13
2024-11-30 14:26:22 +01:00
renovate[bot] 38b2ea0798 Update python Docker tag to v3.13 2024-11-30 12:59:43 +00:00
ThePhaseless 58ae7964df remove python action update script 2024-11-30 12:59:00 +00:00
ThePhaseless 5283fb2d0e exclude python from autoupdate 2024-11-30 12:58:02 +00:00
ThePhaseless b3e7662782 fix ruff 2024-11-30 12:48:04 +00:00
ThePhaseless 074a3dd712 [skip ci] fix renovate 2024-11-30 12:47:34 +00:00
ThePhaseless cb48f16370 update python version in action with base 2024-11-30 12:45:19 +00:00
ThePhaseless 637de7572d use latest cosign 2024-11-30 12:44:08 +00:00
ThePhaseless 7b55252a73 run ruff before tests 2024-11-30 12:43:56 +00:00
ThePhaseless cbe4cf57a5 use all urls always 2024-11-30 12:43:05 +00:00
ThePhaseless 0775d107ad add version control and more verbose error return 2024-11-30 12:42:51 +00:00
ThePhaseless d36972b80e update python in action 2024-11-30 12:42:17 +00:00
renovate[bot] 27ec17f7f2 Update dependency seleniumbase to v4.33.2 (#24)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-30 12:08:29 +00:00
ThePhaseless 0b2bf9e12a use dynamic driver symlink 2024-11-30 11:38:48 +00:00
renovate[bot] 8c6906c916 Update dependency ruff to v0.8.1 (#29)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-29 06:26:30 +00:00
renovate[bot] 3103051ccf Update dependency httpx to ^0.28.0 (#28)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-28 18:20:06 +00:00
ThePhaseless 8551bdfef8 Merge pull request #25 from ThePhaseless/renovate/docker-build-push-action-6.x
Update docker/build-push-action action to v6.10.0
2024-11-28 14:06:45 +01:00
renovate[bot] cdebe4be0e Update docker/build-push-action action to v6.10.0 2024-11-28 13:06:36 +00:00
ThePhaseless 543296ce68 update lockfile 2024-11-28 12:56:09 +00:00
ThePhaseless 7210ae4bc0 add and ignore pyautogui 2024-11-28 12:55:55 +00:00
ThePhaseless f782e1bed6 Create LICENSE 2024-11-28 13:40:46 +01:00
ThePhaseless 49329ec950 update lockfile 2024-11-28 12:35:29 +00:00
ThePhaseless 2ae289ef0c use renovate instead of dependabot 2024-11-28 12:33:04 +00:00
ThePhaseless 8ef570ec46 separate depedencies and fill out details 2024-11-28 12:32:55 +00:00
ThePhaseless e899f8d5ac Merge pull request #23 from ThePhaseless/renovate/configure
Configure Renovate
2024-11-28 13:28:06 +01:00
renovate[bot] ab0e7f9e43 Add renovate.json 2024-11-28 12:27:27 +00:00
ThePhaseless d26974e22a [skip ci] Add example issues for NAS devices 2024-11-26 21:15:34 +01:00
ThePhaseless 994dcb2dc4 add manual build 2024-11-26 18:18:02 +00:00
ThePhaseless 0d4d5093ca [skip ci] update readme and bug report 2024-11-26 17:56:10 +00:00
ThePhaseless fd8c7156fd use async test 2024-11-26 17:43:25 +00:00
ThePhaseless 39a5045836 Use httpstatus code 2024-11-26 12:20:03 +00:00
ThePhaseless 6dc1133daf switch to bullseye to fix chromium not launching on arm 2024-11-26 12:19:52 +00:00
ThePhaseless 794ebdf00e add cache, pip, progress and fix bypass 2024-11-25 10:55:40 +00:00
ThePhaseless c366ce7db6 add healthcheck 2024-11-25 10:19:09 +00:00
ThePhaseless 00e443a5eb retry failed tests 3 times 2024-11-25 09:55:46 +00:00
ThePhaseless b9f3153689 add shebang 2024-11-25 09:54:19 +00:00
ThePhaseless 4453fa6a93 use sh file as cmd 2024-11-25 09:26:14 +00:00
ThePhaseless c40ad328f1 Merge pull request #21 from ThePhaseless/dependabot/github_actions/dot-github/workflows/docker/metadata-action-5.6.1
Bump docker/metadata-action from 5.5.1 to 5.6.1 in /.github/workflows
2024-11-25 10:09:25 +01:00
dependabot[bot] 428fbd4b24 Bump docker/metadata-action from 5.5.1 to 5.6.1 in /.github/workflows
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.5.1 to 5.6.1.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/8e5442c4ef9f78752691e2d8f8d19755c6f78e81...369eb591f429131d6889c46b94e711f089e6ca96)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 07:46:10 +00:00
35 changed files with 2264 additions and 2722 deletions
+3 -4
View File
@@ -1,5 +1,4 @@
FROM python:3.12
FROM ghcr.io/astral-sh/uv:debian
ENV UV_LINK_MODE=copy
RUN apt update && apt upgrade -y && apt install -y chromium xvfb
RUN curl -sSL https://install.python-poetry.org | python3 -
RUN apt update && apt upgrade -y && apt install -y chromium chromium-driver xvfb git
+2 -1
View File
@@ -32,6 +32,7 @@
"8181:8191"
],
"features": {
"ghcr.io/devcontainers-extra/features/act:1": {}
"ghcr.io/devcontainers-extra/features/act:1": {},
"ghcr.io/devcontainers/features/desktop-lite:1": {}
}
}
-24
View File
@@ -1,24 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**I've:**
- [ ] - read Loop Warning on Readme.
- [ ] - done the troubleshooting from Readme.
- [ ] - checked if such issue already exists.
**Docker host (please complete the following information):**
- OS: [e.g. Ubuntu Linux]
- Platform and model: [Synology, PC, Laptop, RPi 3]
- Architecture [e.g. ARM64]
**Additional context**
Add any other context about the problem here.
+47
View File
@@ -0,0 +1,47 @@
name: Bug report
description: Create a bug report
assignees: ThePhaseless
body:
- type: checkboxes
attributes:
label: "I've completed the following steps:"
options:
- label: Read Loop Warning on Readme
- label: Done the troubleshooting from Readme
- label: Checked if such issue already exists
- type: input
id: docker-host
attributes:
label: OS
placeholder: e.g. Docker, Ubuntu Linux
- type: input
id: platform-model
attributes:
label: Platform and model
placeholder: e.g. Synology, PC, Laptop, RPi 3
- type: input
id: architecture
attributes:
label: Architecture
placeholder: e.g. ARM64
- type: input
id: website
attributes:
label: Website
placeholder: e.g. https://nowsecure.nl
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
placeholder: "Example: The application crashes when trying to load a new file"
- type: textarea
attributes:
label: Additional context
description: Add any other context about the problem here.
+1
View File
@@ -0,0 +1 @@
blank_issues_enabled: false
-16
View File
@@ -1,16 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for more information:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://containers.dev/guide/dependabot
version: 2
updates:
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: weekly
- package-ecosystem: github-actions
directory: ".github/workflows/"
schedule:
interval: weekly
+121 -76
View File
@@ -14,6 +14,7 @@ on:
tags: ["v*.*.*"]
pull_request:
branches: ["main"]
workflow_dispatch:
env:
# Use docker.io for Docker Hub if empty
@@ -24,38 +25,28 @@ env:
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Test
id: test
uses: docker/build-push-action@v6
with:
python-version: "3.12"
- name: Set up Poetry
run: pip install poetry
- name: Setup a local virtual environment (if no poetry.toml file)
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
- uses: actions/cache@v4
name: Define a cache for the virtual environment based on the dependencies lock file
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}
- name: Install dependencies
run: |
poetry install
sudo apt update
sudo apt install -y xvfb scrot python3-tk
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install -y ./google-chrome-stable_current_amd64.deb
rm ./google-chrome-stable_current_amd64.deb
- name: Run tests
run: poetry run pytest
context: .
platforms: linux/amd64
cache-from: type=gha,scope=x64
pull: true
cache-to: type=gha,mode=max,scope=x64
target: test
build:
needs: test
@@ -63,43 +54,95 @@ jobs:
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
strategy:
matrix:
platform: [linux/amd64, linux/arm64]
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da #v3.7.0
with:
cosign-release: "v2.2.4"
- name: Prepare variables
id: vars
run: |
SURFIX=$(echo ${{ matrix.platform }} | cut -d'/' -f2)
echo "SURFIX=$SURFIX" >> $GITHUB_OUTPUT
# Generate a unique local tag for the image
echo "LOCAL_TAG=${{ github.sha }}-$SURFIX" >> $GITHUB_OUTPUT
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Set up BuildKit Docker container builder
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
# Log into registry
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
uses: docker/metadata-action@v5
with:
tags: type=raw,value=${{ steps.vars.outputs.LOCAL_TAG }}
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and export Docker image for each platform (without pushing)
- name: Build Docker image
id: build
uses: docker/build-push-action@v6
with:
context: .
pull: true
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ matrix.platform }}
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
build-args: GITHUB_BUILD=true,VERSION=${{ github.ref_type == 'tag' && github.ref_name || github.sha }}
merge-and-push:
needs: build
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Install the cosign tool
- name: Install cosign
uses: sigstore/cosign-installer@v3
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Log into registry
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract Docker metadata for tagging
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
tags: |
type=ref,event=branch
@@ -107,35 +150,37 @@ jobs:
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,enable=${{ github.event_name != 'pull_request' && github.ref_name == 'main' }}, value=latest
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: GITHUB_BUILD=true
# Create manifest lists and push
- name: Create and push manifest lists
run: |
TAGS="${{ steps.meta.outputs.tags }}"
args=""
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
image=${image,,}
# Create tag arguments
for tag in $TAGS; do
args="$args -t $tag"
done
if [ "${{ github.ref_type }}" == "tag" ]; then
args="$args -t ${image}:latest"
fi
echo $args
docker buildx imagetools create $args \
${image}:${{github.sha}}-amd64 \
${image}:${{github.sha}}-arm64
# Sign the manifest
- name: Sign the manifests
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
run: |
for TAG in $TAGS; do
cosign sign --yes $TAG
done
+1 -1
View File
@@ -165,7 +165,7 @@ cython_debug/
core
# Screenshots
*.png
screenshots/
# Downloaded files
downloaded_files/
+14 -22
View File
@@ -1,27 +1,19 @@
{
"configurations": [
{
"console": "integratedTerminal",
"env": {
"LOG_LEVEL": "DEBUG"
},
"justMyCode": false,
"name": "Python Debugger: Main",
"program": "main.py",
"request": "launch",
"type": "debugpy"
},
],
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Main",
"type": "debugpy",
"justMyCode": false,
"env": {
"LOG_LEVEL": "DEBUG",
},
"request": "launch",
"program": "main.py",
"console": "integratedTerminal"
},
{
"name": "Python Debugger: Current File",
"justMyCode": false,
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
"version": "0.2.0"
}
+13 -10
View File
@@ -1,20 +1,23 @@
{
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.analysis.autoImportCompletions": true,
"python.analysis.typeCheckingMode": "basic",
"python.terminal.activateEnvironment": true,
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.defaultFormatter": "charliermarsh.ruff"
},
"python.analysis.autoImportCompletions": true,
"python.analysis.packageIndexDepths": [
{
"name": "",
"depth": 5,
"includeAllSymbols": true,
"name": ""
}
],
"python.analysis.typeCheckingMode": "standard",
"python.terminal.activateEnvironment": true,
"python.testing.pytestArgs": [
"tests",
"-n",
"auto",
"--retries=3",
],
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false
}
+28 -18
View File
@@ -1,30 +1,40 @@
FROM python:3.12-slim
FROM debian:bullseye-slim AS base
# Inspired by https://github.com/Hudrolax/uc-docker-alpine/
ARG GITHUB_BUILD=false \
VERSION
ARG GITHUB_BUILD=false
ENV GITHUB_BUILD=${GITHUB_BUILD}
ENV HOME=/root
ENV \
ENV HOME=/root \
GITHUB_BUILD=${GITHUB_BUILD}\
VERSION=${VERSION}\
DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
# prevents python creating .pyc files
PYTHONDONTWRITEBYTECODE=1 \
# do not ask any interactive question
POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=true \
DISPLAY=:0
ENV PATH="${HOME}/.local/bin:$PATH"
WORKDIR /app
EXPOSE 8191
RUN apt update &&\
apt install -y xvfb scrot python3-tk curl chromium
RUN curl -sSL https://install.python-poetry.org | python3 -
ENV PATH="${HOME}/.local/bin:$PATH"
COPY pyproject.toml poetry.lock ./
RUN poetry install
RUN apt-get update && \
apt-get install -y --no-install-recommends --no-install-suggests xauth xvfb scrot curl chromium chromium-driver ca-certificates
ADD https://astral.sh/uv/install.sh install.sh
RUN sh install.sh
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=${HOME}/.cache/uv uv sync
# SeleniumBase does not come with an arm64 chromedriver binary
RUN cd .venv/lib/*/site-packages/seleniumbase/drivers && ln -s /usr/bin/chromedriver uc_driver
COPY . .
CMD [". .venv/bin/activate && python3 main.py"]
FROM base AS test
RUN --mount=type=cache,target=${HOME}/.cache/uv uv sync --group test
RUN ./test.sh
FROM base
EXPOSE 8191
HEALTHCHECK --interval=15m --timeout=30s --start-period=5s --retries=3 CMD [ "curl", "http://localhost:8191/health" ]
CMD ["./cmd.sh"]
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+53 -37
View File
@@ -1,56 +1,72 @@
# Byparr
An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) as a drop-in replacement, build with [nodriver](https://github.com/ultrafunkamsterdam/nodriver) and [FastAPI](https://fastapi.tiangolo.com).
> [!WARNING]
> 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 timeouting.
An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) as a drop-in replacement, built with [seleniumbase](https://seleniumbase.io/) and [FastAPI](https://fastapi.tiangolo.com).
> [!IMPORTANT]
> Currenly, due to [bug in nodriver](https://github.com/ultrafunkamsterdam/undetected-chromedriver/issues/1954), if you want to run this project ouside of prebuild container, you have to run `python fix_nodriver.py` after creating venv to patch the library.
> 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.
> [!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]
> Thanks to FastAPI implementation, now you can also see the API documentation at `/docs` or `/` (redirect to `/docs`) endpoints.
## Early Development
Long story short, I created it in like 3 days, so if you get any bugs/hangs etc. please report it, so both of us can enjoy unblocked websites!
I focus maily on Cloudflare, which is tested daily, any other anti-bot challenges should pass out of the box, but if any issues, please report these providers with an example website ❤️
## Troubleshooting
1. Clone repo to the host that has the container has issues on.
2. Using vscode and `SSH extention`, connect to the host and open repo in it.
4. Download `devcontainers` extention and reopen repo in container (with `CTRL + SHIFT + P` -> `Reopen in devcontainer`)
3. Open vscode terminal (`` CTRL + ` ``) and run `./run_vnc.sh` script.
5. Write down the port from `Forwarded Address` in `Ports` tab in vscode (probably 5900).
6. Open <https://novnc.com/noVNC/vnc.html> in your pc's browser and using settings on left under websocket, set host to `localhost` nad port to the port you wrote down and disable encryption.
7. Connect to the VNC server on container.
8. Check if `chromium` works by running in VNC's terminal command `chromium --no-sandbox`
9. If chromium works, run (or run debug) tests from VS Code.
10. Check if everything works by observing VNC in the browser as code is being tested.
11. If code works, congrats! (/s) You are on your own.
12. If it does not, try another host or network and try again.
### Docker
1. Clone repo to the host that has issues with Byparr.
2. Run `docker build --target test .`
3. Depending of the build success:
1. If run successfully, try updating container or if already on newest stable release create an issue for creating new release with new dependencies
2. If build fails, try troubleshooting on another host/using other method
### Local
1. Download [uv](https://docs.astral.sh/uv/getting-started/installation/)
2. Download dependencies using `uv sync --group test`
3. Run tests with `uv run pytest --retries 3` (You can add `-n auto` for parallelization)
4. If you see any `F` character in terminal, that means test failed even after retries.
5. Depending of the test success:
1. If run successfully, try updating container or if already on newest stable release create an issue for creating new release with new dependencies
2. If test fails, try troubleshooting on another host/using other method
## Options
| Env | Default | Description |
| -------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `USE_XVFB` | `SeleniumBase default` | Use virtual desktop with Xvfb. (Linux only) (Can cause performance hog [#14](https://github.com/ThePhaseless/Byparr/issues/14)) |
| `USE_HEADLESS` | `SeleniumBase default` | Use headless chromium. |
| `PROXY` | None | Proxy to use. (format: `username:password@host:port`) |
## Tags
- `v*.*.*`/`latest` - Releases considered stable
- `main` - Latest release from main branch (untested)
## Usage
### Docker Compose
```yaml
services:
byparr:
image: ghcr.io/thephaseless/byparr
environment:
- LOG_LEVEL=INFO # optional
ports:
- "8191:8191" # Optional if used with *arr network
See `compose.yaml`
### Docker
```bash
docker run -p 8191:8191 ghcr.io/thephaseless/byparr:latest
```
### Local
```bash
uv sync && ./cmd.sh
```
## Need help with / TODO
- [ ] Slimming container (~3GB bruh)
- [ ] Add more anti-bot challenges
- [x] Add docstrings
- [ ] Implement versioning
- [ ] Proxy support
- [ ] Add more architectures support
- [x] Slimming container (only ~650 MB now!)
- [x] Add more anti-bot challenges
- [x] Add doc strings
- [x] Implement versioning
- [x] Proxy support
- [x] Add more architectures support
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
uv run main.py
+2
View File
@@ -6,5 +6,7 @@ services:
dockerfile: Dockerfile
environment:
- LOG_LEVEL=INFO
volumes:
- ./screenshots:/app/screenshots # For screenshots when exception occurs
ports:
- "8191:8191"
-65
View File
@@ -1,65 +0,0 @@
# https://github.com/ultrafunkamsterdam/undetected-chromedriver/issues/1954
# Fix for nodriver in .venv/lib/python3.11/site-packages/nodriver/core/browser.py
from __future__ import annotations
import logging
import os
from pathlib import Path
from platform import python_version
env_path = os.getenv("VIRTUAL_ENV")
if env_path is None:
env_path = Path(os.__file__).parent.parent.parent.as_posix()
python_version = python_version().split(".")[0:2]
nodriver_path = Path(env_path + f"/lib/python{'.'.join(python_version)}/site-packages/nodriver/cdp/network.py")
if not nodriver_path.exists():
msg = f"{nodriver_path} not found"
raise FileNotFoundError(msg)
new_cookie_partition_key = """\
if isinstance(json, str):
return cls(top_level_site=json, has_cross_site_ancestor=False)
elif isinstance(json, dict):
return cls(
top_level_site=str(json["topLevelSite"]),
has_cross_site_ancestor=bool(json["hasCrossSiteAncestor"]),
)
"""
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info(f"Fixing nodriver in {nodriver_path}")
# delete CookiePartitionKey declaration
with nodriver_path.open("r+") as f:
lines = f.readlines()
found_def = False
found_body = False
i = -1
while i < len(lines):
i += 1
line = lines[i]
strip_line = line.strip("\n")
if not found_def and line.startswith("class CookiePartitionKey:"):
logger.info(f"Found line {i}: {strip_line}")
found_def = True
continue
if found_def:
if line.startswith(" def from_json"):
logger.info(f"Found line {i}: {strip_line}")
found_body = True
continue
if found_body:
if line.startswith(("\t\t", " ")):
logger.info(f"Removing line {i}: {strip_line}")
lines.pop(i)
i -= 1
continue
else:
lines = lines[:i] + [new_cookie_partition_key] + lines[i:]
break
with nodriver_path.open("w") as f:
f.writelines(lines)
+11 -71
View File
@@ -1,83 +1,23 @@
from __future__ import annotations
import logging
import time
import uvicorn.config
from bs4 import BeautifulSoup
from fastapi import FastAPI, HTTPException
from fastapi.responses import RedirectResponse
from sbase import SB, BaseCase
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
import src
import src.utils
import src.utils.consts
from src.models.requests import LinkRequest, LinkResponse, Solution
from src.consts import LOG_LEVEL, VERSION
from src.endpoints import router
from src.middlewares import LogRequest
from src.utils import logger
from src.utils.consts import LOG_LEVEL
logger.info("Using version %s", VERSION)
app = FastAPI(debug=LOG_LEVEL == logging.DEBUG, log_level=LOG_LEVEL)
app.add_middleware(GZipMiddleware)
app.add_middleware(LogRequest)
@app.get("/")
def read_root():
"""Redirect to /docs."""
logger.info("Redirecting to /docs")
return RedirectResponse(url="/docs", status_code=301)
@app.get("/health")
async def health_check():
"""Health check endpoint."""
logger.info("Health check")
# browser: Chrome = await new_browser()
# browser.get("https://google.com")
# browser.stop()
return {"status": "ok"}
@app.post("/v1")
def read_item(request: LinkRequest):
"""Handle POST requests."""
start_time = int(time.time() * 1000)
# request.url = "https://nowsecure.nl"
logger.info(f"Request: {request}")
response: LinkResponse
# start_time = int(time.time() * 1000)
with SB(uc=True, locale_code="en", test=False, xvfb=True, ad_block=True) as sb:
sb: BaseCase
sb.uc_open_with_reconnect(request.url)
sb.uc_gui_click_captcha()
logger.info(f"Got webpage: {request.url}")
sb.save_screenshot("screenshot.png")
logger.info(f"Got webpage: {request.url}")
source = sb.get_page_source()
source_bs = BeautifulSoup(source, "html.parser")
title_tag = source_bs.title
if title_tag is None:
raise HTTPException(status_code=500, detail="Title tag not found")
if title_tag.string in src.utils.consts.CHALLENGE_TITLES:
raise HTTPException(status_code=500, detail="Could not bypass challenge")
title = title_tag.string
logger.info(f"Title: {title}")
response = LinkResponse(
message="Success",
solution=Solution(
userAgent=sb.get_user_agent(),
url=sb.get_current_url(),
status=200,
cookies=sb.get_cookies(),
headers={},
response=source,
),
startTimestamp=start_time,
)
return response
app.include_router(router=router)
if __name__ == "__main__":
Generated
-2168
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
[virtualenvs]
in-project = true
create = true
+27 -20
View File
@@ -1,27 +1,34 @@
[tool.poetry]
name = "byparr"
# cspell:disable
[project]
authors = [{ name = "ThePhaseless", email = "kukubaorch@gmail.com" }]
license = { text = "LICENSE" }
requires-python = "<4.0,>=3.12"
name = "Byparr"
version = "0.1.0"
description = ""
package-mode = false
authors = ["Your Name <you@example.com>"]
description = "API for getting cookies for Cloudflare challenges"
readme = "README.md"
dependencies = [
"fastapi[standard]==0.115.9",
"pyautogui==0.9.54",
"pydantic==2.10.6",
"seleniumbase==4.35.2",
"uvicorn==0.34.0",
]
urls = { repository = "https://github.com/ThePhaseless/Byparr" }
[tool.poetry.dependencies]
python = "^3.12"
pytest = "^8"
fastapi = { extras = ["standard"], version = "^0" }
requests = "^2"
httpx = "^0.27"
pytest-asyncio = "^0"
ruff = "^0.8.0"
seleniumbase = "^4.32.12"
pyautogui = "^0.9.54"
beautifulsoup4 = "^4.12.3"
[dependency-groups]
test = [
"httpx==0.28.1",
"pytest==8.3.4",
"pytest-asyncio==0.25.3",
"pytest-progress==1.3.0",
"pytest-retry==1.7.0",
"pytest-xdist==3.6.1",
]
dev = ["deptry==0.23.0", "ruff==0.9.8"]
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.deptry.per_rule_ignores]
DEP002 = ["pyautogui"]
[tool.ruff.lint]
ignore = [
+10
View File
@@ -0,0 +1,10 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"packageRules": [
{
"automerge": true,
"matchUpdateTypes": ["minor", "patch"]
}
]
}
View File
+43
View File
@@ -0,0 +1,43 @@
import logging
import os
def get_version_from_env():
"""
Retrieve the version from the environment variable 'VERSION'.
This function checks the 'VERSION' environment variable for a value
that starts with 'v' and returns the version without the prefix.
Returns:
str | None: The version string without the 'v' prefix, or None if
the 'VERSION' environment variable is not set or does not start
with 'v'.
"""
version_env = os.getenv("VERSION")
if not version_env:
return None
return version_env.removeprefix("v")
LOG_LEVEL = os.getenv("LOG_LEVEL") or "INFO"
LOG_LEVEL = logging.getLevelNamesMapping()[LOG_LEVEL.upper()]
VERSION = get_version_from_env() or "unknown"
USE_XVFB = os.getenv("USE_XVFB") in ["true", "1"] if os.getenv("USE_XVFB") else None
USE_HEADLESS = (
os.getenv("USE_HEADLESS") in ["true", "1"] if os.getenv("USE_HEADLESS") else None
)
PROXY = os.getenv("PROXY")
CHALLENGE_TITLES = [
# Cloudflare
"Just a moment...",
# DDoS-GUARD
"DDoS-Guard",
]
+75
View File
@@ -0,0 +1,75 @@
import time
from http import HTTPStatus
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import RedirectResponse
from sbase import BaseCase
from src.consts import CHALLENGE_TITLES
from src.models import (
LinkRequest,
LinkResponse,
Solution,
)
from .utils import get_sb, logger, save_screenshot
router = APIRouter()
SeleniumDep = Annotated[BaseCase, Depends(get_sb)]
@router.get("/", include_in_schema=False)
def read_root():
"""Redirect to /docs."""
logger.debug("Redirecting to /docs")
return RedirectResponse(url="/docs", status_code=301)
@router.get("/health")
def health_check(sb: SeleniumDep):
"""Health check endpoint."""
health_check_request = read_item(
LinkRequest.model_construct(url="https://google.com"),
sb,
)
if health_check_request.solution.status != HTTPStatus.OK:
raise HTTPException(
status_code=500,
detail="Health check failed",
)
return {"status": "ok"}
@router.post("/v1")
def read_item(request: LinkRequest, sb: SeleniumDep) -> LinkResponse:
"""Handle POST requests."""
start_time = int(time.time() * 1000)
sb.uc_open_with_reconnect(request.url)
logger.debug(f"Got webpage: {request.url}")
source_bs = sb.get_beautiful_soup()
title_tag = source_bs.title
if title_tag and title_tag.string in CHALLENGE_TITLES:
logger.debug("Challenge detected")
sb.uc_gui_click_captcha()
logger.info("Clicked captcha")
if sb.get_title() in CHALLENGE_TITLES:
save_screenshot(sb)
raise HTTPException(status_code=500, detail="Could not bypass challenge")
return LinkResponse(
message="Success",
solution=Solution(
userAgent=sb.get_user_agent(),
url=sb.get_current_url(),
status=200,
cookies=sb.get_cookies(),
headers={},
response=str(sb.get_beautiful_soup()),
),
start_timestamp=start_time,
)
+29
View File
@@ -0,0 +1,29 @@
import time
from http import HTTPStatus
from starlette.middleware.base import BaseHTTPMiddleware
from src.models import LinkRequest
from src.utils import logger
class LogRequest(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
"""Log requests."""
if request.url.path != "/v1":
return await call_next(request)
start_time = time.perf_counter()
request_body = LinkRequest.model_validate(await request.json())
logger.info(
f"From: {request.client.host if request.client else 'unknown'} at {time.strftime('%Y-%m-%d %H:%M:%S')}: {request_body.url}"
)
response = await call_next(request)
process_time = time.perf_counter() - start_time
if response.status_code == HTTPStatus.OK:
logger.info(f"Done {request_body.url} in {process_time:.2f}s")
else:
logger.info(f"Failed {request_body.url} in {process_time:.2f}s")
return response
+73
View File
@@ -0,0 +1,73 @@
from __future__ import annotations
import time
from http import HTTPStatus
from typing import Annotated, Any
from fastapi import Body
from pydantic import BaseModel
from src import consts
class LinkRequest(BaseModel):
cmd: Annotated[
str,
Body(
default="request.get",
description="Type of request, currently only supports GET requests. This string is purely for compatibility with FlareSolverr.",
),
]
url: Annotated[str, Body(pattern=r"^https?://", default="https://")]
max_timeout: Annotated[int, Body(default=60)]
class Solution(BaseModel):
url: str
status: int
cookies: list
userAgent: str # noqa: N815 # Ignore to preserve compatibility
headers: dict[str, Any]
response: str
@classmethod
def invalid(cls, url: str):
"""
Return an empty Solution with default values.
Useful for returning an error response.
"""
return cls(
url=url,
status=HTTPStatus.INTERNAL_SERVER_ERROR,
cookies=[],
userAgent="",
headers={},
response="",
)
class LinkResponse(BaseModel):
status: str = "ok"
message: str
solution: Solution
start_timestamp: Annotated[int, Body(alias="startTimestamp")] = int(
time.time() * 1000
)
end_timestamp: Annotated[int, Body(alias="endTimestamp")] = int(time.time() * 1000)
version: str = consts.VERSION
@classmethod
def invalid(cls, url: str):
"""
Return an invalid LinkResponse with default error values.
This method is used to generate a response indicating an invalid request.
"""
return cls(
status="error",
message="Invalid request",
solution=Solution.invalid(url),
start_timestamp=int(time.time() * 1000),
end_timestamp=int(time.time() * 1000),
)
View File
-95
View File
@@ -1,95 +0,0 @@
from __future__ import annotations
from pydantic import BaseModel
class Author(BaseModel):
login: str
id: int
node_id: str
avatar_url: str
gravatar_id: str
url: str
html_url: str
followers_url: str
following_url: str
gists_url: str
starred_url: str
subscriptions_url: str
organizations_url: str
repos_url: str
events_url: str
received_events_url: str
type: str
site_admin: bool
class Uploader(BaseModel):
login: str
id: int
node_id: str
avatar_url: str
gravatar_id: str
url: str
html_url: str
followers_url: str
following_url: str
gists_url: str
starred_url: str
subscriptions_url: str
organizations_url: str
repos_url: str
events_url: str
received_events_url: str
type: str
site_admin: bool
class Asset(BaseModel):
url: str
id: int
node_id: str
name: str
label: str | None
uploader: Uploader
content_type: str
state: str
size: int
download_count: int
created_at: str
updated_at: str
browser_download_url: str
class Reactions(BaseModel):
url: str
total_count: int
laugh: int
hooray: int
confused: int
heart: int
rocket: int
eyes: int
class GithubResponse(BaseModel):
url: str
assets_url: str
upload_url: str
html_url: str
id: int
author: Author
node_id: str
tag_name: str
target_commitish: str
name: str
draft: bool
prerelease: bool
created_at: str
published_at: str
assets: list[Asset]
tarball_url: str
zipball_url: str
body: str
reactions: Reactions
-61
View File
@@ -1,61 +0,0 @@
from __future__ import annotations
import time
from http import HTTPStatus
from typing import Any
from pydantic import BaseModel
class LinkRequest(BaseModel):
cmd: str
url: str
maxTimeout: int # noqa: N815 # Ignore to preserve compatibility
class ProtectionTriggeredError(Exception):
pass
class Solution(BaseModel):
url: str
status: int
cookies: list
userAgent: str # noqa: N815 # Ignore to preserve compatibility
headers: dict[str, Any]
response: str
@classmethod
def empty(cls):
return cls(
url="",
status=HTTPStatus.INTERNAL_SERVER_ERROR,
cookies=[],
userAgent="",
headers={},
response="",
)
class LinkResponse(BaseModel):
status: str = "ok"
message: str
solution: Solution
startTimestamp: int # noqa: N815 # Ignore to preserve compatibility
endTimestamp: int = int(time.time() * 1000) # noqa: N815 # Ignore to preserve compatibility
version: str = "3.3.21" # TODO: Implement versioning
@classmethod
def invalid(cls):
return cls(
status="error",
message="Invalid request",
solution=Solution.empty(),
startTimestamp=int(time.time() * 1000),
endTimestamp=int(time.time() * 1000),
version="3.3.21",
)
class NoChromeExtensionError(Exception):
"""No chrome extention found."""
+35
View File
@@ -0,0 +1,35 @@
import logging
from time import gmtime, strftime
from fastapi import Header
from sbase import SB, BaseCase
from src.consts import LOG_LEVEL, PROXY, USE_HEADLESS
logger = logging.getLogger("uvicorn.error")
logger.setLevel(LOG_LEVEL)
if len(logger.handlers) == 0:
logger.addHandler(logging.StreamHandler())
def get_sb(
proxy: str | None = Header(
default=None,
examples=["username:password@host:port"],
description="Override default proxy from env",
),
):
"""Get SeleniumBase instance."""
with SB(
uc=True,
headless=USE_HEADLESS,
locale_code="en",
ad_block=True,
proxy=proxy or PROXY,
) as sb:
yield sb
def save_screenshot(sb: BaseCase):
"""Save screenshot on HTTPException."""
sb.save_screenshot(f"screenshots/{strftime('%Y-%m-%d %H:%M:%S', gmtime())}.png")
-8
View File
@@ -1,8 +0,0 @@
import logging
from src.utils.consts import LOG_LEVEL
logger = logging.getLogger("uvicorn.error")
logger.setLevel(LOG_LEVEL)
if len(logger.handlers) == 0:
logger.addHandler(logging.StreamHandler())
-12
View File
@@ -1,12 +0,0 @@
import logging
import os
LOG_LEVEL = os.getenv("LOG_LEVEL") or "INFO"
LOG_LEVEL = logging.getLevelNamesMapping()[LOG_LEVEL.upper()]
CHALLENGE_TITLES = [
# Cloudflare
"Just a moment...",
# DDoS-GUARD
"DDoS-Guard",
]
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
uv run pytest --retries 3 -n auto
+18 -10
View File
@@ -5,29 +5,26 @@ import pytest
from starlette.testclient import TestClient
from main import app
from src.models.requests import LinkRequest
from src.models import LinkRequest
client = TestClient(app)
test_websites = [
"https://btmet.com/",
"https://ext.to/",
]
# Not testable on github actions
github_restricted = [
"https://www.ygg.re/",
"https://extratorrent.st/",
"https://idope.se/",
"https://speed.cd/login",
]
# if os.getenv("GITHUB_ACTIONS") != "true":
test_websites.extend(github_restricted)
@pytest.mark.parametrize("website", test_websites)
def test_bypass(website: str):
"""
Tests if the service can bypass cloudflare/DDOS-GUARD on given websites.
This test is skipped if the website is not reachable or does not have cloudflare/DDOS-GUARD.
"""
test_request = httpx.get(
website,
)
@@ -39,12 +36,23 @@ def test_bypass(website: str):
response = client.post(
"/v1",
json=LinkRequest(url=website, maxTimeout=30, cmd="request.get").model_dump(),
json={
**LinkRequest.model_construct(
url=website, max_timeout=30, cmd="request.get"
).model_dump(),
# "proxy": "203.174.15.83:8080",
},
)
assert response.status_code == HTTPStatus.OK
def test_health_check():
"""
Tests the health check endpoint.
This test ensures that the health check
endpoint returns HTTPStatus.OK.
"""
response = client.get("/health")
assert response.status_code == HTTPStatus.OK
Generated
+1451
View File
File diff suppressed because it is too large Load Diff