Compare commits

...

439 Commits

Author SHA1 Message Date
Fijxu 1e4925333b Deprecation notice loasjdksadsaddsa 2023-11-10 17:36:41 -03:00
Fijxu 060d2be689 Merge remote-tracking branch 'librey/main' into librey 2023-10-14 13:56:59 -03:00
Ahwx bfce38b6dc
feat(README.md): adding @Ahwxorg's OVH instance 2023-10-05 11:11:26 +02:00
Ahwx bb3718b2d7
chore(instances.json): remove `lx.vern.cc` as vern seems to be down 2023-10-05 11:08:37 +02:00
Fijxu 517839ae24 Merge remote-tracking branch 'librey/main' into librey 2023-09-29 02:33:28 -03:00
Ahwx 4e363c3500
fix: onion address for supernets (merge pull request #60 from codedipper/add-instances4)
supernets onion
2023-09-28 23:15:35 +02:00
Revvy 420949d4b7
supernets onion 2023-09-25 20:13:45 -04:00
Ahwx 217601aa49
feat: add/remove instances (merge pull request #56 from codedipper/add-instances3)
add/remove instances
2023-09-22 23:59:10 +02:00
Revvy b01219c8c6
add/remove instances 2023-09-21 20:52:38 -04:00
Ahwx d92989ed6c
feat: adding instance (merge pull request #53 from codedipper/add-instances2)
Add librex.supernets.org
2023-09-17 12:06:43 +02:00
Revvy 6867fcceb6
librex.supernets.org 2023-09-16 20:40:44 -04:00
Ahwx 0cd23c8e0d
feat: adding pulldown (merge pull request #50 from davidovski/language_dropdown)
Language selection dropdown
2023-09-09 19:46:12 +02:00
Ahwx d64b917077
fix: typo so duckduckgo works again (merge pull request #51 from davidovski/fix_duckduckgo)
Fix typo in duckduckgo
2023-09-09 16:04:23 +02:00
davidovski 049272c043 Fix typo in duckduckgo 2023-09-09 14:45:29 +01:00
davidovski e99670628d Use languages list to generate dropdown in settings 2023-09-09 14:28:04 +01:00
davidovski 6a1dea2581 Use language list for wikipedia 2023-09-09 14:07:34 +01:00
Ahwx d0499bafc0
feat(instances.json): adding @Ahwxorg's 2nd instance in france 2023-09-07 18:18:07 +02:00
Ahwx 5512e5da80
feat(auto_updater.sh): adding auto updater like LibreX used to have 2023-09-07 17:59:39 +02:00
Ahwx 5e2cc89816
fix: edit domain for benike.me (merge pull request #46 from drinkmonster/main)
edit domain
2023-09-07 00:56:49 +02:00
Ahwx efe057ac03
fix: moving logic to printing results (merge pull request #48 from davidovski/frontend_passing)
Moving logic to printing results
2023-09-07 00:55:05 +02:00
davidovski fa07f21f56 Move base_url parsing to print results 2023-09-06 12:23:59 +01:00
davidovski c70436b257 Move checking for frontends to printing instead of parsing 2023-09-06 12:07:38 +01:00
Berényi Bence f79e4f5026
edit domain 2023-09-06 08:47:12 +02:00
Ahwx c9ff9a0de8
feat(instances.json): add librey.baczek.me 2023-09-05 23:42:06 +02:00
Ahwx 2fc6bfe7af
feat(xmr-ahwx.png): adding ahwx' xmr' qr code 2023-09-05 15:50:00 +02:00
Ahwx 43234d6d87
feat(donate.php): adding xmr and qr for ahwx 2023-09-05 15:49:05 +02:00
Ahwx 0e30c8a93a
ci: adding support for multi-arch docker images (merge pull request #44 from mentos1386/patch-1)
ci: multi-arch docker images
2023-09-04 12:21:52 +02:00
Tine Jozelj 3e00dbd788
ci: multi-arch docker images
based on https://docs.docker.com/build/ci/github-actions/multi-platform/
2023-09-03 23:38:39 +02:00
Ahwx 530fbf5a26
style: minor ui improvements on donate page (merge pull request #43 from osarthak/update-donate)
update donate ui && fix footer links margin
2023-09-03 23:07:57 +02:00
Ahwx 66b66a52f7
fix: update instances list to redirect to official instances which generate from json (merge pull request #42 from codedipper/update-readme)
update instance list on readme
2023-09-03 23:06:45 +02:00
Ahwx 97203e72a8
feat: adding more flags to example docker-compose.yaml (merge pull request #41 from codedipper/compose-fix)
update default compose
2023-09-03 23:03:50 +02:00
osarthak 7d260df145 update donate ui && fix footer links margin 2023-09-03 17:56:18 +05:30
Revvy 158a7e0296
more changes 2023-09-02 22:56:39 -04:00
Revvy 30a8802eae
more changes 2023-09-02 22:54:49 -04:00
Revvy aa9f46dbbd
more changes 2023-09-02 22:51:54 -04:00
Revvy ea51467714
update instance list on readme 2023-09-02 22:45:27 -04:00
Revvy ee9f7d8447
update default compose 2023-09-02 22:23:23 -04:00
Ahwx 9361117f09
fix(docker-compose.yml): Add "docs" for Watchtower 2023-09-02 22:33:48 +02:00
Ahwx 2ed2370219
fix(instances.json): fixing order; feat: add watchtower to automatically pull newest image upon release (merge pull request #38 from codedipper/watchtower)
watchtower, fix instances.json order
2023-09-02 22:31:43 +02:00
Revvy 94de6a116b
typo in docker readme 2023-09-02 00:15:52 -04:00
Revvy f73a3f0ff9
fix instances.json order 2023-09-02 00:13:52 -04:00
Revvy 5a8672c150
add watchtower 2023-09-02 00:12:13 -04:00
Ahwx 514c290b46
chore: update instances; feat: docker stuff (merge pull request #37 from codedipper/man)
Update instances, Update Docker configs & docs
2023-09-01 23:08:48 +02:00
Revvy 0c7224a67a
some security headers 2023-09-01 08:19:15 -04:00
Revvy 90f07bceeb
fix default for cache ttl docker 2023-08-31 10:40:14 -04:00
Revvy 5e37afdd12
add cache ttl to docker 2023-08-31 10:39:04 -04:00
Revvy f718c36e45
update cocker configs and docs 2023-08-31 10:22:55 -04:00
Revvy 123b3bfcd4
update instances 2023-08-31 10:18:38 -04:00
Ahwx b8869a217e
feat(SECURITY.md): add something like a security policy 2023-08-31 14:09:39 +02:00
Ahwx dd8df71abd
feat: cache results to combat spammers (merge pull request #34 from davidovski/results_caching)
Results caching
2023-08-31 14:07:17 +02:00
Ahwx 68b5de6bd6
fix: some minor css padding; feat: add instance (merge pull request #36 from whoisYoges/CastorFixes)
Fixed Some CSS and Added a New Instance
2023-08-31 10:41:29 +02:00
Castor 7c31b07811
`Add:` instance to readme 2023-08-31 10:49:09 +05:45
Castor 9f75502627
`Add:` a new libreY instance 2023-08-31 10:25:20 +05:45
Castor 407a4dcb74
`Fix:` indentation for search settings. 2023-08-31 10:23:36 +05:45
Castor 063b6ea608
`Updated:` spacing between instance list and footer. 2023-08-31 10:12:23 +05:45
Ahwx 6c5474c93f
chore: update instances (merge pull request #35 from codedipper/add-instances3)
add/remove instances
2023-08-30 23:18:26 +02:00
davidovski 4a98228a90 Properly remove google request if on cooldown 2023-08-30 22:06:36 +01:00
Ahwx a9ead078ea
fix: docker stuff (merge pull request #33 from nohoster/docker-update)
Docker update
2023-08-30 23:01:03 +02:00
davidovski 37f77e5e8d set default language 2023-08-30 21:47:22 +01:00
Ahwx 0f50470821
fix: ads sometimes show up with ddg (merge pull request #32 from codedipper/ad-ddg-fix)
fix when ads sometimes show up with ddg
2023-08-30 22:46:08 +02:00
davidovski bfe699d5ad Do not throw error if duckduck go query fails 2023-08-30 21:40:30 +01:00
davidovski f8f30323ee do not avoid request if cached 2023-08-30 21:19:50 +01:00
davidovski 01fe983009 curl follow location by default 2023-08-30 21:06:09 +01:00
davidovski 73c5b4b98e fix not respecting cooldown 2023-08-30 21:00:00 +01:00
davidovski 9d431ae8c0 Actually exec fallback requests 2023-08-30 20:50:23 +01:00
Revvy dd41f423ac
add/remove instances 2023-08-30 14:18:49 -04:00
davidovski ad747d51a1 Make fallback work when no results found 2023-08-30 18:11:17 +01:00
davidovski a33f26a638 Add no instances message 2023-08-30 17:50:56 +01:00
davidovski 12f02198f9 Add no results messages 2023-08-30 17:26:34 +01:00
davidovski a00da6eb65 Fix typo 2023-08-30 16:07:35 +01:00
davidovski aaf111abf7 Always do no fallback on fallback requests 2023-08-30 16:05:31 +01:00
davidovski 4da025948b fix missing $ 2023-08-30 14:00:44 +01:00
davidovski 4488200d22 Add ttl on caches 2023-08-30 13:58:47 +01:00
davidovski a8c4f4e609 Use caching for all requests 2023-08-30 13:50:01 +01:00
nohoster efce4e387e fixed var 2023-08-29 20:01:34 -06:00
Revvy 46fe062bd3
fix when ads sometimes show up with ddg 2023-08-29 21:58:27 -04:00
nohoster f9430475bf Updated and simplified the docker building setup 2023-08-29 19:49:11 -06:00
Fijxu 4bbd44cb35 Merge remote-tracking branch 'librey/main' into librey
lolxdxdxddddddddddddddddddddddddddddddddddddddd
2023-08-29 21:38:06 -04:00
Ahwx 8f9b9803f2
fix: vuln within image parsing (merge pull request #31 from codedipper/nibH3YzJ)
irresponsible disclosure
2023-08-29 20:17:24 +02:00
Revvy 33240c4d21 fix high-severity vulnerability 2023-08-29 14:07:50 -04:00
Ahwx 3b23c4d099
fix: docker attributes variable format (merge pull request #30 from nohoster/patch-1)
Fix variable format.
2023-08-29 19:46:40 +02:00
Ahwx d64ce8f4dd
fix: unable to create organisation package (merge pull request #29 from BluenationStudio/main)
fix unable to create organization package
2023-08-29 19:45:02 +02:00
nohoster a2f94fb0ca
Fix variable format.
The format was wrong, it had a misplaced "}". It should be fine now.
2023-08-29 14:04:15 +00:00
Jakub Doboš 1330453370
fix unable to create organization package 2023-08-29 10:09:18 +02:00
Ahwx 1c4e9eafde
feat: adding docker stuff (merge pull request #24 from BluenationStudio/main)
Start building docker images from the repo on ghcr
2023-08-29 10:00:17 +02:00
Ahwx 79e61a792b
feat: adding librex.nohost.network (merge pull request #28 from nohoster/main)
Updated my instance to LibreY
2023-08-29 09:58:58 +02:00
nohoster 08bb5b5d49
Update instances.json 2023-08-29 01:53:33 +00:00
nohoster da95ec8c9e
Update README.md 2023-08-29 01:51:35 +00:00
Ahwx 07588b7d73
feat: adding instance & fix: formatting (merge pull request #27 from codedipper/main)
add instance, fix formatting
2023-08-29 01:16:50 +02:00
Revvy 304c3738cc add instances, fix formatting 2023-08-28 18:46:29 -04:00
Ahwx 7f61a54141
fix: some padding (merge pull request #26 from osarthak/update)
fixed active sub-search-button, did-you-mean, small footer
2023-08-29 00:35:38 +02:00
osarthak e6c0bfda33 fixed sub-search-button border padding, did-you-mean on mobile, smaller footer 2023-08-27 15:55:17 +05:30
Jakub Doboš 06ee3f06e8 build docker image 2023-08-27 00:04:26 +02:00
Ahwx 3ae47a1cfc
feat: load balancing and cooldowns (merge pull request #19 from davidovski/load_balancing)
Load balancing and Cooldowns
2023-08-26 11:06:24 +02:00
davidovski 98707900bf Fix language config variable not working 2023-08-26 00:42:44 +01:00
davidovski a87b78095f Fix missing quote in docker build script 2023-08-25 23:15:17 +01:00
davidovski ccc0d78dee Fixed incorrect use of function_exists 2023-08-25 19:09:06 +01:00
davidovski 11e11192a4 Do not persist if apcu is not installed 2023-08-25 19:03:11 +01:00
davidovski 8bae58c2b2 Add php8-apcu to dependencies 2023-08-25 18:06:12 +01:00
davidovski b8047b2982 add default for request_cooldown 2023-08-25 17:53:59 +01:00
davidovski 039e549d4c Change default timeout to 25 minutes 2023-08-25 17:48:45 +01:00
davidovski f50022f780 added request cooldowns for google 2023-08-25 17:39:08 +01:00
davidovski 0fd041a353 Add timeouts for failing instances 2023-08-25 16:23:53 +01:00
Ahwx 2c36d28a2f
refactor(*): everything (merge pull request #18 from davidovski/the_refactor)
Major Refactor
2023-08-25 14:45:49 +02:00
davidovski a7d1836eff Fixed fallback not occuring when special result 2023-08-25 11:36:19 +01:00
davidovski 723887bfc0 Fix typo in variable name for instances 2023-08-25 00:12:19 +01:00
davidovski 04e0183d79 Fix missing arg error 2023-08-25 00:10:03 +01:00
davidovski 036b10efe7 Add hl back into google query 2023-08-25 00:03:12 +01:00
davidovski 508ac0c576 Use cookie frontend over config frontend 2023-08-24 15:45:45 +01:00
davidovski 5ce0f2ccd0 fix video and image search 2023-08-24 03:57:11 +01:00
davidovski 1b694e0882 Fix frontends being parsed from config 2023-08-23 10:55:51 +01:00
davidovski 8ede57f4f4 fix issue with not actually using duckduckgo 2023-08-23 02:32:47 +01:00
davidovski 1e15006067 Remove duplicate nfb parameter 2023-08-23 00:54:10 +01:00
davidovski 14cdccb83f add theme to query parameter 2023-08-23 00:51:23 +01:00
davidovski 1b898c6614 fallback on all queries 2023-08-23 00:46:21 +01:00
davidovski 649b0065e3 make some options editable via url parameters 2023-08-23 00:46:21 +01:00
davidovski b3693add93 use correct parameter for search query 2023-08-23 00:46:21 +01:00
davidovski 89c957e92c Make settings.php use opts 2023-08-23 00:46:21 +01:00
davidovski 6c253bcb47 put all settings in single "opts" array 2023-08-23 00:46:21 +01:00
davidovski 4941a6aa58 use engine request for torrent search 2023-08-23 00:46:21 +01:00
davidovski 0bd726d897 moved files 2023-08-23 00:46:21 +01:00
davidovski f4a80135bd ensure url remaisn the same when switching types 2023-08-23 00:46:21 +01:00
davidovski 34fdaac058 use same logic for search and api 2023-08-23 00:46:21 +01:00
davidovski 19627c94c9 add bittorrent and tor to be enginerequest types 2023-08-23 00:46:21 +01:00
davidovski 74da63dab2 Make search categories type of request 2023-08-23 00:46:21 +01:00
davidovski f59f94fdd5 include different print and fetch functions for search 2023-08-23 00:46:21 +01:00
davidovski fd93a0e154 Add EngineRequest class 2023-08-23 00:46:21 +01:00
Fijxu bd19b6cbcf Merge remote-tracking branch 'librey/main' into librey 2023-08-21 13:27:14 -04:00
Ahwx 85ef67c798
chore(instances.json): france -> netherlands for search.ahwx.org 2023-08-21 15:08:03 +02:00
Ahwx 28aed7d61e
chore(readme.md): france -> netherlands for search.ahwx.org 2023-08-21 15:07:04 +02:00
Ahwx dbbec941da
Merge pull request #17 from codedipper/add-instances2
add/remove instances
2023-08-21 15:05:49 +02:00
Revvy 6d657deb2f update retro-hax <3 2023-08-21 08:23:02 -04:00
Revvy 476fcdcd43 add/remove instances 2023-08-20 07:40:17 -04:00
Ahwx 82ac92a98b
fix: gateway timeout on calling fallback instances (merge pull request #16 from davidovski/fix_fallback)
Fix Gateway Timeout on fallback
2023-08-20 12:21:38 +02:00
davidovski 9ae13f41ad add fallback to duckduckgo engine 2023-08-20 01:52:29 +01:00
davidovski 9980f3a9e7 use prefered engine on api 2023-08-20 00:34:22 +01:00
Ahwx e2527200c9
chore(config.php.example): update user agent 2023-08-19 23:05:21 +02:00
Ahwx 5f8bc14d73
fix(config.php.example): hotfix for instance_fallback 2023-08-19 22:07:56 +02:00
Ahwx a6782f81df
chore: update instances (merge pull request #14 from codedipper/add-instances)
update instances
2023-08-19 21:59:15 +02:00
davidovski ae9d706a4b extend number of tries for fallback 2023-08-19 20:16:43 +01:00
davidovski 8e8c718237 fix error when displaying no text results 2023-08-19 19:51:34 +01:00
davidovski d556296c5a add no fallback option to requests 2023-08-19 19:23:54 +01:00
Revvy a8661c3de6 update instances 2023-08-19 10:56:56 -04:00
Ahwx 9296cb4600
fix: passing quotation marks to google searches (merge pull request #13 from davidovski/quote_searches)
Fix passing quotation marks to google searches
2023-08-19 11:49:35 +02:00
davidovski 423de89bd8 Fix passing quotation marks to google searches 2023-08-19 01:54:48 +01:00
Ahwx 903ec51483
feat: changing instances and fix typo (merge pull request #12 from codedipper/main)
add/remove instances, fix typo
2023-08-18 22:38:04 +02:00
Revvy f5579c1110 changed domain 2023-08-18 10:52:37 -04:00
Revvy 677db09535 fix order god i'm stupid 2023-08-18 08:47:18 -04:00
Revvy 2111fda8b8 zzls and bloatcat <3 2023-08-18 08:43:44 -04:00
Revvy 99a1fcb9c8 space 2023-08-18 08:29:47 -04:00
Revvy 1de1ad330c change flag 2023-08-18 08:29:27 -04:00
Revvy fa50117b9f change readme 2023-08-18 08:27:58 -04:00
Fijxu 7f5950a5ff Merge remote-tracking branch 'librey/main' into librey 2023-08-18 01:47:22 -04:00
Revvy ab1141f647 change order 2023-08-17 21:47:44 -04:00
Revvy b19d95d5f5 add protocol 2023-08-17 21:30:45 -04:00
Revvy bab77bd50c hnhx/librex#256 hnhx/librex#253 2023-08-17 21:29:45 -04:00
Revvy 127ab3d543 add/remove instances, fix typo 2023-08-17 20:59:26 -04:00
Ahwx be59098abd
fix: docker shit, wikipedia vuln pointed out via email by Yufan You (merge pull request #9 from codedipper/main) 2023-08-17 23:59:48 +02:00
Ahwx 91ecdf64c2
feat: add "Did you mean?" to LibreY (merge pull request #8 from davidovski/did_you_mean
Live saving shit right here!
2023-08-17 23:51:53 +02:00
Ahwx 3ef3b31973
feat: add instances page (merge pull request #7 from davidovski/instances_list)
Instances list
2023-08-17 23:48:07 +02:00
Revvy d0b9411ad3 update docker-compose.yml for new docker changes 2023-08-17 16:14:03 -04:00
Revvy d3cea672a5 CONFIG_INSTANCE_FALLBACK 2023-08-17 16:12:04 -04:00
Revvy ee377e514e choosing engine support docker 2023-08-17 15:48:12 -04:00
Revvy 0ac3cd2e06 CURLOPT_PROXYTYPE docker 2023-08-17 15:15:11 -04:00
Revvy 3b5e95ff60 CONFIG_GOOGLE_NUMBER_OF_RESULTS docker 2023-08-17 15:07:17 -04:00
Revvy edbc23f124 Thank you random Chinese student! 2023-08-17 14:27:25 -04:00
davidovski 78c774bc3b Style did you mean text 2023-08-17 14:33:26 +01:00
davidovski d409d61a6b Add did you mean to results output 2023-08-17 14:33:26 +01:00
davidovski b7e0ed8742 Add instances.php to footer 2023-08-16 22:27:48 +01:00
davidovski b20a57572b Add instances list 2023-08-16 22:26:31 +01:00
Ahwx 3687c4b40f
fix(readme.md): add revvy 2023-08-15 21:23:09 +02:00
Ahwx b06a07a25d
fix(instances.json): add revvy and libre.me 2023-08-15 21:22:25 +02:00
Ahwxorg 171a18e52a
feat(readme.md): add instances list, along with other minor changes in the readme 2023-08-15 20:54:23 +02:00
Ahwxorg 70dff6cb1e
Merge pull request #6 from codedipper/main
fix ddg search when zero-click (wikipedia) result is present
2023-08-15 18:52:50 +02:00
Revvy 6d78488f65 fix ddg search when zero-click result is present 2023-08-14 20:45:02 -04:00
Ahwxorg 3d876fa097
revert: see issue #4 2023-08-14 15:45:09 +02:00
Ahwxorg 21057dbe3f
fix: try to use googlebot as a user agent to try to fix rate limiting 2023-08-14 14:31:06 +02:00
Ahwxorg 1054b5bd0f
Merge pull request #3 from codedipper/main
change to Y in logo, remove librarian as it is no longer maintained
2023-08-14 13:21:02 +02:00
Revvy 2f2dc396c4 change to Y in logo, remove librarian as it is no longer maintained 2023-08-13 04:21:22 -04:00
Ahwxorg 2ca9603121
feat: adding fallback to other instances if rate limiting happens, PR from davidovski/librex.
Fallback to other librex instances
2023-08-12 02:12:37 +02:00
Fijxu 2f87e05d6e Merge branch 'librex_fallback' 2023-08-11 01:33:04 -04:00
Fijxu d4e467c9a1 Merge branch 'mmatteini-fix-save-settings' 2023-08-11 01:25:45 -04:00
Michele d2eb12c96f Fixed additional issues with checkboxes and reset. 2023-08-09 17:58:48 +02:00
Michele 0738ecab20 Fixed a bug causing settings page to stop working after saving once. 2023-08-09 15:27:54 +02:00
Ahwxorg 078d4bf4b3
feat: bringing stuff over from regular LibreX (Merge pull request #2 from codedipper/main) 2023-08-08 19:02:38 +02:00
Revvy 4c9f31d2d4 update ddg bangs, fix hnhx/librex#257 2023-08-07 18:02:12 -04:00
Revvy bc0881c663 hnhx/librex#252 2023-08-07 17:45:30 -04:00
Revvy 678a625696 hnhx/librex#259 2023-08-07 17:42:45 -04:00
Revvy 6241c2491d #234 from hnhx/librex 2023-08-07 17:39:53 -04:00
davidovski 05a52f5f62 Filter reqests to self on fallback 2023-08-07 18:47:01 +01:00
davidovski f737730e40 Copy settings cookies when making a call to other instance 2023-08-07 18:47:01 +01:00
davidovski 19aef64bab Don't accept a fallback instance with a single result 2023-08-07 18:47:01 +01:00
davidovski 4aea931839 Remove automtic redirection setting 2023-08-07 18:47:01 +01:00
davidovski b97c4daac7 Try different instance if fallback fails 2023-08-07 18:47:01 +01:00
davidovski e4fe769c10 Use librex as fallback search engine 2023-08-07 18:47:01 +01:00
davidovski 34feaa27ea Fix checkboxes not unchecking when saving 2023-08-07 18:47:01 +01:00
davidovski cce8aca6e5 Add disable automatic redirection setting 2023-08-07 18:46:59 +01:00
davidovski b783acb506 Filter reqests to self on fallback 2023-08-07 18:27:54 +01:00
davidovski 3f2cd3fdb3 Copy settings cookies when making a call to other instance 2023-08-07 17:01:12 +01:00
davidovski 7214e4e729 Don't accept a fallback instance with a single result 2023-08-07 15:33:57 +01:00
davidovski 4349ef54ea Remove automtic redirection setting 2023-08-07 15:13:29 +01:00
davidovski feef1f4525 Try different instance if fallback fails 2023-08-07 15:05:41 +01:00
davidovski eecaae4a03 Use librex as fallback search engine 2023-08-07 14:54:25 +01:00
davidovski b0f449671d Fix checkboxes not unchecking when saving 2023-08-06 13:27:40 +01:00
davidovski ff1db195d1 Add disable automatic redirection setting 2023-08-06 13:09:06 +01:00
Ahwx 40d14465ad chore(*): renaming the entirity of LibreY (2) 2023-08-02 16:28:24 +02:00
Ahwx c3b2444eea chore(*): renaming the entirity of LibreY 2023-08-02 16:18:21 +02:00
Ahwxorg 6a71de282c
feat(engines/google/text.php): remove random redirection because of privacy concerns 2023-08-02 14:00:32 +02:00
Ahwxorg c592817c2b
Update README.md (2) 2023-08-02 13:53:28 +02:00
Ahwxorg bcc8358b94
Update README.md 2023-08-02 13:51:51 +02:00
Fijxu e18baedc45 Merge remote-tracking branch 'upstream/main' 2023-06-29 22:15:16 -04:00
hnhx b5a9f12df9
Merge pull request #250 from rafalohaki/main
Update Version Alpine/PHP
2023-06-24 08:52:57 +00:00
hnhx e11a20cedf
Merge pull request #235 from amogusussy/fix-rutor
Fix rutor's size and seed/leech number.
2023-06-24 08:51:30 +00:00
hnhx ee3ac90b39
Merge pull request #236 from youshitsune/main
add search.decentrala.org
2023-06-24 08:48:32 +00:00
hnhx 0bdd6f9c57
Merge pull request #237 from GospodinHoroshiy/main
Redirect to random instance if google is ratelimiting
2023-06-24 08:46:10 +00:00
rafalohaki e2eead1ce0 Update Version:
Alpine 3.17->3.18
php7->php8
2023-06-23 13:51:40 +00:00
hnhx a75a233fbd
Merge pull request #229 from codedipper/main
add ~vern instance (again), fix spaceint instance, stackexchange in anonymousoverflow
2023-06-16 10:22:04 +00:00
Revvy 5b800fbdf1
Merge branch 'main' into main 2023-06-16 10:18:17 +00:00
gospodin e03b930386 moved to redirect earlier, fixed formatting issues 2023-06-11 03:47:19 +03:00
gospodin 7559bc8101 Redirect to random instance if google is ratelimiting 2023-06-10 19:53:58 +03:00
youshitsune b135467fcc add search.decentrala.org 2023-06-08 11:04:49 +02:00
amogusussy bb5c370205 fix rutor 2023-06-04 16:08:05 +01:00
Fijxu 7c9977fa3f Merge remote-tracking branch 'upstream/main' 2023-06-01 23:54:56 -04:00
hnhx b8817a6e28
removed dead instances (json) 2023-05-31 15:46:58 +00:00
hnhx a4b68eac09
removed dead instances 2023-05-31 15:45:39 +00:00
hnhx 799fc5b0d7
Merge pull request #228 from dyoxin/main
Add instance
2023-05-31 15:36:27 +00:00
hnhx b4a009b2ee
Merge pull request #230 from Fijxu/main
[librex.zzls.xyz] Update I2P address.
2023-05-31 15:28:51 +00:00
hnhx b300235410
Merge pull request #233 from ReprovedC0medown1nch1ng/patch-1
Added instance librex.nohost.network
2023-05-31 15:27:26 +00:00
Revvy b7776f0c7c stackexchange support with anonymousoverflow 2023-05-28 17:47:35 -04:00
ReprovedC0medown1nch1ng 413b14f8d1
Update instances.json
Fixed missing comma
2023-05-26 14:05:24 +00:00
ReprovedC0medown1nch1ng a1c636bc5a
Added librex.nohost.network to json.instances 2023-05-26 01:14:13 +00:00
ReprovedC0medown1nch1ng 9a2bf7b88c
Added instance librex.nohost.network
Added my instance librex.nohost.network at the bottom
2023-05-25 19:35:29 +00:00
Revvy f3b9badfbc spaceint instance 2023-05-21 10:50:53 -04:00
Fijxu f22336e367 Update I2P address. 2023-05-21 00:08:05 -04:00
Revvy 81df7ba3ed ~vern instance 2023-05-18 21:54:30 -04:00
dyoxin c976e3e3fd Add instance 2023-05-17 22:50:24 -04:00
Fijxu eb5f6c0f32 Merge remote-tracking branch 'upstream/main' 2023-05-05 12:21:44 -04:00
hnhx d6954a125f
Merge pull request #219 from codedipper/main
change clearnet domain for my instance
2023-05-04 08:38:47 +02:00
Revvy 972d690064 change clearnet domain for my instance 2023-05-03 20:33:59 -04:00
hnhx 6d6a1ecd3e
Merge pull request #218 from Hukasx0/main
Fixed 'no space between attributes'
2023-05-02 20:41:42 +02:00
Hubert Kasperek 88df13340a
Changed space placement to remove unnecessary space when condition is not met 2023-05-02 19:40:30 +02:00
Hubert Kasperek 870ef39b8c
Fixed 'no space between attributes'
Found by the HTML validator
2023-05-02 19:07:16 +02:00
hnhx 1346e9fcc1
removed a dead instance from the json as well 2023-05-01 08:15:24 +00:00
hnhx e3663f996e
removed a dead instance 2023-05-01 08:14:04 +00:00
hnhx b0ce09abbd
Merge pull request #210 from codedipper/main
gist support with gothub, goodreads to biblioreads
2023-05-01 09:45:08 +02:00
hnhx a7b96cd89f
Merge pull request #217 from Hukasx0/main
Added two new themes: ubuntu and tokyo_night
2023-05-01 09:41:24 +02:00
hnhx fc0e4eca8f
Merge pull request #215 from nik012003/main
Make opensearch.xml location relative
2023-05-01 09:40:47 +02:00
Hukasx0 e29fe84078 Colors have been slightly modified 2023-04-30 21:31:40 +02:00
Hukasx0 3526040b5d Added two new themes: ubuntu and tokyo_night 2023-04-30 18:16:58 +02:00
Nicola Guerrera 2b33116fe0 Make openserach.xml location relative 2023-04-30 14:56:55 +02:00
Nicola Guerrera ffd6d56035
Merge pull request #1 from hnhx/main
Update LibreX
2023-04-30 14:55:20 +02:00
Revvy 398961cd3d goodreads => biblioreads 2023-04-24 19:19:46 -04:00
Revvy 50467f2a9c gist support with gothub 2023-04-22 17:07:25 -04:00
hnhx eaa76b3cfa
Merge pull request #199 from codedipper/main
Remove bibliogram, add suds
2023-04-17 10:25:12 +02:00
hnhx 227ff16e67
Merge pull request #206 from rafalohaki/main
Update sukebei.php
2023-04-17 10:23:29 +02:00
hnhx 08c3cf520e
Merge pull request #209 from drinkmonster/main
added my instance
2023-04-17 10:22:20 +02:00
monster energy 96f47b9600
also added to instances.json 2023-04-13 09:59:05 +02:00
monster energy ef32e900eb
added my instance 2023-04-13 09:56:47 +02:00
Revvy b52b2aa4da fix original_name 2023-04-09 18:37:22 -04:00
rafalohaki f34549b972
Update sukebei.php
Modified the get_sukebei_results() function to handle cases where the name and magnet nodes are null or do not exist.
Added conditional statements to check if the name and magnet nodes exist before attempting to access their properties, in order to prevent null errors and warnings.
Added empty string as the default value for name and magnet variables in case their corresponding nodes are null or do not exist.
Removed the use of deprecated functions explode() and htmlspecialchars() in the code.
No longer accessing the textContent property of DOMXPath::evaluate().
2023-04-09 01:24:39 +02:00
rafalohaki c13228e240
Update sukebei.php
textContent, XPath expression fix
2023-04-09 01:19:53 +02:00
rafalohaki 9e24214000
fix librex image pull access
fixed: pull access denied for librex
2023-04-09 00:52:38 +02:00
hnhx 52ae847748
updated the instances in the json file as well 2023-04-08 09:35:49 +00:00
hnhx 4826071262
removed dead instances, added new ones 2023-04-08 09:31:08 +00:00
hnhx 49b846c67a
Merge pull request #202 from Ahwxorg/main
change tor address since i switched servers and am an idiot
2023-04-08 09:08:49 +00:00
Livia 92898c06be
change tor address since i switched servers and am an idiot 2023-04-05 09:50:56 +02:00
Revvy 2283a4fee8 suds => snopes 2023-03-26 20:10:15 -04:00
Revvy e4178913bd remove bibliogram 2023-03-26 19:51:29 -04:00
hnhx d04315009e added number of results option, fixed a theme name 2023-03-24 09:39:52 +01:00
hnhx 435af0af0b
Merge pull request #197 from tuzu128/main
Added Catppuccin Theme
2023-03-24 09:22:08 +01:00
TheTuzu d3c33dc6e4 Added Catppucin theme 2023-03-23 18:34:32 +01:00
Fijxu ffc5e556bc Add donation link 2023-03-17 15:09:46 -03:00
hnhx d8dd8325f2
Merge pull request #189 from Wint3rmute/add-librex-baczek-me
Add librex.baczek.me instance
2023-03-17 16:32:59 +01:00
hnhx 23964f0d9c
Merge pull request #192 from Wint3rmute/improve-docker-build-caching
Improve docker build caching
2023-03-17 16:32:03 +01:00
wint3rmute 19a02e1166 Improve docker build caching 2023-03-17 15:13:21 +01:00
wint3rmute 523edfa5df Add librex.baczek.me instance 2023-03-15 21:02:07 +01:00
hnhx 35d9a21c5d fixed wikipedia bang, added tor instance for search.ahwx.org 2023-03-14 12:12:47 +01:00
hnhx a24708edec
Merge pull request #179 from juniorbotelho/refactor/solve-search-errors
resolves a number of bugs, both in docker and master branch
2023-03-14 06:39:42 +01:00
Junior L. Botelho (JLB) 07ad6732cf
refactor: remove .vscode debug folder 2023-03-13 20:21:12 -03:00
Junior L. Botelho (JLB) ed06bb7080
refactor: remove invalid value of CURLOPT_ENCODING option 2023-03-13 18:44:20 -03:00
Junior L. Botelho (JLB) b29d7e0d91
refactor: keep vscode debug configuration 2023-03-13 18:44:03 -03:00
hnhx ff6358952f
Merge pull request #187 from codedipper/main
add revvy.de instance
2023-03-13 21:53:10 +01:00
Revvy f37467dafe
add to instances.json 2023-03-13 04:34:30 +00:00
Revvy b6ee16e4f4
add revvy.de instance 2023-03-13 04:30:13 +00:00
Junior L. Botelho (JLB) 395f3640e5
refactor: solve torrent and tor search errors 2023-03-08 18:46:23 -03:00
Junior L. Botelho (JLB) 0ef03edcb1
refactor: solve error request due to invalid request protocol 2023-03-07 18:35:16 -03:00
Junior L. Botelho (JLB) a25893b53d
feat: add 'docker-compose.yml' template for easy-to-use 2023-03-07 18:34:03 -03:00
Junior L. Botelho (JLB) 1bcd0ec358
refactor: solve config errors of dockerfile and php configuration 2023-03-07 18:33:19 -03:00
hnhx 62799b3b5d
Merge pull request #176 from nik012003/patch-1
Updated sesu.cc instance
2023-03-04 10:30:44 +01:00
Nicola Guerrera a6ea568c98
Updated sesu.cc instance 2023-03-03 20:03:26 +01:00
Junior L. Botelho (JLB) 6c38e14510
refactor: solve invalid quotes params 2023-02-27 16:35:06 -03:00
hnhx 8d227132fe
Merge pull request #175 from Z3r0ish/patches
Added instance
2023-02-26 13:25:45 +01:00
root bf72b73589 Added instance 2023-02-25 00:03:12 +00:00
hnhx 9a7d9eb084
Merge pull request #170 from juniorbotelho/feat/wikipedia-language-settings
add wikipedia language option in /settings route
2023-02-21 12:53:01 +00:00
hnhx 1b3012760d
Merge pull request #172 from beucismis/main
Update frontends project_url
2023-02-21 12:52:39 +00:00
beucismis aaa0ae4468 Update frontends project_url 2023-02-21 15:33:25 +03:00
Junior L. Botelho (JLB) 659c8116c9
feat: add wikipedia.php language cookie config 2023-02-21 09:06:50 -03:00
Junior L. Botelho (JLB) 4194f9ae57
feat: add wikipedia language option in /settings route 2023-02-19 09:38:26 -03:00
hnhx 5dfe95d299
Merge pull request #169 from juniorbotelho/feat/wikipedia-language-support
adds language support for Wikipedia results and revert implementation of docker logs using 'docker logs -f librex'
2023-02-19 11:54:52 +00:00
Junior L. Botelho (JLB) acddc5faf1
revert(logs): remove nginx logs forward for privacy purposes 2023-02-19 07:41:51 -03:00
Junior L. Botelho (JLB) d56c3632b1
refactor: fix codebase consistency "wikipedia_language" => "en" 2023-02-19 07:37:02 -03:00
Junior L. Botelho (JLB) 76f98f8960
refactor(docker): if omits the Wiki language env, then use the lang of google search engine 2023-02-18 14:37:02 -03:00
Junior L. Botelho (JLB) 45a9463f0a
refactor: add info about WIKIPEDIA environment to docker readme 2023-02-18 14:23:04 -03:00
Junior L. Botelho (JLB) 4a4fbcf660
refactor: add info about WIKIPEDIA environment to docker readme 2023-02-18 14:20:23 -03:00
Junior L. Botelho (JLB) 0208b8f738
feat: adds language support for Wikipedia results and implements 'docker logs -f librex' 2023-02-18 14:16:25 -03:00
hnhx 1efc101e30 fixed wikipedia url 2023-02-18 14:46:14 +01:00
hnhx f92f322439 removed redudant config require 2023-02-17 18:50:25 +01:00
hnhx 1a8257cf11 removed debug 2023-02-17 09:47:18 +01:00
hnhx a8645b7eb6 split the google language to site and results, now everything related to instances are defined in the config file 2023-02-17 09:44:03 +01:00
hnhx 04ae09bd54
moved the docker related things to the wiki 2023-02-16 23:22:42 +00:00
hnhx 7aefbb2b9e
Merge pull request #165 from juniorbotelho/fix/docker-environments
fix(docker): fix typo "CONFIG GOOGLE LANGUAGE"
2023-02-16 23:18:00 +00:00
hnhx 67fc64b60e
Merge pull request #164 from jkumeboshi/patch-1
PHP error
2023-02-16 23:17:43 +00:00
Junior L. Botelho (JLB) 31ba753c79
fix(docker): fix typo "CONFIG GOOGLE LANGUAGE" 2023-02-16 16:42:54 -03:00
J.K.Umeboshi 4271c9f635
PHP error
when I save settings I get "Undefined variable: '$name' in /var/www/html/settings.php on line 26" message
I think that the correct variable name shall be $key
2023-02-16 12:35:04 +01:00
hnhx 689d31025e
Merge pull request #161 from juniorbotelho/docker
Add Docker to the project with emphasis on multi-configurations.
2023-02-12 22:49:25 +00:00
Junior L. Botelho (JLB) 15c26fffa6
chore: fix docker/README.md mistakes
chore: check if environment variables are fixed

chore: add most useful informations in readme file

chore: add table of environments in readmes
2023-02-12 17:38:08 -03:00
Junior Botelho d1845992e5
Merge branch 'hnhx:main' into docker 2023-02-12 20:13:42 +00:00
Junior L. Botelho (JLB) f80a585629
chore: fix docker/README.md mistakes 2023-02-12 17:11:02 -03:00
Junior L. Botelho (JLB) 0be3398071
chore: improves the README.md file from docker by adding more information 2023-02-12 17:06:00 -03:00
Junior L. Botelho (JLB) 377f9d00e3
chore: add readme for docker specifications 2023-02-12 16:19:22 -03:00
Junior L. Botelho (JLB) a0a3a904df
chore: add readme for docker specifications 2023-02-12 16:05:57 -03:00
Junior L. Botelho (JLB) 2706cf3eb0
chore: remove the php7-xml extension as it is not being used by the project 2023-02-12 15:04:59 -03:00
Junior L. Botelho (JLB) 8e65f0253a
this resolves the issue with a variable that was defined with the value '.com' when it should only be 'com' 2023-02-12 14:34:38 -03:00
Junior L. Botelho (JLB) 9c17401c66
revert: Removed the '@' symbol from line 187 in 'misc/tools.php' as it is not recommended to use error suppression 2023-02-12 13:54:42 -03:00
Junior L. Botelho (JLB) c1c401a5f9
chore: downgraded PHP from version 8 to version 7.4 for better compatibility 2023-02-12 13:39:32 -03:00
Junior L. Botelho (JLB) 449ec0dd7a
refactor: Removed the '@' symbol from line 187 in 'misc/tools.php' as it is not recommended to use error suppression 2023-02-12 13:36:47 -03:00
Junior L. Botelho (JLB) 8b2b8af183
chore: fixed an issue that occurred when nginx did not have permissions on the 'php-fpm8.sock' file 2023-02-12 13:35:16 -03:00
Junior L. Botelho (JLB) 36d8aeeb5b
chore: after running the 'docker run' command, the environment variables will now be effective 2023-02-12 12:56:22 -03:00
Junior L. Botelho (JLB) 3bd1ba068b
chore: updated the PHP version from 7.4 to 8 for better performance 2023-02-12 12:50:41 -03:00
hnhx 0e78734743
Merge pull request #160 from Ratakor/main
remove cloudflared instance
2023-02-12 14:31:29 +00:00
Junior L. Botelho (JLB) 3cbb36eb66
chore: configured Nginx Dockerfile, updated PHP requirements in the PHP Dockerfile, and made other changes 2023-02-12 11:13:58 -03:00
Ratakor 7e5deb7be8 fix indent 2023-02-12 10:52:32 +01:00
Junior L. Botelho (JLB) 928808461a
chore: fixed dependency errors, added conditions to delete proxy configs, and removed duplicate quotes 2023-02-11 23:32:45 -03:00
Junior L. Botelho (JLB) 48b9863e3c
chore: to create Dockerfile modules and break up the procedure into smaller, step-by-step files instead of one large Dockerfile 2023-02-11 23:08:53 -03:00
Junior L. Botelho (JLB) 779cdf0da3
chore: move the templates to their appropriate folders 2023-02-11 20:08:33 -03:00
Junior L. Botelho (JLB) 656d9aa2d6
chore: change approach of dockerfiles 2023-02-11 19:54:45 -03:00
Junior L. Botelho (JLB) 4a5dad014d
chore: rename docker directory 2023-02-11 19:18:04 -03:00
Junior L. Botelho (JLB) 0faba78be1
chore: improve the method for passing images that will be built on Docker 2023-02-11 19:14:38 -03:00
Junior L. Botelho (JLB) b3a6a43acb
chore: for the initial execution, the entrypoint should include the addition of buildx 2023-02-11 18:59:04 -03:00
Junior L. Botelho (JLB) 450560eb6d
chore: the Docker build time errors have been fixed by changing the name of the nginx folder and renaming build.sh to prepare.sh 2023-02-11 16:53:22 -03:00
Junior L. Botelho (JLB) 9abb2cdbc8
chore: create template substitution variables with shell 2023-02-11 15:55:17 -03:00
Ratakor 60812f88bd readd search.funami.tech (see Issue #159) 2023-02-11 19:26:03 +01:00
Ratakor c641e602f1 remove cloudflared instance 2023-02-11 19:09:50 +01:00
Junior L. Botelho (JLB) a6883f62d7
chore: add environment variable substitutions for invalid or empty environment variables from the Dockerfile 2023-02-11 13:20:40 -03:00
Junior L. Botelho (JLB) 77915000b4
refactor: set the 'Dockerfiles' to use 'Alpine' images as the base 2023-02-11 01:33:34 -03:00
Junior L. Botelho (JLB) cc11ab9fff
chore: keep 'config.php' and 'opensearch.xml' just in root files from .gitignore 2023-02-11 01:18:33 -03:00
juniorbotelho 71ed181043 chore: keep 'config.php' and 'opensearch.xml' just in root files from .gitignore 2023-02-11 00:41:34 -03:00
juniorbotelho e9b23846d3 chore: create template files, remove incorrect Docker environment variables, and replace scripts 2023-02-11 00:37:09 -03:00
juniorbotelho 78082f1ac1 chore: add sleep infinity as init command docker container 2023-02-10 23:42:00 -03:00
juniorbotelho ef8ebd6b2d chore: add 'config.php' and 'opensearch.xml' configurations as Docker environment variables 2023-02-10 23:25:41 -03:00
juniorbotelho e99e268ec9 chore: fix wrong folders path and incorrect 'cache clean' command from apk 2023-02-10 22:33:39 -03:00
juniorbotelho 816e892b29 chore: add packages, move necessary files, and set the entrypoint runner 2023-02-10 22:29:13 -03:00
juniorbotelho d55652609b refactor: change '.docker' scripts folder structure 2023-02-10 21:49:01 -03:00
juniorbotelho af82157957 chore: create initial config dockerfile 2023-02-10 19:33:33 -03:00
hnhx 6bdd1d23e8 added a new instance librex.retro-hax.net 2023-02-10 09:12:19 +01:00
juniorbotelho 85cb9e36bb chore: add initial 'Dockerfiles' to project 2023-02-09 19:42:38 -03:00
hnhx 7966ec984b
Merge pull request #157 from Ftonans/main
Add new instance librex.bloatcat.tk
2023-02-08 18:20:19 +01:00
Ftonans 5b52a019d5 Add new instance librex.bloatcat.tk 2023-02-08 18:33:14 +03:00
hnhx e88c2771a8
Merge pull request #155 from Ratakor/main
unifiy / at the end of instances.json  for scripting purpose and remove 2 dead instances
2023-02-07 22:42:35 +01:00
Ratakor 7237d580c8 removed 2 dead instances 2023-02-07 19:16:02 +01:00
Ratakor 0a11072e4a unified / at the end for scripting purpose 2023-02-07 17:59:15 +01:00
hnhx d909552dbf code cleanup, removed an instance that broke the rules 2023-02-05 09:55:28 +01:00
hnhx 644f264f0c
Merge pull request #152 from Fijxu/main
Add librex.zzls.xyz
2023-02-03 20:46:04 +01:00
Fijxu cdd08eb3f6 asd 2023-02-03 16:16:17 -03:00
Fijxu d5d214605c Add librex.zzls.xyz 2023-02-03 12:51:22 -03:00
hnhx 2a9526cbac fixed video url, removed useless char from google request url 2023-02-02 16:25:09 +01:00
hnhx df195343a1
Merge pull request #150 from sesucc/main
changed subdomain for sesu.cc
2023-02-01 18:53:09 +01:00
sesucc 7d90e77142 changed subdomain for sesu.cc 2023-02-01 14:36:33 -03:00
hnhx 8c83f48e63
fixed formatting 2023-01-29 13:54:55 +01:00
hnhx 3468fbf1f4
updated the images, added a bit more info about librex 2023-01-29 13:52:47 +01:00
hnhx 9aa2d3498a
Merge pull request #146 from kiran9000/patch-1
added my singaporean librex instance
2023-01-29 13:45:17 +01:00
kiran9k 1fdab7f5d4
added to instances.json 2023-01-29 18:51:17 +07:00
kiran9k 967e80bfc9
xd 2023-01-29 18:48:54 +07:00
kiran9k e12d034ed4
added my singaporean librex instance
:3
2023-01-29 16:54:46 +07:00
hnhx 8edd1f9d46 replaced brave video search with invidious, fixed the broken json, fixed the broken main tor instance 2023-01-27 18:17:57 +01:00
hnhx c050a09429
Merge pull request #145 from jajecznik56/patch-2
Update instances.json
2023-01-26 19:27:29 +00:00
hnhx 3c4f9cb6b6
Merge pull request #144 from jajecznik56/patch-1
Update README.md
2023-01-26 19:27:15 +00:00
jajecznik56 9ae1720ce2
Update README.md 2023-01-26 20:26:10 +01:00
jajecznik56 77f272d234
Update instances.json 2023-01-26 20:25:28 +01:00
jajecznik56 ad97ee25b6
Update instances.json 2023-01-26 11:37:13 +00:00
jajecznik56 626a95dd21
Update README.md 2023-01-26 11:30:49 +00:00
hnhx 5db8c3d4c7
Merge pull request #142 from se-su/main
changed b32.i2p address for sesu.cc instance
2023-01-18 23:04:04 +01:00
sesu 97a54859e0 changed b32.i2p address for sesu.cc instance 2023-01-18 18:10:16 -03:00
hnhx 98f4cd287c
Merge pull request #139 from OshekharO/patch-1
Add StackOverflow Frontend
2023-01-18 18:00:23 +01:00
hnhx c6701efd7c added sukebei.nyaa.si results, added a new instance, fixed the imgur redirect URL 2023-01-18 16:47:21 +01:00
Saksham Shekher 7c4ff9324d
Update settings.php 2023-01-17 07:21:45 +05:30
Saksham Shekher d51788e706
Update config.php.example 2023-01-16 20:15:32 +05:30
Saksham Shekher a2de9b0fe2
Update settings.php 2023-01-16 20:14:42 +05:30
Saksham Shekher 8fb871c84c
Add StackOverflow Frontend 2023-01-16 20:13:17 +05:30
hnhx 204289d58c
Merge pull request #135 from OshekharO/patch-6
Added Frontends: Medium,GitHub and more
2023-01-15 13:29:06 +01:00
Saksham Shekher e5804ffb4f
Update tools.php 2023-01-15 17:50:42 +05:30
Saksham Shekher 0ed99e9000
Update config.php.example 2023-01-15 17:50:17 +05:30
Saksham Shekher e872a9e98e
Update settings.php 2023-01-15 17:49:57 +05:30
Saksham Shekher 5a7905afc4
Remove Pastebin & Reuters 2023-01-15 14:55:57 +05:30
Saksham Shekher a52d9dc256
Update config.php.example 2023-01-15 14:55:13 +05:30
Saksham Shekher e060832a54
Update settings.php 2023-01-15 14:54:50 +05:30
Saksham Shekher 3bbb2338d8
Update config.php.example 2023-01-15 10:29:27 +05:30
Saksham Shekher e6c65ad62b
Update settings.php 2023-01-15 10:28:38 +05:30
Saksham Shekher 10522378ba
Add reuters 2023-01-15 10:26:53 +05:30
Saksham Shekher fe544e00d8
Update config.php.example 2023-01-15 10:19:36 +05:30
Saksham Shekher cbac6bd5af
Update settings.php 2023-01-15 10:19:01 +05:30
Saksham Shekher 36b7b453f3
Add pastebin 2023-01-15 10:17:45 +05:30
Saksham Shekher 558d63b562
Merge branch 'hnhx:main' into patch-6 2023-01-15 10:00:01 +05:30
hnhx 4bcdb51b91 next page buttons are now in correct position on mobile, official instance moved to a new domain, added liberapay donation option 2023-01-15 02:24:27 +01:00
Saksham Shekher 8cbbc0f9d0
Merge branch 'hnhx:main' into patch-6 2023-01-14 17:59:54 +05:30
hnhx 5f7d81a7d6 underline active category, disable icon for torrent/tor if the host disabled it, removed a dead instance 2023-01-13 13:08:12 +01:00
Saksham Shekher 962ec8ad3c
Update config.php.example 2023-01-13 16:57:40 +05:30
Saksham Shekher 1224d3bdca
Update settings.php 2023-01-13 16:56:59 +05:30
Saksham Shekher fcd56802ea
Sry 2023-01-13 16:56:01 +05:30
Saksham Shekher 2a6cf9e57b
Update config.php.example 2023-01-13 16:50:04 +05:30
Saksham Shekher 2d81ba6304
Update tools.php 2023-01-13 16:46:57 +05:30
Saksham Shekher 41d2655318
Update settings.php 2023-01-13 16:45:22 +05:30
Saksham Shekher 3776615049
Added Frontends: Medium,GitHub,
Imgur,yt music,odysee
2023-01-13 16:39:11 +05:30
hnhx 9fad27104b added google language and safe search settings, made the codebase prettier 2023-01-13 09:31:48 +01:00
hnhx 3afd3ec769
Merge pull request #128 from Kame03/patch-1
Added tor for instance search.milivojevic.in.rs
2023-01-08 16:54:50 +00:00
Viktor Milivojević 41c0e83240
Added tor for instance search.milivojevic.in.rs 2023-01-08 16:38:26 +01:00
hnhx ca4c997d99
fixed formatting for an instance 2023-01-07 22:05:11 +00:00
hnhx df1d68fd0f
Merge pull request #126 from MyRoWARE/main
Added new instance: librex.myroware.eu
2023-01-07 22:04:27 +00:00
MyRoWARE 5dba4823c5 Removed plus enter 2023-01-07 22:49:09 +01:00
MyRoWARE 414b9baa19 Removed comma from intances.jon 2023-01-07 19:13:50 +01:00
Robin Dvořák a66bac4d6c
Merge branch 'main' into main 2023-01-07 18:52:35 +01:00
MyRoWARE dff4a55769 Fixed country location 2023-01-07 18:49:27 +01:00
hnhx 7dcdb1d6e8
Merge pull request #127 from whoisYoges/master
Add new instance
2023-01-07 17:45:49 +00:00
Castor c93f072484
indentation fix 2023-01-07 23:09:01 +05:45
Castor de581b055a
Add new librex instance 2023-01-07 22:05:32 +05:45
MyRoWARE 856130b86d Added new instance 2023-01-07 16:24:05 +01:00
hnhx 7e2c1b4ff5
Merge pull request #125 from amogusussy/Use-<a>-instead-of-buttons/form-request
Use <a> instead of buttons/form request
2023-01-07 12:22:43 +00:00
hnhx 74062ce433
Merge pull request #123 from gtlsgamr/patch-1
Added instance for ~tildevarsh
2023-01-06 23:49:23 +00:00
amogusussy d274ccb46b
Update search.php 2023-01-06 19:37:11 +00:00
amogusussy 3dc5b7443b
Update styles.css 2023-01-06 19:20:37 +00:00
amogusussy fef7fd957f
Update search.php 2023-01-06 19:19:30 +00:00
Hitarth Thummar 14d74a340b
Update instances.json 2023-01-06 22:02:48 +05:30
Hitarth Thummar b77d5ef4b7
Added instance for ~tildevarsh 2023-01-06 16:13:41 +05:30
hnhx e500d76399
Merge pull request #121 from Ratakor/main
add instance
2023-01-03 21:38:19 +00:00
ratakor 9f8cba2a33 add instance 2023-01-03 17:00:29 +01:00
hnhx 985bdf44ae
Merge pull request #119 from Ratakor/main
add dracula theme and fix useless whitespace
2023-01-01 20:36:01 +00:00
ratakor 441b755ad7 add dracula theme and fix useless whitespace 2023-01-01 14:43:21 +01:00
hnhx b96953bd20 added breezewiki to the frontends, removed a dead intance and added a new one 2022-12-28 11:45:09 +01:00
hnhx 71de47d472
Merge pull request #116 from hnhx/revert-113-main
Revert "Refactor UI/UX design for improved user experience"
2022-12-28 10:20:58 +00:00
72 changed files with 2675 additions and 1153 deletions

10
.dockerignore Normal file
View File

@ -0,0 +1,10 @@
.github/
.git/
.gitignore
.dockerignore
config.php.example
docker-compose.yml
Dockerfile
opensearch.xml.example
README.md
docker-old/

35
.github/workflows/docker-image.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Docker Image CI
on:
push:
branches: [ "main" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions: write-all
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: owner
uses: ASzc/change-string-case-action@v5
with:
string: ${{ github.repository_owner }}
- id: repo
uses: ASzc/change-string-case-action@v5
with:
string: ${{ github.event.repository.name }}
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/${{ steps.owner.outputs.lowercase }}/${{ steps.repo.outputs.lowercase }}:latest

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
./config.php
./opensearch.xml
/config.php
/opensearch.xml

42
Dockerfile Normal file
View File

@ -0,0 +1,42 @@
FROM alpine:3.18
WORKDIR "/var/www/html"
ADD "." "."
# Docker metadata contains information about the maintainer, such as the name, repository, and support email
# See more: https://docs.docker.com/config/labels-custom-metadata/
LABEL name="LibreY" \
description="Framework and javascript free privacy respecting meta search engine" \
version="1.0" \
vendor="Ahwx <ahwx.org>" \
maintainer="Ahwx <ahwx.org>" \
url="https://github.com/Ahwxorg/LibreY" \
authors="https://github.com/Ahwxorg/LibreY/contributors"
# Include arguments as temporary environment variables to be handled by Docker during the image build process
# Change or add new arguments to customize the image generated by 'docker build' command
ARG DOCKER_SCRIPTS="docker"
ARG NGINX_PORT=8080
# Set this argument during build time to indicate that the path is for php's www.conf
ARG WWW_CONFIG="/etc/php82/php-fpm.d/www.conf"
# Customize the environment during both execution and build time by modifying the environment variables added to the container's shell
# When building your image, make sure to set the 'TZ' environment variable to your desired time zone location, for example 'America/Sao_Paulo'
# See more: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
ENV TZ="America/New_York"
# Install required packages
RUN apk add gettext php82 php82-fpm php82-dom php82-curl php82-json php82-apcu nginx --no-cache
# Configure PHP-FPM to listen on a Unix socket instead of a TCP port, which is more secure and efficient
RUN touch /run/php-fpm82.sock && chown nginx:nginx "/run/php-fpm82.sock"
RUN sed -i 's/^\s*listen = 127.0.0.1:9000/listen = \/run\/php-fpm82.sock/' ${WWW_CONFIG} &&\
sed -i 's/^\s*;\s*listen.owner = nobody/listen.owner = nginx/' ${WWW_CONFIG} &&\
sed -i 's/^\s*;\s*listen.group = nobody/listen.group = nginx/' ${WWW_CONFIG} &&\
sed -i 's/^\s*;\s*listen.mode = 0660/listen.mode = 0660/' ${WWW_CONFIG}
EXPOSE ${NGINX_PORT}
# Configures the container to be run as an executable.
ENTRYPOINT ["/bin/sh", "-c", "docker/entrypoint.sh"]

View File

@ -1,60 +1,50 @@
<h1 align="center">LibreX</h1>
<h1 align="center">LibreY</h1>
<p float="left">
<img src="https://user-images.githubusercontent.com/49120638/207549667-c731a4f2-b9b0-4385-96be-9c17a8bb2984.png" width="400">
<img src="https://user-images.githubusercontent.com/49120638/207550159-4fa639a5-24e6-42e0-9e58-f04e5d18e391.png" width="400">
# Disclaimer
> LibreY is a fork of LibreX, a framework-less and javascript-free privacy respecting meta search engine, made by [hnhx](https://github.com/hnhx). LibreY changed some features like automatic redirection. The original code is written by [hnhx and contributors](https://github.com/hnhx/LibreX/contributors)
<p align="center">
<img src="https://user-images.githubusercontent.com/49120638/215327189-76c54dec-8b19-4faf-8c39-29a61aa3b143.png" width="400">
<img src="https://user-images.githubusercontent.com/49120638/215327239-b2a1cb07-3773-4ae7-bb3b-738de2cc3161.png" width="400">
</p>
<p align="center">A privacy respecting free as in freedom meta search engine</p>
<p align="center"></p>
<br>
### Instances
| Clearnet | TOR | I2P | Country |
|-|-|-|-|
| [librex.beparanoid.de](https://librex.beparanoid.de/) | [](http://librex.2356uhnbpv5nk3bni5bv6jg2cd6lgj664kwx3lhyelstpttpyv4kk2qd.onion/) | ❌ | 🇭🇺 HU (OFFICIAL INSTANCE) |
| [lx.vern.cc](https://lx.vern.cc/) | [](http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/) | [](http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/) | 🇺🇸 US |
| [lx.sesu.cc](https://lx.sesu.cc/) | [](http://lx.swxoebbpeqiiixyhbuh3vbw53pdrmtbiaj2sqveol6kkn5rpapfi4aad.onion/) | [](http://37bw4xelfgivsih5s4s5cozkxkhgoeqx5bjfjnrnmv5utdtk45sa.b32.i2p/) | 🇨🇱 CL |
| [librex.mikata.ru](https://librex.mikata.ru/) | [](http://f7ssz7l3biu4fugwctfpcx4txg5yq4gqhrt473ledsuc3ivtd3omniid.onion/) | ❌ | 🇺🇸 US |
| [librex.terryiscool160.xyz](https://librex.terryiscool160.xyz/) | [](http://librex.n53wt4ivvfdfaqkwldgdzfsubszukie2an6auja6x2wp3e3oa7v2gqyd.onion/) | ❌ | 🇬🇧 UK |
| [search.davidovski.xyz](https://search.davidovski.xyz/) | ❌ | ❌ | 🇬🇧 UK |
| [search.funami.tech](https://search.funami.tech/) | ❌ | ❌ | 🇰🇷 KR |
| [search.madreyk.xyz](https://search.madreyk.xyz/) | ❌ | ❌ | 🇩🇪 DE |
| [search.pabloferreiro.es](https://search.pabloferreiro.es/) | ❌ | ❌ | 🇩🇪 DE |
| [buscar.weblibre.org](https://buscar.weblibre.org/) | ❌ | ❌ | 🇨🇱 CL |
| [search.ahwx.org](https://search.ahwx.org/) | ❌ | ❌ | 🇳🇱 NL |
| [librex.pufe.org](https://librex.pufe.org/) | ❌ | ❌ | :new_zealand: NZ |
| [librex.kitscomputer.tk](https://librex.kitscomputer.tk/) | ❌ | ❌ | 🇺🇸 US |
You can find a list of instances on any LibreY instance by accessing /instances.php.<br>
Alternatively look at `instances.json` where the list is generated from.<br><br>
While the official instances may be more updated and have better uptime, please consider using another person's instances as these are heavily overloaded.<br>
Support the community. ❤️<br><br>
Instance list on [@codedipper](https://github.com/codedipper)'s instance:<br>
[librex.me](https://librex.me/instances.php)<br>
[librex.revvy.de](https://librex.revvy.de/instances.php)<br>
[Tor](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/instances.php)<br>
[I2P](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/instances.php)<br>
<br>
[@Ahwxorg](https://github.com/Ahwxorg)'s instances:<br>
[search.ahwx.org](https://search.ahwx.org/instances.php)<br>
[Tor](http://wn5jl6fxlzzfenlyu3lc4q7jpw2saplrywxvxtvqbguotwd4y5cjeuqd.onion/instances.php)<br>
[search2.ahwx.org](https://search.ahwx.org/instances.php)<br>
[Tor](http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion/instances.php)<br>
<br>
[@davidovski](https://github.com/davidovski)'s instance:<br>
[search.davidovski.xyz](https://search.davidovski.xyz/instances.php)<br>
<br>
### Thanks rms
Huge thanks to Richard Stallman for using LibreX and featuring it on his [website](https://stallman.org/stallman-computing.html)!
### About LibreY
> However, the Librex proxies have worked around that problem. They enable me to access Google Search indirectly, and they work correctly through Tor with LibreJS enabled.
LibreY gives you text results from DuckDuckGo or Google, images from Qwant, and torrents from i.e. Ahmia and popular torrent sites without spying on you.
<br>LibreY doesn't save **any** type of data about the user, there are no logs (except NGINX logs if the host sets them).
<br>
### About LibreX
LibreX gives you results from Google, Brave, Qwant, Ahmia and popular torrent sites without spying on you.
<br>
<br>
If you would like to learn more about LibreX check out the [Wiki](https://github.com/hnhx/librex/wiki).
<br>
<br>
### Mirror
You can access the source code via this git mirror
```
git clone https://git.beparanoid.de/librex
```
### LibreX compared to other metasearch engines
### LibreY compared to other metasearch engines
| Name | Works without JS | Privacy frontend redirect | Torrent results | API | No 3rd party libs used |
|-|-|-|-|-|-|
| LibreX | ✅ | ✅ | ✅ | ✅ | ✅ |
| LibreY | ✅ | ✅ | ✅ | ✅ | ✅ |
| SearXNG | ❓ Not user friendly | ❓ Only host can set it | ✅ | ✅ | ❌ |
| Whoogle | ✅ | ❓ Only host can set it | ❌ | ❌ | ❌ |

9
SECURITY.md Normal file
View File

@ -0,0 +1,9 @@
# Security Policy
## Supported Versions
Basically the latest commit. We don't really do versioning with LibreY.
## Reporting a Vulnerability
Please join #librey:ahwx.org on Matrix and please DM me (@ahwx:ahwx.org) or if Matrix is absolutely impossible, email me; ahwx *at* ahwx *dot* org

53
api.php
View File

@ -1,9 +1,10 @@
<?php
$config = require "config.php";
require "misc/tools.php";
require "misc/search_engine.php";
if (!isset($_REQUEST["q"]))
{
$opts = load_opts();
if (!$opts->query) {
echo "<p>Example API request: <a href=\"./api.php?q=gentoo&p=2&t=0\">./api.php?q=gentoo&p=2&t=0</a></p>
<br/>
<p>\"q\" is the keyword</p>
@ -16,51 +17,7 @@
die();
}
$query = $_REQUEST["q"];
$query_encoded = urlencode($query);
$page = isset($_REQUEST["p"]) ? (int) $_REQUEST["p"] : 0;
$type = isset($_REQUEST["t"]) ? (int) $_REQUEST["t"] : 0;
$results = array();
switch ($type)
{
case 0:
require "engines/google/text.php";
$results = get_text_results($query, $page);
break;
case 1:
require "engines/qwant/image.php";
$results = get_image_results($query_encoded, $page);
break;
case 2:
require "engines/brave/video.php";
$results = get_video_results($query_encoded);
break;
case 3:
if ($config->disable_bittorent_search)
$results = array("error" => "disabled");
else
{
require "engines/bittorrent/merge.php";
$results = get_merged_torrent_results($query_encoded);
}
break;
case 4:
if ($config->disable_hidden_service_search)
$results = array("error" => "disabled");
else
{
require "engines/ahmia/hidden_service.php";
$results = get_hidden_service_results($query_encoded);
}
break;
default:
require "engines/google/text.php";
$results = get_text_results($query_encoded, $page);
break;
}
$results = fetch_search_results($opts, false);
header("Content-Type: application/json");
echo json_encode($results);
?>

6
auto_updater.sh Normal file
View File

@ -0,0 +1,6 @@
#!/bin/sh
while true; do
git stash
git pull
sleep 60
done

View File

@ -4,26 +4,130 @@
// e.g.: fr -> https://google.fr/
"google_domain" => "com",
// Google results will be in this language
"google_language" => "en",
// Results will be in this language
"language" => "",
"number_of_results" => 10,
// You can use any Invidious instance here
"invidious_instance_for_video_results" => "https://invidious.snopyta.org",
"disable_bittorent_search" => false,
"bittorent_trackers" => "&tr=http%3A%2F%2Fnyaa.tracker.wf%3A7777%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce",
"bittorent_trackers" => "&tr=http://nyaa.tracker.wf:7777/announce&tr=udp://open.stealth.si:80/announce&tr=udp://tracker.opentrackr.org:1337/announce&tr=udp://exodus.desync.com:6969/announce&tr=udp://tracker.torrent.eu.org:451/announce",
"disable_hidden_service_search" => false,
// Fallback to another librex instance if google search fails
// This may greatly increase the time it takes to get a result, if a direct search is not possible
"instance_fallback" => true,
// how long in minutes to put google/other instances on cooldown if they aren't responding
"request_cooldown" => 25,
// how long in minutes to store results for in the cache
"cache_time" => 20,
/*
Preset privacy friendly frontends for users, these can be overwritten by users in settings
e.g.: "invidious" => "https://yewtu.be",
Preset privacy friendly frontends for users, these can be overwritten by users in the settings
e.g.: Preset the invidious instance URL: "instance_url" => "https://yewtu.be",
*/
"invidious" => "", // youtube
"bibliogram" => "", // instagram
"nitter" => "", // twitter
"libreddit" => "", // reddit
"proxitok" => "", // tiktok
"wikiless" => "", // wikipedia
"quetre" => "", // quora
"libremdb" => "", // imdb
"frontends" => array(
"invidious" => array(
"instance_url" => "",
"project_url" => "https://docs.invidious.io/instances/",
"original_name" => "YouTube",
"original_url" => "youtube.com"
),
"rimgo" => array(
"instance_url" => "",
"project_url" => "https://codeberg.org/video-prize-ranch/rimgo#instances",
"original_name" => "Imgur",
"original_url" => "imgur.com"
),
"scribe" => array(
"instance_url" => "",
"project_url" => "https://git.sr.ht/~edwardloveall/scribe/tree/main/docs/instances.md",
"original_name" => "Medium",
"original_url" => "medium.com"
),
"gothub" => array(
"instance_url" => "",
"project_url" => "https://codeberg.org/gothub/gothub#instances",
"original_name" => "GitHub",
"original_url" => "github.com"
),
"nitter" => array(
"instance_url" => "",
"project_url" => "https://github.com/zedeus/nitter/wiki/Instances",
"original_name" => "Twitter",
"original_url" => "twitter.com"
),
"libreddit" => array(
"instance_url" => "",
"project_url" => "https://github.com/libreddit/libreddit-instances/blob/master/instances.md",
"original_name" => "Reddit",
"original_url" => "reddit.com"
),
"proxitok" => array(
"instance_url" => "",
"project_url" => "https://github.com/pablouser1/ProxiTok/wiki/Public-instances",
"original_name" => "TikTok",
"original_url" => "tiktok.com"
),
"wikiless" => array(
"instance_url" => "",
"project_url" => "https://github.com/Metastem/wikiless#instances",
"original_name" => "Wikipedia",
"original_url" => "wikipedia.org"
),
"quetre" => array(
"instance_url" => "",
"project_url" => "https://github.com/zyachel/quetre#instances",
"original_name" => "Quora",
"original_url" => "quora.com"
),
"libremdb" => array(
"instance_url" => "",
"project_url" => "https://github.com/zyachel/libremdb#instances",
"original_name" => "IMDb",
"original_url" => "imdb.com"
),
"breezewiki" => array(
"instance_url" => "",
"project_url" => "https://docs.breezewiki.com/Links.html",
"original_name" => "Fandom",
"original_url" => "fandom.com"
),
"anonymousoverflow" => array(
"instance_url" => "",
"project_url" => "https://github.com/httpjamesm/AnonymousOverflow#clearnet-instances",
"original_name" => "StackOverflow",
"original_url" => "stackoverflow.com"
),
"suds" => array(
"instance_url" => "",
"project_url" => "https://git.vern.cc/cobra/Suds/src/branch/main/instances.json",
"original_name" => "Snopes",
"original_url" => "snopes.com"
),
"biblioreads" => array(
"instance_url" => "",
"project_url" => "https://github.com/nesaku/BiblioReads#instances",
"original_name" => "Goodreads",
"original_url" => "goodreads.com"
)
),
"preferred_engines" => array(
/* replace with "text" => "duckduckgo" to use duckduckgo instead
* (recommended if being ratelimited */
"text" => "google"
// "text" => "duckduckgo"
),
/*
To send requests trough a proxy uncomment CURLOPT_PROXY and CURLOPT_PROXYTYPE:
@ -43,15 +147,15 @@
// CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:116.0) Gecko/20100101 Firefox/116.0", // For a normal Windows 10 PC running Firefox x64
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_WHATEVER,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 18,
CURLOPT_VERBOSE => false
CURLOPT_TIMEOUT => 3,
CURLOPT_VERBOSE => false,
CURLOPT_FOLLOWLOCATION => true
)
);
?>

32
docker-compose.yml Normal file
View File

@ -0,0 +1,32 @@
version: "3"
services:
librey:
image: ghcr.io/ahwxorg/librey:latest
container_name: librey
network_mode: bridge
ports:
- 8080:8080
environment:
- CONFIG_GOOGLE_DOMAIN=com
- CONFIG_LANGUAGE=en
- CONFIG_NUMBER_OF_RESULTS=10
- CONFIG_INVIDIOUS_INSTANCE=https://invidious.snopyta.org
- CONFIG_DISABLE_BITTORRENT_SEARCH=false
- CONFIG_HIDDEN_SERVICE_SEARCH=false
- CONFIG_INSTANCE_FALLBACK=true
- CONFIG_RATE_LIMIT_COOLDOWN=25
- CONFIG_CACHE_TIME=20
- CONFIG_TEXT_SEARCH_ENGINE=google
- CURLOPT_PROXY_ENABLED=false
- CURLOPT_PROXY=192.0.2.53:8388
- CURLOPT_PROXYTYPE=CURLPROXY_HTTP
- CURLOPT_USERAGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:116.0) Gecko/20100101 Firefox/116.0
- CURLOPT_FOLLOWLOCATION=true
volumes:
- ./nginx_logs:/var/log/nginx
- ./php_logs:/var/log/php7
restart: unless-stopped
watchtower: # Watchtower is not required but highly recommended, since Watchtower will re-pull and restart the LibreY container automatically whenever there's an update.
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock

208
docker/README.md Normal file
View File

@ -0,0 +1,208 @@
### Introduction
- [Introduction](#introduction)
- [Running a docker container](#running-a-docker-container)
- [Running a Docker container through ghcr](#running-a-docker-container-through-ghcr)
- [Running a Docker container with composer](#running-a-docker-container-with-composer)
- [Environment variables that can be set in the Docker container](#environment-variables-that-can-be-set-in-the-docker-container)
- [Search Configuration](#search)
- [Frontend Configuration](#frontends)
- [Search Engine Configuration](#engines)
- [cURL Configuration](#curl)
- [OpenSearch Configuration](#opensearch)
- [Docker version issues](#docker-version-issues)
- [Building a docker image](#building-a-docker-image)
- [Support for different architectures](#support-for-different-architectures)
### Running a docker container
Dockerized librey is a way to provide users with yet another way to self-host their own projects with a view to privacy. If you wish to help, please start by looking for bugs in used docker configurations.
### Running a Docker container through ghcr
To run librey in a docker container, you can simply use the command:
```sh
docker run -d \
--name librey \
-e TZ="America/New_York" \
-e CONFIG_GOOGLE_DOMAIN="com" \
-e CONFIG_GOOGLE_LANGUAGE="en" \
-e CONFIG_WIKIPEDIA_LANGUAGE="en" \
-p 8080:8080 \
ghcr.io/ahwxorg/librey:latest
```
Also run with watchtower for auto-updating: (optional)
```sh
docker run -d \
--name librey-watchtower-1 \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower
```
<br>
### Running a Docker container with composer
```yml
version: "3"
services:
librey:
image: ghcr.io/ahwxorg/librey:latest
container_name: librey
network_mode: bridge
ports:
- 8080:8080
environment:
- CONFIG_GOOGLE_DOMAIN=com
- CONFIG_LANGUAGE=en
- CONFIG_NUMBER_OF_RESULTS=10
- CONFIG_INVIDIOUS_INSTANCE=https://invidious.snopyta.org
- CONFIG_DISABLE_BITTORRENT_SEARCH=false
- CONFIG_HIDDEN_SERVICE_SEARCH=false
- CONFIG_INSTANCE_FALLBACK=true
- CONFIG_RATE_LIMIT_COOLDOWN=25
- CONFIG_CACHE_TIME=20
- CONFIG_TEXT_SEARCH_ENGINE=google
- CURLOPT_PROXY_ENABLED=false
- CURLOPT_PROXY=192.0.2.53:8388
- CURLOPT_PROXYTYPE=CURLPROXY_HTTP
- CURLOPT_USERAGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:116.0) Gecko/20100101 Firefox/116.0
- CURLOPT_FOLLOWLOCATION=true
volumes:
- ./nginx_logs:/var/log/nginx
- ./php_logs:/var/log/php7
restart: unless-stopped
watchtower: # Watchtower is not required but highly recommended, since Watchtower will re-pull and restart the LibreY container automatically whenever there's an update.
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
```
<br>
### Environment variables that can be set in the Docker container
This docker image was developed with high configurability in mind, so here is the list of environment variables that can be changed according to your use case, no matter how specific.
<br>
### Search
| Variables | Default | Examples | Description |
|:----------|:-------------|:---------|:------|
| CONFIG_GOOGLE_DOMAIN | "com" | "com", "com.br", "cat", "se" | Defines which Google domain the search will be done on, change according to your country. |
| CONFIG_LANGUAGE | "en" | "zh-Hans", "fil", "no" | Defines the language in which searches will be done, see the list of supported languages [here](https://developers.google.com/custom-search/docs/ref_languages). |
| CONFIG_NUMBER_OF_RESULTS | 10 | integer | Number of results for Google to return each page. |
| CONFIG_INVIDIOUS_INSTANCE | "https://invidious.snopyta.org" | string | Defines the host that will be used to do video searches using Invidious. |
| CONFIG_DISABLE_BITTORRENT_SEARCH | false | boolean | Defines whether bittorrent search will be disabled |
| CONFIG_BITTORRENT_TRACKERS | "&tr=http://nyaa.tracker.wf:7777/announce&tr=udp://open.stealth.si:80/announce&tr=udp://tracker.opentrackr.org:1337/announce&tr=udp://exodus.desync.com:6969/announce&tr=udp://tracker.torrent.eu.org:451/announce" | string | Set list of bittorrent trackers for torrent search. |
| CONFIG_HIDDEN_SERVICE_SEARCH | false | boolean | Defines whether hidden service search will be disabled |
| CONFIG_INSTANCE_FALLBACK | true | boolean | Choose whether or not to use the API on the backend to request to another LibreX/Y instance in case of rate limiting. |
| CONFIG_RATE_LIMIT_COOLDOWN | 25 | integer | Time in minutes to wait before sending requests to Google again after a rate limit. |
| CONFIG_CACHE_TIME | 20 | integer | Time in minutes to store results for in the cache. |
### Frontends
| Variables | Default | Examples | Description |
|:----------|:-------------|:---------|:------|
| APP_INVIDIOUS | "" | "https://example.com", string | Integration with external self-hosted apps, configure the desired host. |
| APP_RIMGO | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_SCRIBE | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_GOTHUB | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_NITTER | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_LIBREREDDIT | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_PROXITOK | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_WIKILESS | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_QUETRE | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_LIBREMDB | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_BREEZEWIKI | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_ANONYMOUS_OVERFLOW | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_SUDS | "" | string | Integration with external self-hosted apps, configure the desired host. |
| APP_BIBLIOREADS | "" | string | Integration with external self-hosted apps, configure the desired host. |
### Engines
| Variables | Default | Examples | Description |
|:----------|:-------------|:---------|:------|
| CONFIG_TEXT_SEARCH_ENGINE | "google" | "google", "duckduckgo" | Integration with external self-hosted apps, configure the desired host. |
### cURL
| Variables | Default | Examples | Description |
|:----------|:-------------|:---------|:------|
| CURLOPT_PROXY_ENABLED | false | boolean | If you want to use a proxy, you need to set this variable to true. |
| CURLOPT_PROXY | "" | "192.0.2.53:8388" | Set the proxy using the ip and port to be used. |
| CURLOPT_PROXYTYPE | "CURLPROXY_HTTP" | "CURLPROXY_SOCKS4A", "CURLPROXY_SOCKS5", "CURLPROXY_SOCKS5_HOSTNAME" | Set the type of proxy connection (if you enabled it). |
| CURLOPT_RETURNTRANSFER | true | boolean | Return the transfer as a string of the return value of curl_exec() instead of outputting it directly. |
| CURLOPT_ENCODING | "" | string | Return the transfer as a string of the return value of curl_exec() instead of outputting it directly. |
| CURLOPT_USERAGENT | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:116.0) Gecko/20100101 Firefox/116.0" | string | This variable defines the 'User-Agent' that curl will use to attempt to avoid being blocked. |
| CURLOPT_IPRESOLVE | "CURL_IPRESOLVE_WHATEVER" | "CURL_IPRESOLVE_V4", "CURL_IPRESOLVE_V6" | Use a fixed IP version for making requests, or what DNS prefers. |
| CURLOPT_CUSTOMREQUEST | "GET" | "POST", "CONNECT" | Defines the HTTP method that curl will use to make the request. |
| CURLOPT_MAXREDIRS | 5 | integer | The maximum amount of HTTP redirections to follow, only enabled with CURLOPT_FOLLOWLOCATION. |
| CURLOPT_TIMEOUT | 3 | integer | The maximum amount of time for cURL requests to complete. |
| CURLOPT_VERBOSE | false | boolean | Whether to output verbose information. |
| CURLOPT_FOLLOWLOCATION | true | boolean | Whether to follow any Location header. Required for instance fallback. |
### OpenSearch
| Variables | Default | Examples | Description |
|:----------|:-------------|:---------|:------|
| OPEN_SEARCH_TITLE | "LibreY" | string | [OpenSearch XML](https://developer.mozilla.org/en-US/docs/Web/OpenSearch) |
| OPEN_SEARCH_DESCRIPTION | "Framework and javascript free privacy respecting meta search engine" | string | [OpenSearch XML](https://developer.mozilla.org/en-US/docs/Web/OpenSearch) |
| OPEN_SEARCH_ENCODING | "UTF-8" | "UTF-8" | [OpenSearch XML](https://developer.mozilla.org/en-US/docs/Web/OpenSearch) |
| OPEN_SEARCH_LONG_NAME | "LibreY Search" | string | [OpenSearch XML](https://developer.mozilla.org/en-US/docs/Web/OpenSearch) |
| OPEN_SEARCH_HOST | "http://localhost:80" | string | Host used to identify librey on the network |
<br>
### Docker version issues
If you are going to build your own docker image based on this repository, pay attention to your Docker version, because depending on how recent the installed version is, maybe you should use the `buildx` command instead of `build`.
Docker <= 20.10: `docker build`
Docker > 20.10: `docker buildx build`
<br>
### Building a docker image
If you don't want to use the image that is already available on `docker hub`, then you can simply build the Dockerfile directly from the github repository using the command:
```sh
docker build https://github.com/Ahwxorg/librey.git -t librey:latest
```
```sh
docker run -d --name librey \
-e CONFIG_GOOGLE_DOMAIN="com" \
-e CONFIG_GOOGLE_LANGUAGE="en" \
-p 8080:8080 \
librey:latest
```
Or, instead of doing the build remotely, you still have the opportunity to `git clone` the repository, and build it locally with the command:
```sh
git clone https://github.com/Ahwxorg/librey.git
cd librey/
docker build -t librey:latest .
```
<br>
### Support for different architectures
Supported architectures for the official librey images include the same ones supported by Alpine itself, which are typically denoted as `linux/386`, `linux/amd64`, `linux/arm/v6`. If you need support for a different architecture, such as `linux/arm/v7`, you can modify the 'Dockerfile' to use a more comprehensive base image like `ubuntu:latest` instead.
In this case, you must run the `buildx` process specifying the desired architecture as shown in the example below:
```sh
docker buildx build \
--no-cache \
--platform linux/arm/v7 \
--tag ahwxorg/librey:latest .
```
**OBS:** Keep in mind that this can cause some issues at build time, so you need to know a little about Dockerfiles to solve this problem for your specific case.

68
docker/attributes.sh Executable file
View File

@ -0,0 +1,68 @@
#!/bin/sh
# YOU DON'T NEED TO EDIT THIS FILE. IF YOU WANT TO SET CUSTOM ENVIRONMENT VARIABLES,
# USE THE 'DOCKERFILE IMAGE' FROM ROOT DIRECTORY AND PASS THE ENVIRONMENT PARAMETERS
# These templates will be used to create configuration files that incorporate values from environment variables
# If these locations do not already exist within the Docker container, they will be created
export CONFIG_PHP_TEMPLATE="$(pwd)/config.php"
export CONFIG_OPEN_SEARCH_TEMPLATE="$(pwd)/opensearch.xml"
export CONFIG_NGINX_TEMPLATE="/etc/nginx/http.d/librey.conf"
# Configure 'opensearch.xml' with librey configuration metadata, such as the encoding and the host that stores the site
# These configurations will replace the 'opensearch.xml' inside '.dockers/templates' for the best setup for your instance
export OPEN_SEARCH_TITLE=${OPEN_SEARCH_TITLE:-"LibreY"}
export OPEN_SEARCH_DESCRIPTION=${OPEN_SEARCH_DESCRIPTION:-"Framework and javascript free privacy respecting meta search engine"}
export OPEN_SEARCH_ENCODING=${OPEN_SEARCH_ENCODING:-"UTF-8"}
export OPEN_SEARCH_LONG_NAME=${OPEN_SEARCH_LONG_NAME:-"LibreY Search"}
export OPEN_SEARCH_HOST=${OPEN_SEARCH_HOST:-"127.0.0.1"}
# Replace the 'config.php' script, which contains the most common search engine configurations, with these environment setups
# These environment setups can be found in 'config.php', and the default configurations can be useful for most use cases
export CONFIG_GOOGLE_DOMAIN=${CONFIG_GOOGLE_DOMAIN:-"com"}
export CONFIG_LANGUAGE=${CONFIG_LANGUAGE:-"en"}
export CONFIG_NUMBER_OF_RESULTS=${CONFIG_NUMBER_OF_RESULTS:-10}
export CONFIG_INVIDIOUS_INSTANCE=${CONFIG_INVIDIOUS_INSTANCE:-"https://invidious.snopyta.org"}
export CONFIG_DISABLE_BITTORRENT_SEARCH=${CONFIG_DISABLE_BITTORRENT_SEARCH:-false}
export CONFIG_BITTORRENT_TRACKERS=${CONFIG_BITTORRENT_TRACKERS:-"&tr=http://nyaa.tracker.wf:7777/announce&tr=udp://open.stealth.si:80/announce&tr=udp://tracker.opentrackr.org:1337/announce&tr=udp://exodus.desync.com:6969/announce&tr=udp://tracker.torrent.eu.org:451/announce"}
export CONFIG_HIDDEN_SERVICE_SEARCH=${CONFIG_HIDDEN_SERVICE_SEARCH:-false}
export CONFIG_INSTANCE_FALLBACK="${CONFIG_INSTANCE_FALLBACK:-true}"
export CONFIG_RATE_LIMIT_COOLDOWN="${CONFIG_RATE_LIMIT_COOLDOWN:-25}"
export CONFIG_CACHE_TIME="${CONFIG_CACHE_TIME:-20}"
# Supported apps integration configuration. These empty spaces can be set up using free hosts as pointers
# A particular example is using the "https://yewtu.be" or a self-hosted host to integrate the invidious app to librey
export APP_INVIDIOUS=${APP_INVIDIOUS:-""}
export APP_RIMGO=${APP_RIMGO:-""}
export APP_SCRIBE=${APP_SCRIBE:-""}
export APP_GOTHUB=${APP_GOTHUB:-""}
export APP_NITTER=${APP_NITTER:-""}
export APP_LIBREREDDIT=${APP_LIBREREDDIT:-""}
export APP_PROXITOK=${APP_PROXITOK:-""}
export APP_WIKILESS=${APP_WIKILESS:-""}
export APP_QUETRE=${APP_QUETRE:-""}
export APP_LIBREMDB=${APP_LIBREMDB:-""}
export APP_BREEZEWIKI=${APP_BREEZEWIKI:-""}
export APP_ANONYMOUS_OVERFLOW=${APP_ANONYMOUS_OVERFLOW:-""}
export APP_SUDS=${APP_SUDS:-""}
export APP_BIBLIOREADS=${APP_BIBLIOREADS:-""}
export CONFIG_TEXT_SEARCH_ENGINE=${CONFIG_TEXT_SEARCH_ENGINE:-"google"}
# GNU/Curl configurations. Leave 'CURLOPT_PROXY' blank whether you don't need to use a proxy for requests
# Generally, a proxy is needed when your IP address is blocked by search engines in response to multiple requests within a short time frame. In these cases, it is recommended to use rotating proxies
export CURLOPT_PROXY_ENABLED=${CURLOPT_PROXY_ENABLED:-false}
export CURLOPT_PROXY=${CURLOPT_PROXY:-""}
export CURLOPT_PROXYTYPE=${CURLOPT_PROXYTYPE:-"CURLPROXY_HTTP"}
export CURLOPT_RETURNTRANSFER=${CURLOPT_RETURNTRANSFER:-true}
export CURLOPT_ENCODING=${CURLOPT_ENCODING:-""}
export CURLOPT_USERAGENT=${CURLOPT_USERAGENT:-"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:116.0) Gecko/20100101 Firefox/116.0"}
export CURLOPT_IPRESOLVE=${CURLOPT_IPRESOLVE:-"CURL_IPRESOLVE_WHATEVER"}
export CURLOPT_CUSTOMREQUEST="${CURLOPT_CUSTOMREQUEST:-"GET"}"
export CURLOPT_MAXREDIRS=${CURLOPT_MAXREDIRS:-5}
export CURLOPT_TIMEOUT=${CURLOPT_TIMEOUT:-3}
export CURLOPT_VERBOSE=${CURLOPT_VERBOSE:-true}
export CURLOPT_FOLLOWLOCATION=${CURLOPT_FOLLOWLOCATION:-true}
# These shell functions will be available for use by any function calls
function AwkTrim() { awk '{$1=$1};1'; }

123
docker/config.php Normal file
View File

@ -0,0 +1,123 @@
<?php
return (object) array(
"google_domain" => "${CONFIG_GOOGLE_DOMAIN}",
"language" => "${CONFIG_LANGUAGE}",
"number_of_results" => ${CONFIG_NUMBER_OF_RESULTS},
"invidious_instance_for_video_results" => "${CONFIG_INVIDIOUS_INSTANCE}",
"disable_bittorent_search" => ${CONFIG_DISABLE_BITTORRENT_SEARCH},
"bittorent_trackers" => "${CONFIG_BITTORRENT_TRACKERS}",
"disable_hidden_service_search" => ${CONFIG_HIDDEN_SERVICE_SEARCH},
"instance_fallback" => ${CONFIG_INSTANCE_FALLBACK},
"request_cooldown" => ${CONFIG_RATE_LIMIT_COOLDOWN},
"cache_time" => ${CONFIG_CACHE_TIME},
"frontends" => array(
"invidious" => array(
"instance_url" => "${APP_INVIDIOUS}",
"project_url" => "https://docs.invidious.io/instances/",
"original_name" => "YouTube",
"original_url" => "youtube.com"
),
"rimgo" => array(
"instance_url" => "${APP_RIMGO}",
"project_url" => "https://codeberg.org/video-prize-ranch/rimgo#instances",
"original_name" => "Imgur",
"original_url" => "imgur.com"
),
"scribe" => array(
"instance_url" => "${APP_SCRIBE}",
"project_url" => "https://git.sr.ht/~edwardloveall/scribe/tree/main/docs/instances.md",
"original_name" => "Medium",
"original_url" => "medium.com"
),
"gothub" => array(
"instance_url" => "${APP_GOTHUB}",
"project_url" => "https://codeberg.org/gothub/gothub#instances",
"original_name" => "GitHub",
"original_url" => "github.com"
),
"nitter" => array(
"instance_url" => "${APP_NITTER}",
"project_url" => "https://github.com/zedeus/nitter/wiki/Instances",
"original_name" => "Twitter",
"original_url" => "twitter.com"
),
"libreddit" => array(
"instance_url" => "${APP_LIBREREDDIT}",
"project_url" => "https://github.com/libreddit/libreddit-instances/blob/master/instances.md",
"original_name" => "Reddit",
"original_url" => "reddit.com"
),
"proxitok" => array(
"instance_url" => "${APP_PROXITOK}",
"project_url" => "https://github.com/pablouser1/ProxiTok/wiki/Public-instances",
"original_name" => "TikTok",
"original_url" => "tiktok.com"
),
"wikiless" => array(
"instance_url" => "${APP_WIKILESS}",
"project_url" => "https://github.com/Metastem/wikiless#instances",
"original_name" => "Wikipedia",
"original_url" => "wikipedia.org"
),
"quetre" => array(
"instance_url" => "${APP_QUETRE}",
"project_url" => "https://github.com/zyachel/quetre#instances",
"original_name" => "Quora",
"original_url" => "quora.com"
),
"libremdb" => array(
"instance_url" => "${APP_LIBREMDB}",
"project_url" => "https://github.com/zyachel/libremdb#instances",
"original_name" => "IMDb",
"original_url" => "imdb.com"
),
"breezewiki" => array(
"instance_url" => "${APP_BREEZEWIKI}",
"project_url" => "https://docs.breezewiki.com/Links.html",
"original_name" => "Fandom",
"original_url" => "fandom.com"
),
"anonymousoverflow" => array(
"instance_url" => "${APP_ANONYMOUS_OVERFLOW}",
"project_url" => "https://github.com/httpjamesm/AnonymousOverflow#clearnet-instances",
"original_name" => "StackOverflow",
"original_url" => "stackoverflow.com"
),
"suds" => array(
"instance_url" => "${APP_SUDS}",
"project_url" => "https://git.vern.cc/cobra/Suds/src/branch/main/instances.json",
"original_name" => "Snopes",
"original_url" => "snopes.com"
),
"biblioreads" => array(
"instance_url" => "${APP_BIBLIOREADS}",
"project_url" => "https://github.com/nesaku/BiblioReads#instances",
"original_name" => "Goodreads",
"original_url" => "goodreads.com"
)
),
"preferred_engines" => array(
"text" => "${CONFIG_TEXT_SEARCH_ENGINE}"
),
"curl_settings" => array(
CURLOPT_PROXY => "${CURLOPT_PROXY}",
CURLOPT_PROXYTYPE => ${CURLOPT_PROXYTYPE},
CURLOPT_RETURNTRANSFER => ${CURLOPT_RETURNTRANSFER},
CURLOPT_ENCODING => "${CURLOPT_ENCODING}",
CURLOPT_USERAGENT => "${CURLOPT_USERAGENT}",
CURLOPT_IPRESOLVE => ${CURLOPT_IPRESOLVE},
CURLOPT_CUSTOMREQUEST => "${CURLOPT_CUSTOMREQUEST}",
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_MAXREDIRS => ${CURLOPT_MAXREDIRS},
CURLOPT_TIMEOUT => ${CURLOPT_TIMEOUT},
CURLOPT_VERBOSE => ${CURLOPT_VERBOSE},
CURLOPT_FOLLOWLOCATION => ${CURLOPT_FOLLOWLOCATION}
)
);
?>

7
docker/entrypoint.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
/bin/sh -c docker/env-substitution.sh
/bin/sh -c /usr/sbin/php-fpm82
exec nginx -g "daemon off;"

29
docker/env-substitution.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/sh
# Load all environment variables from 'attributes.sh' using the command 'source /path/attributes.sh'
source "docker/attributes.sh"
# The lines below will replace the environment variables in the templates with the corresponding variables listed above if the config file is not yet provided. To accomplish this, the GNU 'envsubst' package will be used
# Although not recommended (if you do not know what you are doing), you still have the option to add new substitution file templates using any required environment variables
[[ ! -s ${CONFIG_PHP_TEMPLATE} ]] && cat 'docker/config.php' | envsubst > ${CONFIG_PHP_TEMPLATE};
[[ ! -s ${CONFIG_OPEN_SEARCH_TEMPLATE} ]] && cat 'docker/opensearch.xml' | envsubst > ${CONFIG_OPEN_SEARCH_TEMPLATE};
export OPEN_SEARCH_HOST_FOR_NGINX="$(echo "${OPEN_SEARCH_HOST}" | cut -d "/" -f 3 | cut -d ":" -f 1)"
if [[ ! -s ${CONFIG_NGINX_TEMPLATE} ]]; then
cat 'docker/nginx.conf' | envsubst '${OPEN_SEARCH_HOST_FOR_NGINX}' > ${CONFIG_NGINX_TEMPLATE};
mv "docker/fastcgi.conf" /etc/nginx/fastcgi.conf
chown nginx:nginx "/etc/nginx/fastcgi.conf"
chown nginx:nginx "/etc/nginx/http.d/librey.conf"
fi
# If it is empty or proxy is not enabled, we are using sed to delete
# any line that contains the string 'CURLOPT_PROXY' or 'CURLOPT_PROXYTYPE'
# from the file 'config.php' defined on top of 'attributes.sh'
if [[ -z "${CURLOPT_PROXY}" || "${CURLOPT_PROXY_ENABLED}" = false ]]; then
sed -i "/CURLOPT_PROXY/d" ${CONFIG_PHP_TEMPLATE};
sed -i "/CURLOPT_PROXYTYPE/d" ${CONFIG_PHP_TEMPLATE};
fi

26
docker/fastcgi.conf Normal file
View File

@ -0,0 +1,26 @@
# These settings should work well for serving as a front-end of many search engines
# on our PHP website. However, we may need to adjust them based on our specific requirements.
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param REDIRECT_STATUS 200;

21
docker/nginx.conf Normal file
View File

@ -0,0 +1,21 @@
server {
listen 8080;
server_name ${OPEN_SEARCH_HOST_FOR_NGINX} localhost;
add_header Content-Security-Policy "default-src 'none'; style-src 'self'; img-src 'self'";
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff";
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm82.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
}

9
docker/opensearch.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>${OPEN_SEARCH_TITLE}</ShortName>
<Description>${OPEN_SEARCH_DESCRIPTION}</Description>
<InputEncoding>${OPEN_SEARCH_ENCODING}</InputEncoding>
<LongName>${OPEN_SEARCH_LONG_NAME}</LongName>
<Url rel="results" type="text/html" method="get" template="${OPEN_SEARCH_HOST}/search.php?q={searchTerms}" />
<Url type="application/opensearchdescription+xml" rel="self" template="/opensearch.xml?method=GET" />
</OpenSearchDescription>

View File

@ -4,17 +4,89 @@
// Feel free to add your donation options here, but please don't remove mine.
?>
<title>LibreX - Donate</title>
<title>LibreY - Donate</title>
</head>
<body>
<div class="misc-container">
<h1>Donate to the developer</h1>
<h3>Bitcoin (BTC):</h3>
<p>bc1qs43kh6tvhch02dtsp7x7hcrwj8fwe4rzy7lp0h</p>
<img src="static/images/btc.png" alt="btc qr code" width="150" height="150"/>
<h3>Monero (XMR):</h3>
<p>41dGQr9EwZBfYBY3fibTtJZYfssfRuzJZDSVDeneoVcgckehK3BiLxAV4FvEVJiVqdiW996zvMxhFB8G8ot9nBFqQ84VkuC</p>
<img src="static/images/xmr.png" alt="xmr qr code" width="150" height="150"/>
<div class="donate-container">
<!-- librex dev -->
<h2>
Donate to the original developer of Libre<span class="Y">X</span>, a
project LibreY tries to improve.
</h2>
<div class="flexbox-column">
<div class="qr-box">
<div class="inner-wrap">
<h3>Bitcoin [BTC]</h3>
<p>bc1qs43kh6tvhch02dtsp7x7hcrwj8fwe4rzy7lp0h</p>
</div>
<img
src="/static/images/btc.png"
height="160"
width="160"
alt="btc qr code"
/>
</div>
<div class="qr-box">
<div class="inner-wrap">
<h3>Monero [XMR]</h3>
<p>
41dGQr9EwZBfYBY3fibTtJZYfssfRuzJZDSVDeneoVcgckehK3BiLxAV4FvEVJiVqdiW996zvMxhFB8G8ot9nBFqQ84VkuC
</p>
</div>
<img
src="/static/images/xmr.png"
height="160"
width="160"
alt="xmr qr code (hnhx)"
/>
</div>
<hr class="small-line" />
<!-- librey dev -->
<h2>
Donate to the person that forked LibreX into Libre<span class="Y"
>Y</span
>
</h2>
<div class="qr-box">
<div class="inner-wrap">
<h3>Monero [XMR]</h3>
<p>
4ArntPzKpu32s4z2XqYhyaY1eUeUBKtCzJqEqxWtF5mCi5vR6sdhh32Hd2fk9FjeUxYDtaaUexUqoRNxrgfrtuXs4XpgMNJ
</p>
</div>
<img
src="/static/images/xmr-ahwx.png"
height="160"
width="160"
alt="xmr qr code (ahwx)"
/>
</div>
<div class="flex-row">
<a href="https://ko-fi.com/Ahwxorg" target="_blank"
><img
src="/static/images/kofi.png"
alt="kifi img"
height="50"
width="auto"
/></a>
<a href="https://www.buymeacoffee.com/ahwx" target="_blank">
<img
src="/static/images/buy-me-a-coffee.png"
height="50"
width="auto"
alt="buy-me-a-coffee img"
/></a>
</div>
</div>
</div>
<?php require "misc/footer.php"; ?>

View File

@ -1,53 +1,40 @@
<?php
function get_hidden_service_results($query)
{
global $config;
require "engines/text/text.php";
$url = "https://ahmia.fi/search/?q=$query";
$response = request($url);
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//ol[@class='searchResults']//li[@class='result']") as $result)
{
$url = "http://" . $xpath->evaluate(".//cite", $result)[0]->textContent;
$title = remove_special($xpath->evaluate(".//h4", $result)[0]->textContent);
$description = $xpath->evaluate(".//p", $result)[0]->textContent;
array_push($results,
array (
"title" => $title ? htmlspecialchars($title) : "No description provided",
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => htmlspecialchars($description)
)
);
class TorSearch extends EngineRequest {
public function get_request_url() {
return "https://ahmia.fi/search/?q=" . urlencode($this->query);
}
return $results;
}
public function parse_results($response) {
$results = array();
$xpath = get_xpath($response);
function print_hidden_service_results($results)
{
echo "<div class=\"text-result-container\">";
if (!$xpath)
return $results;
foreach($results as $result)
{
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$description = $result["description"];
foreach($xpath->query("//ol[@class='searchResults']//li[@class='result']") as $result)
{
$url = "http://" . $xpath->evaluate(".//cite", $result)[0]->textContent;
$title = remove_special($xpath->evaluate(".//h4", $result)[0]->textContent);
$description = $xpath->evaluate(".//p", $result)[0]->textContent;
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
array_push($results,
array (
"title" => $title ? htmlspecialchars($title) : "No description provided",
"url" => htmlspecialchars($url),
// base_url is to be removed in the future, see #47
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => htmlspecialchars($description)
)
);
}
return $results;
}
echo "</div>";
public static function print_results($results, $opts) {
TextSearch::print_results($results, $opts);
}
}
?>

View File

@ -1,34 +1,38 @@
<?php
$_1337x_url = "https://1337x.to/search/$query/1/";
function get_1337x_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//table/tbody/tr") as $result)
{
$name = $xpath->evaluate(".//td[@class='coll-1 name']/a", $result)[1]->textContent;
$magnet = "/engines/bittorrent/get_magnet_1337x.php?url=https://1337x.to" . $xpath->evaluate(".//td[@class='coll-1 name']/a/@href", $result)[1]->textContent;
$size_unformatted = explode(" ", $xpath->evaluate(".//td[contains(@class, 'coll-4 size')]", $result)[0]->textContent);
$size = $size_unformatted[0] . " " . preg_replace("/[0-9]+/", "", $size_unformatted[1]);
$seeders = $xpath->evaluate(".//td[@class='coll-2 seeds']", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//td[@class='coll-3 leeches']", $result)[0]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "1337x.to"
)
);
class _1337xRequest extends EngineRequest {
public function get_request_url() {
$query = urlencode($this->query);
return "https://1337x.to/search/$query/1/";
}
return $results;
public function parse_results($response) {
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//table/tbody/tr") as $result) {
$name = $xpath->evaluate(".//td[@class='coll-1 name']/a", $result)[1]->textContent;
$magnet = "./engines/bittorrent/get_magnet_1337x.php?url=https://1337x.to" . $xpath->evaluate(".//td[@class='coll-1 name']/a/@href", $result)[1]->textContent;
$size_unformatted = explode(" ", $xpath->evaluate(".//td[contains(@class, 'coll-4 size')]", $result)[0]->textContent);
$size = $size_unformatted[0] . " " . preg_replace("/[0-9]+/", "", $size_unformatted[1]);
$seeders = $xpath->evaluate(".//td[@class='coll-2 seeds']", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//td[@class='coll-3 leeches']", $result)[0]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "1337x.to"
)
);
}
return $results;
}
}
?>

View File

@ -1,84 +1,48 @@
<?php
class TorrentSearch extends EngineRequest {
public function __construct($opts, $mh) {
parent::__construct($opts, $mh);
function get_merged_torrent_results($query)
{
global $config;
require "engines/bittorrent/thepiratebay.php";
require "engines/bittorrent/rutor.php";
require "engines/bittorrent/yts.php";
require "engines/bittorrent/torrentgalaxy.php";
require "engines/bittorrent/1337x.php";
require "engines/bittorrent/sukebei.php";
require "engines/bittorrent/thepiratebay.php";
require "engines/bittorrent/rutor.php";
require "engines/bittorrent/nyaa.php";
require "engines/bittorrent/yts.php";
require "engines/bittorrent/torrentgalaxy.php";
require "engines/bittorrent/1337x.php";
$query = urlencode($query);
$torrent_urls = array(
$thepiratebay_url,
$rutor_url,
$nyaa_url,
$yts_url,
$torrentgalaxy_url,
$_1337x_url
);
$mh = curl_multi_init();
$chs = $results = array();
foreach ($torrent_urls as $url)
{
$ch = curl_init($url);
curl_setopt_array($ch, $config->curl_settings);
array_push($chs, $ch);
curl_multi_add_handle($mh, $ch);
$this->requests = array(
new PirateBayRequest($opts, $mh),
new _1337xRequest($opts, $mh),
new NyaaRequest($opts, $mh),
new RutorRequest($opts, $mh),
new SukebeiRequest($opts, $mh),
new TorrentGalaxyRequest($opts, $mh),
new YTSRequest($opts, $mh),
);
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
for ($i=0; count($chs)>$i; $i++)
{
$response = curl_multi_getcontent($chs[$i]);
switch ($i)
{
case 0:
$results = array_merge($results, get_thepiratebay_results($response));
break;
case 1:
$results = array_merge($results, get_rutor_results($response));
break;
case 2:
$results = array_merge($results, get_nyaa_results($response));
break;
case 3:
$results = array_merge($results, get_yts_results($response));
break;
case 4:
$results = array_merge($results, get_torrentgalaxy_results($response));
break;
case 5:
$results = array_merge($results, get_1337x_results($response));
break;
public function parse_results($response) {
$results = array();
foreach ($this->requests as $request) {
if ($request->successful())
$results = array_merge($results, $request->get_results());
}
$seeders = array_column($results, "seeders");
array_multisort($seeders, SORT_DESC, $results);
return $results;
}
$seeders = array_column($results, "seeders");
array_multisort($seeders, SORT_DESC, $results);
return $results;
}
public static function print_results($results, $opts) {
echo "<div class=\"text-result-container\">";
function print_merged_torrent_results($results)
{
echo "<div class=\"text-result-container\">";
if (empty($results)) {
echo "<p>There are no results. Please try different keywords!</p>";
return;
}
if (!empty($results))
{
foreach($results as $result)
{
foreach($results as $result) {
$source = $result["source"];
$name = $result["name"];
$magnet = $result["magnet"];
@ -96,11 +60,9 @@
echo "$size</span>";
echo "</div>";
}
}
else
echo "<p>There are no results. Please try different keywords!</p>";
echo "</div>";
echo "</div>";
}
}
?>

View File

@ -1,35 +1,52 @@
<?php
$nyaa_url = "https://nyaa.si/?q=$query";
class NyaaRequest extends EngineRequest {
public $SOURCE = "nyaa.si";
function get_nyaa_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//tbody/tr") as $result)
{
$name = $xpath->evaluate(".//td[@colspan='2']//a[not(contains(@class, 'comments'))]/@title", $result)[0]->textContent;
$centered = $xpath->evaluate(".//td[@class='text-center']", $result);
$magnet = $xpath->evaluate(".//a[2]/@href", $centered[0])[0]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
$size = $centered[1]->textContent;
$seeders = $centered[3]->textContent;
$leechers = $centered[4]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "nyaa.si"
)
);
public function get_request_url() {
return "https://$this->SOURCE/?q=" . urlencode($this->query);
}
return $results;
public function parse_results($response) {
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//tbody/tr") as $result)
{
$name_node = $xpath->evaluate(".//td[@colspan='2']//a[not(contains(@class, 'comments'))]/@title", $result);
if ($name_node->length > 0) {
$name = $name_node[0]->textContent;
} else {
$name = "";
}
$centered = $xpath->evaluate(".//td[@class='text-center']", $result);
$magnet_node = $xpath->evaluate(".//a[2]/@href", $centered[0]);
if ($magnet_node->length > 0) {
$magnet = $magnet_node[0]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $this->opts->bittorent_trackers;
} else {
$magnet = "";
}
$size = $centered[1]->textContent;
$seeders = $centered[3]->textContent;
$leechers = $centered[4]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => $this->SOURCE
)
);
}
return $results;
}
}
?>

View File

@ -1,36 +1,40 @@
<?php
$rutor_url = "http://rutor.info/search/$query";
function get_rutor_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//table/tr[@class='gai' or @class='tum']") as $result)
{
$name = $xpath->evaluate(".//td/a", $result)[2]->textContent;
$magnet = $xpath->evaluate(".//td/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
$size = $xpath->evaluate(".//td", $result)[3]->textContent;
$seeders = $xpath->evaluate(".//span", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//span", $result)[1]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) remove_special($seeders),
"leechers" => (int) remove_special($leechers),
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "rutor.info"
)
);
class RutorRequest extends EngineRequest {
public function get_request_url() {
return "http://rutor.info/search/" . urlencode($this->query);
}
return $results;
public function parse_results($response) {
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//table/tr[@class='gai' or @class='tum']") as $result)
{
$name = $xpath->evaluate(".//td/a", $result)[2]->textContent;
$magnet = $xpath->evaluate(".//td/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $this->opts->bittorrent_trackers;
$td = $xpath->evaluate(".//td", $result);
$size = $td[count($td) == 5 ? 3 : 2]->textContent;
$seeders = $xpath->evaluate(".//span", $result)[0]->textContent;
$leechers = $xpath->evaluate(".//span", $result)[1]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) filter_var($seeders, FILTER_SANITIZE_NUMBER_INT),
"leechers" => (int) filter_var($leechers, FILTER_SANITIZE_NUMBER_INT),
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "rutor.info"
)
);
}
return $results;
}
}
?>

View File

@ -0,0 +1,6 @@
<?php
include "engines/bittorrent/nyaa.php";
class SukebeiRequest extends NyaaRequest {
public $SOURCE = "sukebei.nyaa.si";
}
?>

View File

@ -1,44 +1,45 @@
<?php
class PirateBayRequest extends EngineRequest {
public function get_request_url() {
return "https://apibay.org/q.php?q=" . urlencode($this->query);
}
$thepiratebay_url = "https://apibay.org/q.php?q=$query";
public function parse_results($response) {
$results = array();
$json_response = json_decode($response, true);
function get_thepiratebay_results($response)
{
global $config;
$results = array();
$json_response = json_decode($response, true);
if (empty($json_response))
{
return $results;
}
foreach ($json_response as $response)
{
$size = human_filesize($response["size"]);
$hash = $response["info_hash"];
$name = $response["name"];
$seeders = (int) $response["seeders"];
$leechers = (int) $response["leechers"];
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name" . $this->opts->bittorrent_trackers;
if ($name == "No results returned")
break;
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => (int) htmlspecialchars($seeders),
"leechers" => (int) htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "thepiratebay.org"
)
);
}
if (empty($json_response))
{
return $results;
}
foreach ($json_response as $response)
{
$size = human_filesize($response["size"]);
$hash = $response["info_hash"];
$name = $response["name"];
$seeders = (int) $response["seeders"];
$leechers = (int) $response["leechers"];
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name" . $config->bittorent_trackers;
if ($name == "No results returned")
break;
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => (int) htmlspecialchars($seeders),
"leechers" => (int) htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "thepiratebay.org"
)
);
}
return $results;
}
?>

View File

@ -1,34 +1,40 @@
<?php
$torrentgalaxy_url = "https://torrentgalaxy.to/torrents.php?search=$query#results";
function get_torrentgalaxy_results($response)
{
global $config;
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//div[@class='tgxtablerow txlight']") as $result)
{
$name = $xpath->evaluate(".//div[contains(@class, 'clickable-row')]", $result)[0]->textContent;
$magnet = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $config->bittorent_trackers;
$size = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span", $result)[0]->textContent;
$seeders = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[1]->textContent;
$leechers = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[2]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "torrentgalaxy.to"
)
);
class TorrentGalaxyRequest extends EngineRequest {
public function get_request_url() {
$query = urlencode($this->query);
return "https://torrentgalaxy.to/torrents.php?search=$query#results";
}
return $results;
public function parse_results($response) {
$xpath = get_xpath($response);
$results = array();
if (!$xpath)
return $results;
foreach($xpath->query("//div[@class='tgxtablerow txlight']") as $result)
{
$name = $xpath->evaluate(".//div[contains(@class, 'clickable-row')]", $result)[0]->textContent;
$magnet = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/a/@href", $result)[1]->textContent;
$magnet_without_tracker = explode("&tr=", $magnet)[0];
$magnet = $magnet_without_tracker . $this->opts->bittorrent_trackers;
$size = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span", $result)[0]->textContent;
$seeders = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[1]->textContent;
$leechers = $xpath->evaluate(".//div[@class='tgxtablecell collapsehide rounded txlight']/span/font", $result)[2]->textContent;
array_push($results,
array (
"name" => htmlspecialchars($name),
"seeders" => (int) $seeders,
"leechers" => (int) $leechers,
"magnet" => htmlspecialchars($magnet),
"size" => htmlspecialchars($size),
"source" => "torrentgalaxy.to"
)
);
}
return $results;
}
}
?>

View File

@ -1,14 +1,17 @@
<?php
$yts_url = "https://yts.mx/api/v2/list_movies.json?query_term=$query";
class YTSRequest extends EngineRequest {
public function get_request_url() {
return "https://yts.mx/api/v2/list_movies.json?query_term=" . urlencode($this->query);
}
function get_yts_results($response)
{
global $config;
$results = array();
$json_response = json_decode($response, true);
public function parse_results($response) {
$response = curl_multi_getcontent($this->ch);
$results = array();
$json_response = json_decode($response, true);
if ($json_response["status"] != "ok" || $json_response["data"]["movie_count"] == 0)
return $results;
if ($json_response["status"] == "ok" && $json_response["data"]["movie_count"] != 0)
{
foreach ($json_response["data"]["movies"] as $movie)
{
$name = $movie["title"];
@ -22,24 +25,22 @@
$leechers = $torrent["peers"];
$size = $torrent["size"];
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name_encoded$config->bittorent_trackers";
$magnet = "magnet:?xt=urn:btih:$hash&dn=$name_encoded$this->opts->bittorrent_trackers";
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => htmlspecialchars($seeders),
"leechers" => htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "yts.mx"
)
);
array_push($results,
array (
"size" => htmlspecialchars($size),
"name" => htmlspecialchars($name),
"seeders" => htmlspecialchars($seeders),
"leechers" => htmlspecialchars($leechers),
"magnet" => htmlspecialchars($magnet),
"source" => "yts.mx"
)
);
}
}
}
return $results;
return $results;
}
}
?>

View File

@ -1,65 +0,0 @@
<?php
function get_video_results($query)
{
global $config;
$url = "https://search.brave.com/videos?q=$query&source=web";
$response = request($url);
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//div[@id='results']//div[@class='card']") as $result)
{
$url = $xpath->evaluate(".//a/@href", $result)[0]->textContent;
$title = $xpath->evaluate(".//div/@title", $result)[0]->textContent;
$views = $xpath->evaluate(".//div/@title", $result)[1]->textContent;
$date = $xpath->evaluate(".//div//span", $result)[0]->textContent;
$thumbnail_raw1 = $xpath->evaluate(".//div/@style", $result)[0]->textContent;
$thumbnail_raw2 = explode("url('", $thumbnail_raw1)[1];
$thumbnail = explode("'), url", $thumbnail_raw2)[0];
$url = check_for_privacy_frontend($url);
array_push($results,
array (
"title" => htmlspecialchars($title),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"views" => htmlspecialchars($views),
"date" => htmlspecialchars($date),
"thumbnail" => htmlspecialchars($thumbnail)
)
);
}
return $results;
}
function print_video_results($results)
{
echo "<div class=\"text-result-container\">";
foreach($results as $result)
{
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$views = $result["views"];
$date = $result["date"];
$thumbnail = $result["thumbnail"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "<img class=\"video-img\" src=\"image_proxy.php?url=$thumbnail\">";
echo "<br>";
echo "<span>$date - $views</span>";
echo "</a>";
echo "</div>";
}
echo "</div>";
}
?>

View File

@ -1,177 +0,0 @@
<?php
function get_text_results($query, $page)
{
global $config;
$mh = curl_multi_init();
$query_encoded = urlencode($query);
$results = array();
$url = "https://www.google.$config->google_domain/search?&q=$query_encoded&start=$page&hl=$config->google_language";
$google_ch = curl_init($url);
curl_setopt_array($google_ch, $config->curl_settings);
curl_multi_add_handle($mh, $google_ch);
$special_search = $page ? 0 : check_for_special_search($query);
$special_ch = null;
$url = null;
if ($special_search != 0)
{
switch ($special_search)
{
case 1:
$url = "https://cdn.moneyconvert.net/api/latest.json";
break;
case 2:
$split_query = explode(" ", $query);
$reversed_split_q = array_reverse($split_query);
$word_to_define = $reversed_split_q[1];
$url = "https://api.dictionaryapi.dev/api/v2/entries/en/$word_to_define";
break;
case 5:
$url = "https://wttr.in/@" . $_SERVER["REMOTE_ADDR"] . "?format=j1";
break;
case 6:
$url = "https://check.torproject.org/torbulkexitlist";
break;
case 7:
$url = "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
break;
}
if ($url != NULL)
{
$special_ch = curl_init($url);
curl_setopt_array($special_ch, $config->curl_settings);
curl_multi_add_handle($mh, $special_ch);
}
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
if ($special_search != 0)
{
$special_result = null;
switch ($special_search)
{
case 1:
require "engines/special/currency.php";
$special_result = currency_results($query, curl_multi_getcontent($special_ch));
break;
case 2:
require "engines/special/definition.php";
$special_result = definition_results($query, curl_multi_getcontent($special_ch));
break;
case 3:
require "engines/special/ip.php";
$special_result = ip_result();
break;
case 4:
require "engines/special/user_agent.php";
$special_result = user_agent_result();
break;
case 5:
require "engines/special/weather.php";
$special_result = weather_results(curl_multi_getcontent($special_ch));
break;
case 6:
require "engines/special/tor.php";
$special_result = tor_result(curl_multi_getcontent($special_ch));
break;
case 7:
require "engines/special/wikipedia.php";
$special_result = wikipedia_results($query, curl_multi_getcontent($special_ch));
break;
}
if ($special_result != null)
array_push($results, $special_result);
}
$xpath = get_xpath(curl_multi_getcontent($google_ch));
foreach($xpath->query("//div[@id='search']//div[contains(@class, 'g')]") as $result)
{
$url = $xpath->evaluate(".//div[@class='yuRUbf']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) // filter duplicate results, ignore special result
{
if (!array_key_exists("special_response", end($results)))
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$url = check_for_privacy_frontend($url);
$title = $xpath->evaluate(".//h3", $result)[0];
$description = $xpath->evaluate(".//div[contains(@class, 'VwiC3b')]", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
return $results;
}
function print_text_results($results)
{
$special = $results[0];
if (array_key_exists("special_response", $special))
{
$response = $special["special_response"]["response"];
$source = $special["special_response"]["source"];
echo "<p class=\"special-result-container\">";
if (array_key_exists("image", $special["special_response"]))
{
$image_url = $special["special_response"]["image"];
echo "<img src=\"image_proxy.php?url=$image_url\">";
}
echo $response;
if ($source)
echo "<a href=\"$source\" target=\"_blank\">$source</a>";
echo "</p>";
array_shift($results);
}
echo "<div class=\"text-result-container\">";
foreach($results as $result)
{
$title = $result["title"];
$url = $result["url"];
$base_url = $result["base_url"];
$description = $result["description"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
}
echo "</div>";
}
?>

View File

@ -0,0 +1,67 @@
<?php
class VideoSearch extends EngineRequest {
public function get_request_url() {
$this->instance_url = $this->opts->invidious_instance_for_video_results;
$query = urlencode($this->query);
return "$this->instance_url/api/v1/search?q=$query";
}
public function parse_results($response) {
$results = array();
$json_response = json_decode($response, true);
foreach ($json_response as $response) {
if ($response["type"] == "video") {
$title = $response["title"];
$url = "https://youtube.com/watch?v=" . $response["videoId"];
$uploader = $response["author"];
$views = $response["viewCount"];
$date = $response["publishedText"];
$thumbnail = $this->instance_url . "/vi/" . explode("/vi/" ,$response["videoThumbnails"][4]["url"])[1];
array_push($results,
array (
"title" => htmlspecialchars($title),
"url" => htmlspecialchars($url),
// base_url is to be removed in the future, see #47
"base_url" => htmlspecialchars(get_base_url($url)),
"uploader" => htmlspecialchars($uploader),
"views" => htmlspecialchars($views),
"date" => htmlspecialchars($date),
"thumbnail" => htmlspecialchars($thumbnail)
)
);
}
}
return $results;
}
public static function print_results($results, $opts) {
echo "<div class=\"text-result-container\">";
foreach($results as $result) {
$title = $result["title"];
$url = $result["url"];
$url = check_for_privacy_frontend($url, $opts);
$base_url = get_base_url($url);
$uploader = $result["uploader"];
$views = $result["views"];
$date = $result["date"];
$thumbnail = $result["thumbnail"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "<img class=\"video-img\" src=\"image_proxy.php?url=$thumbnail\">";
echo "<br>";
echo "<span>$uploader - $date - $views views</span>";
echo "</a>";
echo "</div>";
}
echo "</div>";
}
}
?>

View File

@ -0,0 +1,75 @@
<?php
class LibreXFallback extends EngineRequest {
public function __construct($instance, $opts, $mh) {
$this->instance = $instance;
parent::__construct($opts, $mh);
}
public function get_request_url() {
return $this->instance . "api.php?" . opts_to_params($this->opts) . "&nfb=1";
}
public function parse_results($response) {
$response = json_decode($response, true);
if (!$response)
return array();
return array_values($response);
}
}
function load_instances($cooldowns) {
$instances_json = json_decode(file_get_contents("instances.json"), true);
if (empty($instances_json["instances"]))
return array();
$instances = array_map(fn($n) => $n['clearnet'], array_filter($instances_json['instances'], fn($n) => !is_null($n['clearnet'])));
$instances = array_filter($instances, fn($n) => !has_cooldown($n, $cooldowns));
shuffle($instances);
return $instances;
}
function get_librex_results($opts) {
if (!$opts->do_fallback)
return array();
$cooldowns = $opts->cooldowns;
$instances = load_instances($cooldowns);
$results = array();
$tries = 0;
do {
$tries++;
$instance = array_pop($instances);
if (!$instance)
break;
if (parse_url($instance)["host"] == parse_url($_SERVER['HTTP_HOST'])["host"])
continue;
$librex_request = new LibreXFallback($instance, $opts, null);
$results = $librex_request->get_results();
if (!empty($results))
return $results;
// on fail then do this
$timeout = ($opts->request_cooldown ?? "1") * 60;
$cooldowns = set_cooldown($instance, $timeout, $cooldowns);
} while (!empty($instances));
return array(
"error" => array(
"message" => "No results found. Unable to fallback to other instances."
)
);
}
?>

View File

@ -1,60 +1,63 @@
<?php
function get_image_results($query, $page)
{
global $config;
$page = $page / 10 + 1; // qwant has a different page system
$url = "https://lite.qwant.com/?q=$query&t=images&p=$page";
$response = request($url);
$xpath = get_xpath($response);
$results = array();
foreach($xpath->query("//a[@rel='noopener']") as $result)
{
$image = $xpath->evaluate(".//img", $result)[0];
if ($image)
{
$encoded_url = $result->getAttribute("href");
$encoded_url_split1 = explode("==/", $encoded_url)[1];
$encoded_url_split2 = explode("?position", $encoded_url_split1)[0];
$real_url = urldecode(base64_decode($encoded_url_split2));
$real_url = check_for_privacy_frontend($real_url);
$alt = $image->getAttribute("alt");
$thumbnail = urlencode($image->getAttribute("src"));
array_push($results,
array (
"thumbnail" => urldecode(htmlspecialchars($thumbnail)),
"alt" => htmlspecialchars($alt),
"url" => htmlspecialchars($real_url)
)
);
}
class QwantImageSearch extends EngineRequest {
public function get_request_url() {
$page = $this->page / 10 + 1; // qwant has a different page system
$query = urlencode($this->query);
return "https://lite.qwant.com/?q=$query&t=images&p=$page";
}
return $results;
}
public function parse_results($response) {
$results = array();
$xpath = get_xpath($response);
function print_image_results($results)
{
echo "<div class=\"image-result-container\">";
if (!$xpath)
return $results;
foreach($results as $result)
{
$thumbnail = urlencode($result["thumbnail"]);
$alt = $result["alt"];
$url = $result["url"];
foreach($xpath->query("//a[@rel='noopener']") as $result)
{
$image = $xpath->evaluate(".//img", $result)[0];
echo "<a title=\"$alt\" href=\"$url\" target=\"_blank\">";
echo "<img src=\"image_proxy.php?url=$thumbnail\">";
echo "</a>";
if ($image)
{
$encoded_url = $result->getAttribute("href");
$encoded_url_split1 = explode("==/", $encoded_url)[1];
$encoded_url_split2 = explode("?position", $encoded_url_split1)[0];
$real_url = urldecode(base64_decode($encoded_url_split2));
$alt = $image->getAttribute("alt");
$thumbnail = urlencode($image->getAttribute("src"));
array_push($results,
array (
"thumbnail" => urldecode(htmlspecialchars($thumbnail)),
"alt" => htmlspecialchars($alt),
"url" => htmlspecialchars($real_url)
)
);
}
}
echo "</div>";
return $results;
}
public static function print_results($results, $opts) {
echo "<div class=\"image-result-container\">";
foreach($results as $result)
{
$thumbnail = urlencode($result["thumbnail"]);
$alt = $result["alt"];
$url = $result["url"];
$url = check_for_privacy_frontend($url, $opts);
echo "<a title=\"$alt\" href=\"$url\" target=\"_blank\">";
echo "<img src=\"image_proxy.php?url=$thumbnail\">";
echo "</a>";
}
echo "</div>";
}
}
?>

View File

@ -1,18 +1,22 @@
<?php
function currency_results($query, $response)
{
$split_query = explode(" ", $query);
$base_currency = strtoupper($split_query[1]);
$currency_to_convert = strtoupper($split_query[3]);
$amount_to_convert = floatval($split_query[0]);
class CurrencyRequest extends EngineRequest {
public function get_request_url() {
return "https://cdn.moneyconvert.net/api/latest.json";
}
$json_response = json_decode($response, true);
$rates = $json_response["rates"];
public function parse_results($response) {
$split_query = explode(" ", $this->query);
if (array_key_exists($base_currency, $rates) && array_key_exists($currency_to_convert, $rates))
{
$base_currency = strtoupper($split_query[1]);
$currency_to_convert = strtoupper($split_query[3]);
$amount_to_convert = floatval($split_query[0]);
$json_response = json_decode($response, true);
$rates = $json_response["rates"];
if (!array_key_exists($base_currency, $rates) || !array_key_exists($currency_to_convert, $rates))
return array();
$base_currency_response = $rates[$base_currency];
$currency_to_convert_response = $rates[$currency_to_convert];
@ -26,6 +30,6 @@
"source" => $source
)
);
}
}
}
?>

View File

@ -1,10 +1,14 @@
<?php
function definition_results($query, $response)
{
$split_query = explode(" ", $query);
class DefinitionRequest extends EngineRequest {
public function get_request_url() {
$split_query = explode(" ", $this->query);
$reversed_split_q = array_reverse($split_query);
$word_to_define = $reversed_split_q[1];
return "https://api.dictionaryapi.dev/api/v2/entries/en/$word_to_define";
}
public function parse_results($response) {
$json_response = json_decode($response, true);
if (!array_key_exists("title", $json_response))
@ -20,5 +24,6 @@
);
}
}
}
?>

View File

@ -1,11 +1,12 @@
<?php
function ip_result()
{
class IPRequest extends EngineRequest {
public function parse_results($response) {
return array(
"special_response" => array(
"response" => $_SERVER["REMOTE_ADDR"],
"source" => null
)
);
}
}
?>

View File

@ -0,0 +1,91 @@
<?php
function check_for_special_search($query) {
if (isset($_COOKIE["disable_special"]))
return 0;
$query_lower = strtolower($query);
$split_query = explode(" ", $query);
if (strpos($query_lower, "to") && count($split_query) >= 4) // currency
{
$amount_to_convert = floatval($split_query[0]);
if ($amount_to_convert != 0)
return 1;
}
else if (strpos($query_lower, "mean") && count($split_query) >= 2) // definition
{
return 2;
}
else if (strpos($query_lower, "my") !== false)
{
if (strpos($query_lower, "ip"))
{
return 3;
}
else if (strpos($query_lower, "user agent") || strpos($query_lower, "ua"))
{
return 4;
}
}
else if (strpos($query_lower, "weather") !== false)
{
return 5;
}
else if ($query_lower == "tor")
{
return 6;
}
else if (3 > count(explode(" ", $query))) // wikipedia
{
return 7;
}
return 0;
}
function get_special_search_request($opts, $mh) {
if ($opts->page != 0)
return null;
$special_search = check_for_special_search($opts->query);
$special_request = null;
$url = null;
if ($special_search == 0)
return null;
switch ($special_search) {
case 1:
require "engines/special/currency.php";
$special_request = new CurrencyRequest($opts, $mh);
break;
case 2:
require "engines/special/definition.php";
$special_request = new DefinitionRequest($opts, $mh);
break;
case 3:
require "engines/special/ip.php";
$special_request = new IPRequest($opts, $mh);
break;
case 4:
require "engines/special/user_agent.php";
$special_request = new UserAgentRequest($opts, $mh);
break;
case 5:
require "engines/special/weather.php";
$special_request = new WeatherRequest($opts, $mh);
break;
case 6:
require "engines/special/tor.php";
$special_request = new TorRequest($opts, $mh);
break;
case 7:
require "engines/special/wikipedia.php";
$special_request = new WikipediaRequest($opts, $mh);
break;
}
return $special_request;
}
?>

View File

@ -1,18 +1,20 @@
<?php
function tor_result($response)
{
$formatted_response = "It seems like you are not using Tor";
if (strpos($response, $_SERVER["REMOTE_ADDR"]) !== false)
{
$formatted_response = "It seems like you are using Tor";
}
class TorRequest extends EngineRequest {
public function get_request_url() {
return "https://check.torproject.org/torbulkexitlist";
}
public function parse_results($response) {
$formatted_response = strpos($response, $_SERVER["REMOTE_ADDR"]) ? "It seems like you are using Tor" : "It seems like you are not using Tor";
$source = "https://check.torproject.org";
return array(
"special_response" => array(
"response" => $formatted_response,
"source" => $source
)
);
}
}
?>

View File

@ -1,11 +1,12 @@
<?php
function user_agent_result()
{
class UserAgentRequest extends EngineRequest {
public function parse_results($response) {
return array(
"special_response" => array(
"response" => $_SERVER["HTTP_USER_AGENT"],
"source" => null
)
);
}
}
?>

View File

@ -1,26 +1,30 @@
<?php
function weather_results($response)
{
class WeatherRequest extends EngineRequest {
public function get_request_url () {
return "https://wttr.in/@" . $_SERVER["REMOTE_ADDR"] . "?format=j1";
}
public function parse_results($response) {
$json_response = json_decode($response, true);
if ($json_response)
{
$current_weather = $json_response["current_condition"][0];
if (!$json_response)
return array();
$temp_c = $current_weather["temp_C"];
$temp_f = $current_weather["temp_F"];
$description = $current_weather["weatherDesc"][0]["value"];
$current_weather = $json_response["current_condition"][0];
$formatted_response = "$description - $temp_c °C | $temp_f °F";
$temp_c = $current_weather["temp_C"];
$temp_f = $current_weather["temp_F"];
$description = $current_weather["weatherDesc"][0]["value"];
$source = "https://wttr.in";
return array(
"special_response" => array(
"response" => htmlspecialchars($formatted_response),
"source" => $source
)
);
}
$formatted_response = "$description - $temp_c °C | $temp_f °F";
$source = "https://wttr.in";
return array(
"special_response" => array(
"response" => htmlspecialchars($formatted_response),
"source" => $source
)
);
}
}
?>

View File

@ -1,17 +1,28 @@
<?php
function wikipedia_results($query, $response)
{
$query_encoded = urlencode($query);
class WikipediaRequest extends EngineRequest {
public function get_request_url() {
$this->wikipedia_domain = "wikipedia.org";
$query_encoded = urlencode($this->query);
$json_response = json_decode($response, true);
$languages = json_decode(file_get_contents("static/misc/languages.json"), true);
$first_page = array_values($json_response["query"]["pages"])[0];
if (array_key_exists($this->opts->language, $languages))
$this->wikipedia_domain = $languages[$this->opts->language]["wikipedia"] . ".wikipedia.org";
return "https://$this->wikipedia_domain/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
}
public function parse_results($response) {
$json_response = json_decode($response, true);
$first_page = array_values($json_response["query"]["pages"])[0];
if (array_key_exists("missing", $first_page))
return array();
if (!array_key_exists("missing", $first_page))
{
$description = substr($first_page["extract"], 0, 250) . "...";
$source = check_for_privacy_frontend("https://en.wikipedia.org/wiki/$query");
$source = "https://$this->wikipedia_domain/wiki/$this->query";
$response = array(
"special_response" => array(
"response" => htmlspecialchars($description),
@ -19,8 +30,7 @@
)
);
if (array_key_exists("thumbnail", $first_page))
{
if (array_key_exists("thumbnail", $first_page)) {
$image_url = $first_page["thumbnail"]["source"];
$response["special_response"]["image"] = $image_url;
}

View File

@ -0,0 +1,65 @@
<?php
class DuckDuckGoRequest extends EngineRequest {
function get_request_url()
{
$query_encoded = str_replace("%22", "\"", urlencode($this->query));
$results = array();
$domain = 'com';
$results_language = $this->opts->language;
$number_of_results = $this->opts->number_of_results;
$url = "https://html.duckduckgo.$domain/html/?q=$query_encoded&kd=-1&s=" . 3 * $this->page;
if (3 > strlen($results_language) && 0 < strlen($results_language))
$url .= "&lr=lang_$results_language";
if (3 > strlen($number_of_results) && 0 < strlen($number_of_results))
$url .= "&num=$number_of_results";
if (isset($_COOKIE["safe_search"]))
$url .= "&safe=medium";
return $url;
}
public function parse_results($response) {
$results = array();
$xpath = get_xpath($response);
if (!$xpath)
return $results;
foreach($xpath->query("/html/body/div[1]/div[". count($xpath->query('/html/body/div[1]/div')) ."]/div/div/div[contains(@class, 'web-result')]/div") as $result) {
$url = $xpath->evaluate(".//h2[@class='result__title']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) { // filter duplicate results
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$title = $xpath->evaluate(".//h2[@class='result__title']", $result)[0];
$description = $xpath->evaluate(".//a[@class='result__snippet']", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
// base_url is to be removed in the future, see #47
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
return $results;
}
}
?>

82
engines/text/google.php Normal file
View File

@ -0,0 +1,82 @@
<?php
class GoogleRequest extends EngineRequest {
public function get_request_url() {
$query_encoded = str_replace("%22", "\"", urlencode($this->query));
$results = array();
$domain = $this->opts->google_domain;
$results_language = $this->opts->language;
$number_of_results = $this->opts->number_of_results;
$url = "https://www.google.$domain/search?q=$query_encoded&nfpr=1&start=$this->page";
if (3 > strlen($results_language) && 0 < strlen($results_language)) {
$url .= "&lr=lang_$results_language";
$url .= "&hl=$results_language";
}
if (3 > strlen($number_of_results) && 0 < strlen($number_of_results))
$url .= "&num=$number_of_results";
if (isset($_COOKIE["safe_search"]))
$url .= "&safe=medium";
return $url;
}
public function parse_results($response) {
$results = array();
$xpath = get_xpath($response);
if (!$xpath)
return $results;
$didyoumean = $xpath->query(".//a[@class='gL9Hy']")[0];
if (!is_null($didyoumean))
array_push($results, array(
"did_you_mean" => $didyoumean->textContent
));
foreach($xpath->query("//div[@id='search']//div[contains(@class, 'g')]") as $result) {
$url = $xpath->evaluate(".//div[@class='yuRUbf']//a/@href", $result)[0];
if ($url == null)
continue;
if (!empty($results)) // filter duplicate results, ignore special result
{
if (end($results)["url"] == $url->textContent)
continue;
}
$url = $url->textContent;
$title = $xpath->evaluate(".//h3", $result)[0];
$description = $xpath->evaluate(".//div[contains(@class, 'VwiC3b')]", $result)[0];
array_push($results,
array (
"title" => htmlspecialchars($title->textContent),
"url" => htmlspecialchars($url),
// base_url is to be removed in the future, see #47
"base_url" => htmlspecialchars(get_base_url($url)),
"description" => $description == null ?
"No description was provided for this site." :
htmlspecialchars($description->textContent)
)
);
}
if (empty($results) && !str_contains($response, "Our systems have detected unusual traffic from your computer network.")) {
$results["error"] = array(
"message" => "There are no results. Please try different keywords!"
);
}
return $results;
}
}
?>

153
engines/text/text.php Normal file
View File

@ -0,0 +1,153 @@
<?php
class TextSearch extends EngineRequest {
public function __construct($opts, $mh) {
$this->query = $opts->query;
$this->page = $opts->page;
$this->opts = $opts;
$this->engine = $opts->preferred_engines["text"] ?? "google";
$query_parts = explode(" ", $this->query);
$last_word_query = end($query_parts);
if (substr($this->query, 0, 1) == "!" || substr($last_word_query, 0, 1) == "!")
check_ddg_bang($this->query, $opts);
if ($this->engine == "google") {
require "engines/text/google.php";
$this->engine_request = new GoogleRequest($opts, $mh);
}
if ($this->engine == "duckduckgo") {
require "engines/text/duckduckgo.php";
$this->engine_request = new DuckDuckGoRequest($opts, $mh);
}
if (has_cooldown($this->engine, $this->opts->cooldowns) && !has_cached_results($this->engine_request->url)) {
// TODO dont add it in the first place
curl_multi_remove_handle($mh, $this->engine_request->ch);
$this->engine_request = null;
return;
}
require "engines/special/special.php";
$this->special_request = get_special_search_request($opts, $mh);
}
public function parse_results($response) {
if (!isset($this->engine_request))
return array();
$results = $this->engine_request->get_results();
if (empty($results)) {
set_cooldown($this->engine, ($opts->request_cooldown ?? "1") * 60, $this->opts->cooldowns);
} else {
if ($this->special_request) {
$special_result = $this->special_request->get_results();
if ($special_result)
$results = array_merge(array($special_result), $results);
}
}
return $results;
}
public static function print_results($results, $opts) {
if (empty($results)) {
echo "<div class=\"text-result-container\"><p>An error occured fetching results</p></div>";
return;
}
if (array_key_exists("error", $results)) {
echo "<div class=\"text-result-container\"><p>" . $results["error"]["message"] . "</p></div>";
return;
}
$special = $results[0];
if (array_key_exists("did_you_mean", $special)) {
$didyoumean = $special["did_you_mean"];
$new_url = "/search.php?q=" . urlencode($didyoumean);
echo "<p class=\"did-you-mean\">Did you mean ";
echo "<a href=\"$new_url\">$didyoumean</a>";
echo "?</p>";
}
if (array_key_exists("special_response", $special)) {
$response = $special["special_response"]["response"];
$source = $special["special_response"]["source"];
echo "<p class=\"special-result-container\">";
if (array_key_exists("image", $special["special_response"])) {
$image_url = $special["special_response"]["image"];
echo "<img src=\"image_proxy.php?url=$image_url\">";
}
echo $response;
if ($source) {
$source = check_for_privacy_frontend($source, $opts);
echo "<a href=\"$source\" target=\"_blank\">$source</a>";
}
echo "</p>";
}
echo "<div class=\"text-result-container\">";
foreach($results as $result) {
if (!array_key_exists("title", $result))
continue;
$title = $result["title"];
$url = $result["url"];
$url = check_for_privacy_frontend($url, $opts);
$base_url = get_base_url($url);
$description = $result["description"];
echo "<div class=\"text-result-wrapper\">";
echo "<a href=\"$url\">";
echo "$base_url";
echo "<h2>$title</h2>";
echo "</a>";
echo "<span>$description</span>";
echo "</div>";
}
echo "</div>";
}
}
function check_ddg_bang($query, $opts) {
$bangs_json = file_get_contents("static/misc/ddg_bang.json");
$bangs = json_decode($bangs_json, true);
if (substr($query, 0, 1) == "!")
$search_word = substr(explode(" ", $query)[0], 1);
else
$search_word = substr(end(explode(" ", $query)), 1);
$bang_url = null;
foreach($bangs as $bang) {
if ($bang["t"] == $search_word) {
$bang_url = $bang["u"];
break;
}
}
if ($bang_url) {
$bang_query_array = explode("!" . $search_word, $query);
$bang_query = trim(implode("", $bang_query_array));
$request_url = str_replace("{{{s}}}", str_replace('%26quot%3B','%22', urlencode($bang_query)), $bang_url);
header("Location: " . $request_url);
die();
}
}
?>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -4,21 +4,16 @@
require "misc/tools.php";
$url = $_REQUEST["url"];
$requested_root_domain = get_root_domain($url);
$split_url = explode("/", $url);
$base_url = $split_url[2];
$allowed_domains = array("s2.qwant.com", "s1.qwant.com", "upload.wikimedia.org", get_root_domain($config->invidious_instance_for_video_results));
$base_url_main_split = explode(".", strrev($base_url));
$base_url_main = strrev($base_url_main_split[1]) . "." . strrev($base_url_main_split[0]);
$allowed_domains = array("qwant.com", "wikimedia.org", "brave.com");
if (in_array($base_url_main, $allowed_domains))
if (in_array($requested_root_domain, $allowed_domains))
{
$image = $url;
$image_src = request($image);
header("Content-Type: image/jpeg");
header("Content-Type: image/png");
echo $image_src;
}
?>

View File

@ -1,18 +1,22 @@
<?php require "misc/header.php"; ?>
<title>LibreX</title>
<title>LibreY</title>
</head>
<body>
<form class="search-container" action="search.php" method="get" autocomplete="off">
<h1>Libre<span class="X">X</span></h1>
<h1>Libre<span class="Y">Y</span></h1>
<input type="text" name="q" autofocus/>
<input type="hidden" name="p" value="0"/>
<input type="hidden" name="t" value="0"/>
<input type="submit" class="hide"/>
<div class="search-button-wrapper">
<button name="t" value="0" type="submit">Search with LibreX</button>
<button name="t" value="3" type="submit">Search torrents with LibreX</button>
</div>
</form>
<button name="t" value="0" type="submit">Search with LibreY</button>
<button name="t" value="3" type="submit">Search torrents with LibreY</button>
</div>
</form>
<p style='text-align: center; color: red;'>DEPRECATION NOTICE:</p>
<p style='text-align: center; color: red;'>I got bored of maintaining LibreX/Y, first of all, I don't even use it, it fails randomly and I already fixed it many times and it still fails lol, so yeah, just use my <a href='https://4get.zzls.xyz'>4get (Getting google support soon)</a> or <a href='https://search.zzls.xyz'>SearxNG</a> instance</p>
<p style='text-align: center;'>Oh and also, the LibreY maintainers list all the instances in the instances.json (Highly unfriendly) file instead of the README.md. There is only 4 instances listed in the README.md file and they are the "official" ones backed by the LibreY maintaners. So people will just use those instances and not the other ones hosted by the community. Poop to be honest</p>
<?php require "misc/footer.php"; ?>

View File

@ -1,82 +1,158 @@
{
"instances": [
{
"clearnet": "https://librex.beparanoid.de/",
"tor": "http://librex.2356uhnbpv5nk3bni5bv6jg2cd6lgj664kwx3lhyelstpttpyv4kk2qd.onion/",
"clearnet": "https://search.ahwx.org/",
"tor": "http://wn5jl6fxlzzfenlyu3lc4q7jpw2saplrywxvxtvqbguotwd4y5cjeuqd.onion/",
"i2p": null,
"country": "HU"
"country": "NL",
"librey": true
},
{
"clearnet": "https://lx.vern.cc/",
"tor": "http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/",
"i2p": "http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/",
"country": "US"
},
{
"clearnet": "https://lx.sesu.cc/",
"tor": "http://lx.swxoebbpeqiiixyhbuh3vbw53pdrmtbiaj2sqveol6kkn5rpapfi4aad.onion/",
"i2p": "http://37bw4xelfgivsih5s4s5cozkxkhgoeqx5bjfjnrnmv5utdtk45sa.b32.i2p/",
"country": "CL"
},
{
"clearnet": "https://librex.mikata.ru/",
"tor": "http://f7ssz7l3biu4fugwctfpcx4txg5yq4gqhrt473ledsuc3ivtd3omniid.onion/",
"clearnet": "https://search2.ahwx.org/",
"tor": "http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion/",
"i2p": null,
"country": "US"
"country": "FR",
"librey": true
},
{
"clearnet": "https://librex.terryiscool160.xyz/",
"tor": "http://librex.n53wt4ivvfdfaqkwldgdzfsubszukie2an6auja6x2wp3e3oa7v2gqyd.onion/",
"clearnet": "https://librex.me/",
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/",
"country": "CA",
"librey": true
},
{
"clearnet": "https://librex.revvy.de/",
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/",
"country": "CA",
"librey": true
},
{
"clearnet": "https://librex.zzls.xyz/",
"tor": "http://librex.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion/",
"i2p": "http://zzlsaymhcfla7vibo3a223bybeecu3bd5z6rmw2u4y76maqeu76q.b32.i2p/",
"country": "CL",
"librey": true
},
{
"clearnet": "https://librey.org/",
"tor": "http://jxhkfulu6wpdl4apuy4dyivuowmpprvsd7e3el2z73crq7fmyv7rjkyd.onion/",
"i2p": null,
"country": "UK"
"country": "US",
"librey": true
},
{
"clearnet": "https://librex.supernets.org/",
"tor": "http://ouosr2fq3lktngcvbz4r4op2lab5hbiz5y6g6toorsgieb7elet76jad.onion/",
"i2p": null,
"country": "US",
"librey": true
},
{
"clearnet": "https://search.davidovski.xyz/",
"tor": null,
"i2p": null,
"country": "UK"
"country": "GB",
"librey": true
},
{
"clearnet": "https://librey.spaceint.fr/",
"tor": null,
"i2p": null,
"country": "FR",
"librey": true
},
{
"clearnet": "https://librey.bloatcat.tk/",
"tor": null,
"i2p": null,
"country": "IS",
"librey": true
},
{
"clearnet": "https://search.funami.tech/",
"tor": null,
"i2p": null,
"country": "KR"
"country": "KR",
"librey": true
},
{
"clearnet": "https://search.madreyk.xyz/",
"clearnet": "https://librex.retro-hax.net/",
"tor": null,
"i2p": null,
"country": "DE"
"country": "DE",
"librey": true
},
{
"clearnet": "https://librex.nohost.network/",
"tor": null,
"i2p": null,
"country": "MX",
"librey": true
},
{
"clearnet": "https://search.pabloferreiro.es/",
"tor": null,
"i2p": null,
"country": "DE"
"country": "DE",
"librey": true
},
{
"clearnet": "https://buscar.weblibre.org/",
"clearnet": "https://search.ratakor.com/",
"tor": null,
"i2p": null,
"country": "CL"
"country": "FR",
"librey": true
},
{
"clearnet": "https://search.ahwx.org/",
"clearnet": "https://librex.yogeshlamichhane.com.np/",
"tor": null,
"i2p": null,
"country": "NL"
"country": "FI",
"librey": true
},
{
"clearnet": "https://librex.pufe.org/",
"clearnet": "https://librey.baczek.me/",
"tor": null,
"i2p": null,
"country": "NZ"
"country": "PL",
"librey": true
},
{
"clearnet": "https://librex.kitscomputer.tk/",
"clearnet": "https://lx.benike.me/",
"tor": null,
"i2p": null,
"country": "US"
"country": "DE",
"librey": true
},
{
"clearnet": "https://search.seitan-ayoub.lol/",
"tor": null,
"i2p": null,
"country": "DE",
"librey": true
},
{
"clearnet": "https://librex.myroware.eu/",
"tor": null,
"i2p": null,
"country": "DE",
"librey": false
},
{
"clearnet": "https://search.zeroish.xyz/",
"tor": null,
"i2p": null,
"country": "US",
"librey": false
},
{
"clearnet": "https://librex.baczek.me/",
"tor": null,
"i2p": null,
"country": "PL",
"librey": false
}
]
}

62
instances.php Normal file
View File

@ -0,0 +1,62 @@
<?php
require "misc/header.php";
require "misc/tools.php";
$instances_json = json_decode(file_get_contents("instances.json"), true);
$librey_instances = array_filter($instances_json['instances'], fn($n) => $n['librey']);
$librex_instances = array_filter($instances_json['instances'], fn($n) => !$n['librey']);
function list_instances($instances)
{
echo "<table><tr>";
echo "<th>Clearnet</th>";
echo "<th>Tor</th>";
echo "<th>I2P</th>";
echo "<th>Country</th>";
echo "</tr>";
foreach($instances as $instance) {
$hostname = parse_url($instance["clearnet"])["host"];
$country = get_country_emote($instance["country"]) . $instance["country"];
$is_tor = !is_null($instance["tor"]);
$is_i2p = !is_null($instance["i2p"]);
echo "<tr>";
echo "<td><a href=\"" . $instance["clearnet"] . "\">" . $hostname . "</a></td>";
echo $is_tor
? "<td><a href=\"" . $instance["tor"] . "\">\u{2705}</a></td>"
: "<td>\u{274C}</td>";
echo $is_i2p
? "<td><a href=\"" . $instance["i2p"] . "\">\u{2705}</a></td>"
:"<td>\u{274C}</td>";
echo "<td>$country</td>";
echo "</tr>";
}
echo "</table>";
}
?>
<title>LibreY - instances</title>
</head>
<body>
<div class="misc-container">
<center>
<h2>Libre<span class="Y">Y</span> instances</h2>
<?php
list_instances($librey_instances);
?>
<p>The following instances are running the older <a href="https://github.com/hnhx/librex">LibreX</a>:</p>
<?php
list_instances($librex_instances);
?>
</center>
</div>
<?php require "misc/footer.php"; ?>

45
misc/cooldowns.php Normal file
View File

@ -0,0 +1,45 @@
<?php
if (!function_exists("apcu_fetch"))
error_log("apcu is not installed! Please consider installing php-pecl-apcu for significant performance improvements");
function load_cooldowns() {
if (function_exists("apcu_fetch"))
return apcu_exists("cooldowns") ? apcu_fetch("cooldowns") : array();
return array();
}
function save_cooldowns($cooldowns) {
if (function_exists("apcu_store"))
apcu_store("cooldowns", $cooldowns);
}
function set_cooldown($instance, $timeout, $cooldowns) {
$cooldowns[$instance] = time() + $timeout;
save_cooldowns($cooldowns);
return $cooldowns;
}
function has_cooldown($instance, $cooldowns) {
return ($cooldowns[$instance] ?? 0) > time();
}
function has_cached_results($url) {
if (function_exists("apcu_exists"))
return apcu_exists("cached:$url");
return false;
}
function store_cached_results($url, $results, $ttl = 0) {
if (function_exists("apcu_store") && !empty($results))
return apcu_store("cached:$url", $results, $ttl);
}
function fetch_cached_results($url) {
if (function_exists("apcu_fetch"))
return apcu_fetch("cached:$url");
return array();
}
?>

View File

@ -1,14 +1,16 @@
<div class="footer-container">
<a href="./">LibreX</a>
<a href="https://github.com/hnhx/librex/" target="_blank">Source &amp; Instance list</a>
<a href="./">LibreY</a>
<a href="https://github.com/Ahwxorg/librey/" target="_blank">Source</a>
<a href="./instances.php" target="_blank">Instances</a>
<a href="./settings.php">Settings</a>
<a href="./api.php" target="_blank">API</a>
<a href="./donate.php">Donate ❤️</a>
<a href="https://zzls.xyz/donate">Donate to the hoster (the one hosting this)</a>
<a href="./donate.php">Donate to the developer (hnhx)</a>
</div>
<div class="git-container">
<?php
$hash = file_get_contents(".git/refs/heads/main");
echo "<a href=\"https://github.com/hnhx/librex/commit/$hash\" target=\"_blank\">Latest commit: $hash</a>";
echo "<a href=\"https://git.zzls.xyz/fijxu/librex/commit/$hash\" target=\"_blank\">Latest commit: $hash</a>";
?>
</div>
</body>

View File

@ -6,11 +6,8 @@
<meta name="description" content="A privacy respecting meta search engine."/>
<meta name="referrer" content="no-referrer"/>
<link rel="stylesheet" type="text/css" href="static/css/styles.css"/>
<link title="LibreX search" type="application/opensearchdescription+xml" href="/opensearch.xml?method=POST" rel="search"/>
<link title="LibreY search" type="application/opensearchdescription+xml" href="opensearch.xml?method=POST" rel="search"/>
<link rel="stylesheet" type="text/css" href="<?php
echo "static/css/";
if (isset($_COOKIE["theme"]) || isset($_REQUEST["theme"]))
echo htmlspecialchars((isset($_COOKIE["theme"]) ? $_COOKIE["theme"] : $_REQUEST["theme"]) . ".css");
else
echo "dark.css";
$theme = $_REQUEST["theme"] ?? trim(htmlspecialchars($_COOKIE["theme"] ?? "dark"));
echo "static/css/" . $theme . ".css";
?>"/>

172
misc/search_engine.php Normal file
View File

@ -0,0 +1,172 @@
<?php
require "misc/cooldowns.php";
abstract class EngineRequest {
protected $DO_CACHING = true;
function __construct($opts, $mh) {
$this->query = $opts->query;
$this->page = $opts->page;
$this->mh = $mh;
$this->opts = $opts;
$this->url = $this->get_request_url();
if (!$this->url)
return;
if (has_cached_results($this->url))
return;
$this->ch = curl_init($this->url);
if ($opts->curl_settings)
curl_setopt_array($this->ch, $opts->curl_settings);
if ($mh)
curl_multi_add_handle($mh, $this->ch);
}
public function get_request_url() {
return "";
}
public function successful() {
return (isset($this->ch) && curl_getinfo($this->ch)['http_code'] == '200')
|| has_cached_results($this->url);
}
abstract function parse_results($response);
public function get_results() {
if (!isset($this->url))
return $this->parse_results(null);
if ($this->DO_CACHING && has_cached_results($this->url))
return fetch_cached_results($this->url);
if (!isset($this->ch))
return $this->parse_results(null);
$response = $this->mh ? curl_multi_getcontent($this->ch) : curl_exec($this->ch);
$results = $this->parse_results($response) ?? array();
if ($this->DO_CACHING && !empty($results))
store_cached_results($this->url, $results, $this->opts->cache_time * 60);
return $results;
}
public static function print_results($results, $opts) {}
}
function load_opts() {
$opts = require "config.php";
$opts->request_cooldown ??= 25;
$opts->cache_time ??= 25;
$opts->query = trim($_REQUEST["q"] ?? "");
$opts->type = (int) ($_REQUEST["t"] ?? 0);
$opts->page = (int) ($_REQUEST["p"] ?? 0);
$opts->theme = $_REQUEST["theme"] ?? trim(htmlspecialchars($_COOKIE["theme"] ?? "dark"));
$opts->safe_search = (int) ($_REQUEST["safe"] ?? 0) == 1 || isset($_COOKIE["safe_search"]);
$opts->disable_special = (int) ($_REQUEST["ns"] ?? 0) == 1 || isset($_COOKIE["disable_special"]);
$opts->disable_frontends = (int) ($_REQUEST["nf"] ?? 0) == 1 || isset($_COOKIE["disable_frontends"]);
$opts->language = $_REQUEST["lang"] ?? trim(htmlspecialchars($_COOKIE["language"] ?? $opts->language ?? "en"));
$opts->do_fallback = (int) ($_REQUEST["nfb"] ?? 0) == 0;
if (!$opts->instance_fallback) {
$opts->do_fallback = false;
}
$opts->number_of_results ??= trim(htmlspecialchars($_COOKIE["number_of_results"]));
foreach (array_keys($opts->frontends ?? array()) as $frontend) {
$opts->frontends[$frontend]["instance_url"] = $_COOKIE[$frontend] ?? $opts->frontends[$frontend]["instance_url"];
}
$opts->curl_settings[CURLOPT_FOLLOWLOCATION] ??= true;
return $opts;
}
function opts_to_params($opts) {
$query = urlencode($opts->query);
$params = "";
$params .= "p=$opts->page";
$params .= "&q=$query";
$params .= "&t=$opts->type";
$params .= "&safe=" . ($opts->safe_search ? 1 : 0);
$params .= "&nf=" . ($opts->disable_frontends ? 1 : 0);
$params .= "&ns=" . ($opts->disable_special ? 1 : 0);
return $params;
}
function init_search($opts, $mh) {
switch ($opts->type)
{
case 1:
require "engines/qwant/image.php";
return new QwantImageSearch($opts, $mh);
case 2:
require "engines/invidious/video.php";
return new VideoSearch($opts, $mh);
case 3:
if ($opts->disable_bittorent_search) {
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
break;
}
require "engines/bittorrent/merge.php";
return new TorrentSearch($opts, $mh);
case 4:
if ($opts->disable_hidden_service_search) {
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
break;
}
require "engines/ahmia/hidden_service.php";
return new TorSearch($opts, $mh);
default:
require "engines/text/text.php";
return new TextSearch($opts, $mh);
}
}
function fetch_search_results($opts, $do_print) {
$opts->cooldowns = load_cooldowns();
$start_time = microtime(true);
$mh = curl_multi_init();
$search_category = init_search($opts, $mh);
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
$results = $search_category->get_results();
if (empty($results)) {
require "engines/librex/fallback.php";
$results = get_librex_results($opts);
}
if (!$do_print)
return $results;
print_elapsed_time($start_time);
$search_category->print_results($results, $opts);
return $results;
}
?>

View File

@ -1,74 +1,64 @@
<?php
function get_base_url($url)
{
$split_url = explode("/", $url);
$base_url = $split_url[0] . "//" . $split_url[2] . "/";
return $base_url;
function get_base_url($url) {
$parsed = parse_url($url);
return $parsed["scheme"] . "://" . $parsed["host"] . "/";
}
function try_replace_with_frontend($url, $frontend, $original)
{
$config = require "config.php";
function get_root_domain($url) {
return parse_url($url, PHP_URL_HOST);
}
if (isset($_COOKIE[$frontend]) || isset($_REQUEST[$frontend]) || !empty($config->$frontend))
{
if (isset($_COOKIE[$frontend]))
$frontend = $_COOKIE[$frontend];
else if (isset($_REQUEST[$frontend]))
$frontend = $_REQUEST[$frontend];
else if (!empty($config->$frontend))
$frontend = $config->$frontend;
function try_replace_with_frontend($url, $frontend, $original, $opts) {
$frontends = $opts->frontends;
if ($original == "instagram.com")
{
if (!strpos($url, "/p/"))
$frontend .= "/u";
}
if (array_key_exists($frontend, $opts->frontends)) {
$frontend = $frontends[$frontend]["instance_url"];
if (empty(trim($frontend)))
return $url;
if (strpos($url, "wikipedia.org") !== false)
{
if (strpos($url, "wikipedia.org") !== false) {
$wiki_split = explode(".", $url);
if (count($wiki_split) > 1)
{
if (count($wiki_split) > 1) {
$lang = explode("://", $wiki_split[0])[1];
$url = $frontend . explode($original, $url)[1] . "?lang=" . $lang;
$url = $frontend . explode($original, $url)[1] . (strpos($url, "?") !== false ? "&" : "?") . "lang=" . $lang;
}
}
else
{
} else if (strpos($url, "fandom.com") !== false) {
$fandom_split = explode(".", $url);
if (count($fandom_split) > 1) {
$wiki_name = explode("://", $fandom_split[0])[1];
$url = $frontend . "/" . $wiki_name . explode($original, $url)[1];
}
} else if (strpos($url, "gist.github.com") !== false) {
$gist_path = explode("gist.github.com", $url)[1];
$url = $frontend . "/gist" . $gist_path;
} else if (strpos($url, "stackexchange.com") !== false) {
$se_domain = explode(".", explode("://", $url)[1])[0];
$se_path = explode("stackexchange.com", $url)[1];
$url = $frontend . "/exchange" . "/" . $se_domain . $se_path;
} else {
$url = $frontend . explode($original, $url)[1];
}
return $url;
}
return $url;
}
function check_for_privacy_frontend($url)
{
if (isset($_COOKIE["disable_frontends"]))
function check_for_privacy_frontend($url, $opts) {
if ($opts->disable_frontends)
return $url;
$frontends = array(
"youtube.com" => "invidious",
"instagram.com" => "bibliogram",
"twitter.com" => "nitter",
"reddit.com" => "libreddit",
"tiktok.com" => "proxitok",
"wikipedia.org" => "wikiless",
"quora.com" => "quetre",
"imdb.com" => "libremdb"
);
foreach($opts->frontends as $frontend => $data) {
$original = $data["original_url"];
foreach($frontends as $original => $frontend)
{
if (strpos($url, $original))
{
$url = try_replace_with_frontend($url, $frontend, $original);
if (strpos($url, $original)) {
$url = try_replace_with_frontend($url, $frontend, $original, $opts);
break;
} else if (strpos($url, "stackexchange.com")) {
$url = try_replace_with_frontend($url, "anonymousoverflow", "stackexchange.com", $opts);
break;
}
}
@ -76,88 +66,10 @@
return $url;
}
function check_ddg_bang($query)
{
function get_xpath($response) {
if (!$response)
return null;
$bangs_json = file_get_contents("static/misc/ddg_bang.json");
$bangs = json_decode($bangs_json, true);
if (substr($query, 0, 1) == "!")
$search_word = substr(explode(" ", $query)[0], 1);
else
$search_word = substr(end(explode(" ", $query)), 1);
$bang_url = null;
foreach($bangs as $bang)
{
if ($bang["t"] == $search_word)
{
$bang_url = $bang["u"];
break;
}
}
if ($bang_url)
{
$bang_query_array = explode("!" . $search_word, $query);
$bang_query = trim(implode("", $bang_query_array));
$request_url = str_replace("{{{s}}}", $bang_query, $bang_url);
$request_url = check_for_privacy_frontend($request_url);
header("Location: " . $request_url);
die();
}
}
function check_for_special_search($query)
{
if (isset($_COOKIE["disable_special"]) || isset($_REQUEST["disable_special"]))
return 0;
$query_lower = strtolower($query);
$split_query = explode(" ", $query);
if (strpos($query_lower, "to") && count($split_query) >= 4) // currency
{
$amount_to_convert = floatval($split_query[0]);
if ($amount_to_convert != 0)
return 1;
}
else if (strpos($query_lower, "mean") && count($split_query) >= 2) // definition
{
return 2;
}
else if (strpos($query_lower, "my") !== false)
{
if (strpos($query_lower, "ip"))
{
return 3;
}
else if (strpos($query_lower, "user agent") || strpos($query_lower, "ua"))
{
return 4;
}
}
else if (strpos($query_lower, "weather") !== false)
{
return 5;
}
else if ($query_lower == "tor")
{
return 6;
}
else if (3 > count(explode(" ", $query))) // wikipedia
{
return 7;
}
return 0;
}
function get_xpath($response)
{
$htmlDom = new DOMDocument;
@$htmlDom->loadHTML($response);
$xpath = new DOMXPath($htmlDom);
@ -165,9 +77,8 @@
return $xpath;
}
function request($url)
{
global $config;
function request($url) {
$config ??= require "config.php";
$ch = curl_init($url);
curl_setopt_array($ch, $config->curl_settings);
@ -176,40 +87,50 @@
return $response;
}
function human_filesize($bytes, $dec = 2)
{
function human_filesize($bytes, $dec = 2) {
$size = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$dec}f ", $bytes / pow(1024, $factor)) . @$size[$factor];
}
function remove_special($string)
{
function remove_special($string) {
$string = preg_replace("/[\r\n]+/", "\n", $string);
return trim(preg_replace("/\s+/", ' ', $string));
}
function print_elapsed_time($start_time)
{
function print_elapsed_time($start_time) {
$end_time = number_format(microtime(true) - $start_time, 2, '.', '');
echo "<p id=\"time\">Fetched the results in $end_time seconds</p>";
}
function print_next_page_button($text, $page, $query, $type)
{
function print_next_page_button($text, $page, $query, $type) {
echo "<form class=\"page\" action=\"search.php\" target=\"_top\" method=\"get\" autocomplete=\"off\">";
foreach($_REQUEST as $key=>$value)
{
if ($key != "q" && $key != "p" && $key != "t")
{
echo "<input type=\"hidden\" name=\"$key\" value=\"$value\"/>";
}
}
echo "<input type=\"hidden\" name=\"p\" value=\"" . $page . "\" />";
echo "<input type=\"hidden\" name=\"q\" value=\"$query\" />";
echo "<input type=\"hidden\" name=\"t\" value=\"$type\" />";
echo "<button type=\"submit\">$text</button>";
echo "</form>";
}
function copy_cookies($curl) {
if (array_key_exists("HTTP_COOKIE", $_SERVER))
curl_setopt( $curl, CURLOPT_COOKIE, $_SERVER['HTTP_COOKIE'] );
}
function get_country_emote($code) {
$emoji = [];
foreach(str_split($code) as $c) {
if(($o = ord($c)) > 64 && $o % 32 < 27) {
$emoji[] = hex2bin("f09f87" . dechex($o % 32 + 165));
continue;
}
$emoji[] = $c;
}
return join($emoji);
}
?>

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>LibreX</ShortName>
<Description>A privacy respecting meta search engine.</Description>
<ShortName>LibreY</ShortName>
<Description>Framework and javascript free privacy respecting meta search engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<LongName>LibreX search</LongName>
<Url rel="results" type="text/html" method="get" template="http://localhost/search.php?q={searchTerms}" />
<LongName>LibreY search</LongName>
<Url rel="results" type="text/html" method="get" template="http://localhost:80/search.php?q={searchTerms}" />
<Url type="application/opensearchdescription+xml"
rel="self"
template="/opensearch.xml?method=POST" />
template="/opensearch.xml?method=GET" />
</OpenSearchDescription>

View File

@ -1,137 +1,79 @@
<?php require "misc/header.php"; ?>
<?php
require "misc/header.php";
require "misc/tools.php";
require "misc/search_engine.php";
$opts = load_opts();
function print_page_buttons($type, $query, $page) {
if ($type > 1)
return;
echo "<div class=\"next-page-button-wrapper\">";
if ($page != 0)
{
print_next_page_button("&lt;&lt;", 0, $query, $type);
print_next_page_button("&lt;", $page - 10, $query, $type);
}
for ($i=$page / 10; $page / 10 + 10 > $i; $i++)
print_next_page_button($i + 1, $i * 10, $query, $type);
print_next_page_button("&gt;", $page + 10, $query, $type);
echo "</div>";
}
?>
<title>
<?php
$query = htmlspecialchars(trim($_REQUEST["q"]));
echo $query;
?> - LibreX</title>
echo $opts->query;
?> - LibreY</title>
</head>
<body>
<form class="sub-search-container" method="get" autocomplete="off">
<h1 class="logomobile"><a class="no-decoration" href="./">Libre<span class="X">X</span></a></h1>
<h1 class="logomobile"><a class="no-decoration" href="./">Libre<span class="Y">Y</span></a></h1>
<input type="text" name="q"
<?php
$query_encoded = urlencode($query);
if (1 > strlen($query) || strlen($query) > 256)
if (1 > strlen($opts->query) || strlen($opts->query) > 256)
{
header("Location: ./");
die();
}
echo "value=\"$query\"";
echo "value=\"" . htmlspecialchars($opts->query) . "\"";
?>
>
<br>
<?php
foreach($_REQUEST as $key=>$value)
{
if ($key != "q" && $key != "p" && $key != "t")
{
echo "<input type=\"hidden\" name=\"" . htmlspecialchars($key) . "\" value=\"" . htmlspecialchars($value) . "\"/>";
}
}
$type = isset($_REQUEST["t"]) ? (int) $_REQUEST["t"] : 0;
echo "<button class=\"hide\" name=\"t\" value=\"$type\"/></button>";
echo "<button class=\"hide\" name=\"t\" value=\"$opts->type\"/></button>";
?>
<button type="submit" class="hide"></button>
<input type="hidden" name="p" value="0">
<div class="sub-search-button-wrapper">
<button name="t" value="0"><img src="static/images/text_result.png" alt="text result" />General</button>
<button name="t" value="1"><img src="static/images/image_result.png" alt="image result" />Images</button>
<button name="t" value="2"><img src="static/images/video_result.png" alt="video result" />Videos</button>
<button name="t" value="3"><img src="static/images/torrent_result.png" alt="torrent result" />Torrents</button>
<button name="t" value="4"><img src="static/images/tor_result.png" alt="tor result" />Tor</button>
<?php
$categories = array("general", "images", "videos", "torrents", "tor");
foreach ($categories as $category)
{
$category_index = array_search($category, $categories);
if (($opts->disable_bittorent_search && $category_index == 3) ||
($opts->disable_hidden_service_search && $category_index ==4))
{
continue;
}
echo "<a " . (($category_index == $opts->type) ? "class=\"active\" " : "") . "href=\"./search.php?q=" . urlencode($opts->query) . "&p=0&t=" . $category_index . "\"><img src=\"static/images/" . $category . "_result.png\" alt=\"" . $category . " result\" />" . ucfirst($category) . "</a>";
}
?>
</div>
<hr>
</form>
<?php
$config = require "config.php";
require "misc/tools.php";
$page = isset($_REQUEST["p"]) ? (int) $_REQUEST["p"] : 0;
$start_time = microtime(true);
switch ($type)
{
case 0:
$query_parts = explode(" ", $query);
$last_word_query = end($query_parts);
if (substr($query, 0, 1) == "!" || substr($last_word_query, 0, 1) == "!")
check_ddg_bang($query);
require "engines/google/text.php";
$results = get_text_results($query, $page);
print_elapsed_time($start_time);
print_text_results($results);
break;
case 1:
require "engines/qwant/image.php";
$results = get_image_results($query_encoded, $page);
print_elapsed_time($start_time);
print_image_results($results);
break;
case 2:
require "engines/brave/video.php";
$results = get_video_results($query_encoded);
print_elapsed_time($start_time);
print_video_results($results);
break;
case 3:
if ($config->disable_bittorent_search)
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
else
{
require "engines/bittorrent/merge.php";
$results = get_merged_torrent_results($query_encoded);
print_elapsed_time($start_time);
print_merged_torrent_results($results);
}
break;
case 4:
if ($config->disable_hidden_service_search)
echo "<p class=\"text-result-container\">The host disabled this feature! :C</p>";
else
{
require "engines/ahmia/hidden_service.php";
$results = get_hidden_service_results($query_encoded);
print_elapsed_time($start_time);
print_hidden_service_results($results);
}
break;
default:
require "engines/google/text.php";
$results = get_text_results($query_encoded, $page);
print_text_results($results);
print_elapsed_time($start_time);
break;
}
if (2 > $type)
{
echo "<div class=\"next-page-button-wrapper\">";
if ($page != 0)
{
print_next_page_button("&lt;&lt;", 0, $query, $type);
print_next_page_button("&lt;", $page - 10, $query, $type);
}
for ($i=$page / 10; $page / 10 + 10 > $i; $i++)
print_next_page_button($i + 1, $i * 10, $query, $type);
print_next_page_button("&gt;", $page + 10, $query, $type);
echo "</div>";
}
fetch_search_results($opts, true);
print_page_buttons($opts->type, $opts->query, $opts->page);
?>
<?php require "misc/footer.php"; ?>

View File

@ -1,43 +1,39 @@
<?php
$config = require "config.php";
if (isset($_REQUEST["save"]) || isset($_REQUEST["reset"]))
{
if (isset($_SERVER["HTTP_COOKIE"]))
{
$cookies = explode(";", $_SERVER["HTTP_COOKIE"]);
foreach($cookies as $cookie)
{
$parts = explode("=", $cookie);
$name = trim($parts[0]);
setcookie($name, "", time() - 1000);
}
}
}
require "misc/search_engine.php";
if (isset($_REQUEST["save"]))
{
foreach($_POST as $key=>$value){
if (!empty($value))
{
setcookie($key, $value, time() + (86400 * 90), '/');
$_COOKIE[$name] = $value;
}
}
// Reset all cookies when resetting, or before saving new cookies
if (isset($_REQUEST["reset"]) || isset($_REQUEST["save"])) {
if (isset($_SERVER["HTTP_COOKIE"])) {
$cookies = explode(";", $_SERVER["HTTP_COOKIE"]);
foreach($cookies as $cookie) {
$parts = explode("=", $cookie);
$name = trim($parts[0]);
setcookie($name, "", time() - 1000);
}
if (isset($_REQUEST["save"]) || isset($_REQUEST["reset"]))
{
header("Location: ./settings.php");
die();
}
}
if (isset($_REQUEST["save"])) {
foreach($_POST as $key=>$value) {
if (!empty($value)) {
setcookie($key, $value, time() + (86400 * 90), '/');
} else {
setcookie($key, "", time() - 1000);
}
require "misc/header.php";
}
}
if (isset($_REQUEST["save"]) || isset($_REQUEST["reset"])) {
header("Location: ./");
die();
}
$opts = load_opts();
require "misc/header.php";
?>
<title>LibreX - Settings</title>
<title>LibreY - Settings</title>
</head>
<body>
<div class="misc-container">
@ -52,18 +48,21 @@
<option value=\"amoled\">AMOLED</option>
<option value=\"light\">Light</option>
<option value=\"auto\">Auto</option>
<option value=\"dracula\">Dracula</option>
<option value=\"nord\">Nord</option>
<option value=\"night_owl\">Night Owl</option>
<option value=\"discord\">Discord</option>
<option value=\"google\">Google Dark</option>
<option value=\"startpage\">Startpage Dark</option>
<option value=\"gruvbox\">Gruvbox</option>
<option value=\"github_night\">GitHub Night</option>";
<option value=\"github_night\">GitHub Night</option>
<option value=\"catppuccin\">Catppucin</option>
<option value=\"ubuntu\">Ubuntu</option>
<option value=\"tokyo_night\">Tokyo night</option>";
if (isset($_COOKIE["theme"]))
{
$cookie_theme = $_COOKIE["theme"];
$themes = str_replace($cookie_theme . "\"", $cookie_theme . "\" selected", $themes);
if (isset($opts->theme)) {
$theme = $opts->theme;
$themes = str_replace($theme . "\"", $theme . "\" selected", $themes);
}
echo $themes;
@ -72,30 +71,19 @@
</div>
<div>
<label>Disable special queries (e.g.: currency conversion)</label>
<input type="checkbox" name="disable_special" <?php echo isset($_COOKIE["disable_special"]) ? "checked" : ""; ?> >
<input type="checkbox" name="disable_special" <?php echo $opts->disable_special ? "checked" : ""; ?> >
</div>
<h2>Privacy friendly frontends</h2>
<p>For an example if you want to view YouTube without getting spied on, click on "Invidious", find the instance that is most suitable for you then paste it in (correct format: https://example.com)</p>
<div class="instances-container">
<div class="settings-textbox-container">
<?php
$frontends = array(
"invidious" => array("https://docs.invidious.io/instances/", "YouTube"),
"bibliogram" => array("https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instances.md", "Instagram"),
"nitter" => array("https://github.com/zedeus/nitter/wiki/Instances", "Twitter"),
"libreddit" => array("https://github.com/spikecodes/libreddit", "Reddit"),
"proxitok" => array("https://github.com/pablouser1/ProxiTok/wiki/Public-instances", "TikTok"),
"wikiless" => array("https://codeberg.org/orenom/wikiless", "Wikipedia"),
"quetre" => array("https://github.com/zyachel/quetre", "Quora"),
"libremdb" => array("https://github.com/zyachel/libremdb", "IMDb")
);
foreach($frontends as $frontend => $info)
foreach($opts->frontends as $frontend => $data)
{
echo "<div>";
echo "<a for=\"$frontend\" href=\"" . $info[0] . "\" target=\"_blank\">" . ucfirst($frontend) . "</a>";
echo "<input type=\"text\" name=\"$frontend\" placeholder=\"Replace " . $info[1] . "\" value=";
echo isset($_COOKIE["$frontend"]) ? htmlspecialchars($_COOKIE["$frontend"]) : json_decode(json_encode($config), true)[$frontend];
echo "<a for=\"$frontend\" href=\"" . $data["project_url"] . "\" target=\"_blank\">" . ucfirst($frontend) . "</a>";
echo "<input type=\"text\" name=\"$frontend\" placeholder=\"Replace " . $data["original_name"] . "\" value=";
echo htmlspecialchars($opts->frontends["$frontend"]["instance_url"] ?? "");
echo ">";
echo "</div>";
}
@ -103,8 +91,40 @@
</div>
<div>
<label>Disable frontends</label>
<input type="checkbox" name="disable_frontends" <?php echo isset($_COOKIE["disable_frontends"]) ? "checked" : ""; ?> >
<input type="checkbox" name="disable_frontends" <?php echo $opts->disable_frontends ? "checked" : ""; ?> >
</div>
<h2>Search settings</h2>
<div class="settings-textbox-container">
<div>
<span>Language</span>
<select name="language">
<?php
$languages = json_decode(file_get_contents("static/misc/languages.json"), true);
$options = "";
$options .= "<option value=\"\" " . (!isset($opts->language) ? "selected" : "") . ">Any</option>";
foreach ($languages as $lang_code => $language) {
$name = $language["name"];
$selected = $opts->language == $lang_code ? "selected" : "";
$options .= "<option value=\"$lang_code\" $selected>$name</option>";
}
echo $options;
?>
</select>
</div>
<div>
<label>Number of results per page</label>
<input type="number" name="number_of_results" value="<?php echo htmlspecialchars($opts->number_of_results ?? "10") ?>" >
</div>
</div>
<div>
<label>Safe search</label>
<input type="checkbox" name="safe_search" <?php echo $opts->safe_search ? "checked" : ""; ?> >
</div>
<div>
<button type="submit" name="save" value="1">Save</button>
<button type="submit" name="reset" value="1">Reset</button>

26
static/css/catppuccin.css Normal file
View File

@ -0,0 +1,26 @@
:root {
--main-bg: #1E1E2E;
--main-fg: #CDD6F4;
--result-link-fg: #89B4FA;
--result-fg: #B4B3FE;
--button-bg: #313244;
--special-result-border: opacity 50;
--special-text-background: #44475A;
--special-text-color: #CDD6F4;
--search-container-text-color: #CDD6F4;
--search-container-background-color: #313244;
--search-container-background-border: #B4BEFE;
--search-form-background-color: #181825;
--border: #B4B3FE;
--footer-fg: #A6ADC8;
--footer-bg: #313244;
color-scheme: dark;
}

26
static/css/dracula.css Normal file
View File

@ -0,0 +1,26 @@
:root {
--main-bg: #282A36;
--main-fg: #F8F8F2;
--result-link-fg: #8BE9FD;
--result-fg: #6272A4;
--button-bg: #44475A;
--special-result-border: opacity 50;
--special-text-background: #44475A;
--special-text-color: #F8F8F2;
--search-container-text-color: #F8F8F2;
--search-container-background-color: #44475A;
--search-container-background-border: #6272A4;
--search-form-background-color: #21222C;
--border: #6272A4;
--footer-fg: #C2C2C2;
--footer-bg: #44475A;
color-scheme: dark;
}

View File

@ -30,10 +30,17 @@ a,
.text-result-wrapper a:visited h2,
.special-result-container a,
.sub-search-button-wrapper button {
.did-you-mean a,
.sub-search-button-wrapper a,
.sub-search-button-wrapper a:visited {
color: #bd93f9;
}
.sub-search-button-wrapper .active {
border-bottom: 2px #bd93f9 solid;
padding-bottom: 10px;
}
a:hover,
.text-result-wrapper h2:hover {
text-decoration: underline;
@ -112,6 +119,7 @@ a:hover,
.sub-search-button-wrapper {
margin-left: 165px;
margin-bottom: 10px;
}
.search-button-wrapper button:hover,
@ -125,11 +133,13 @@ a:hover,
margin-right: 5px;
}
.sub-search-button-wrapper button {
.sub-search-button-wrapper a {
border: none;
background-color: inherit;
font-size: 15px;
margin-right: 14px;
margin-right: 20px;
cursor: pointer;
text-decoration: none;
}
.sub-search-button-wrapper img {
@ -141,7 +151,7 @@ a:hover,
.misc-container {
text-align: center;
word-wrap: break-word;
width: 450px;
width: 460px;
margin-left: auto;
margin-right: auto;
margin-bottom: 100px;
@ -161,12 +171,12 @@ a:hover,
text-decoration: underline;
}
.instances-container div {
.settings-textbox-container div {
text-align: left;
margin-bottom: 25px;
}
.instances-container input {
.settings-textbox-container input {
color: inherit;
background-color: inherit;
padding: 5px;
@ -179,7 +189,8 @@ a:hover,
.text-result-container,
#time,
.next-page-button-wrapper {
.next-page-button-wrapper,
.did-you-mean {
margin-left: 170px;
}
@ -238,7 +249,7 @@ a:hover,
}
.next-page-button-wrapper {
margin-top: -50px;
margin-top: -40px;
margin-bottom: 100px;
}
@ -293,8 +304,7 @@ a[title] {
width: 100vw;
left: 0;
background-color: var(--footer-bg);
padding-top: 15px;
padding-bottom: 15px;
padding: 10px;
border-top: 1px solid var(--border);
text-align: center;
}
@ -309,15 +319,14 @@ a[title] {
}
.footer-container a {
margin-left: 15px;
margin-right: 15px;
margin-right: 30px;
}
.hide {
display: none;
}
.X {
.Y {
color: #bd93f9;
}
@ -329,6 +338,60 @@ a[title] {
color: #ff79c6;
}
/* donate css start */
.donate-container {
width: 700px;
margin-left: auto;
margin-right: auto;
margin-bottom: 100px;
}
.flexbox-column {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 10px;
}
.inner-wrap {
width: 500px;
padding: 20px;
}
.qr-box {
background-color: var(--search-container-background-color);
border: 1px solid var(--search-container-background-border);
border-radius: 10px 0px 0px 10px;
width: 100%;
display: flex;
word-wrap: break-word;
align-items: center;
justify-content: space-between;
}
.flex-row {
width: 700px;
height: auto;
display: flex;
flex-direction: row;
justify-content: space-evenly;
}
hr.small-line {
/* background-color: #f1f3f4; */
border: 2px solid var(--main-fg);
height: 0px;
width: 100px;
margin: 30px;
border-radius: 2px;
}
/* donate css end */
@media only screen and (max-width: 1320px) {
.special-result-container {
position: relative;
@ -423,7 +486,7 @@ a[title] {
padding: 0;
}
.sub-search-button-wrapper button {
.sub-search-button-wrapper a {
margin-left: auto;
margin-right: auto;
padding: 0;
@ -463,4 +526,65 @@ a[title] {
margin-left: 20px;
max-width: 90%;
}
}
.next-page-button-wrapper {
margin-top: 30px;
}
.text-result-container,
#time,
.next-page-button-wrapper,
.did-you-mean {
margin-left: 20px;
}
/* dontate css start*/
.donate-container {
margin-bottom: 100px;
width: 95%;
text-align: center;
}
.qr-box {
display: flex;
flex-direction: column;
word-wrap: break-word;
align-items: center;
justify-content: space-between;
word-wrap: break-word;
height: auto;
}
.qr-box {
border-radius: 10px;
flex-direction: column;
align-items: center;
}
.inner-wrap {
width: 80%;
text-align: center;
}
.qr-box img {
width: 40%;
height: auto;
padding: 20px;
}
.flex-row {
flex-direction: column;
align-items: center;
gap: 5px;
width: 0;
}
.flex-row a img {
width: 220px;
height: auto;
}
/* donate css end */
}

View File

@ -0,0 +1,26 @@
:root {
--main-bg: #24283b;
--main-fg: #cfc9c2;
--result-link-fg: #bb9af7;
--result-fg: #a2a08e;
--button-bg: #343b58;
--special-result-border: border 0;
--special-text-background: #1a1b26;
--special-text-color: #c0caf5;
--search-container-text-color: #f2efd3;
--search-container-background-color: #565f89;
--search-container-background-border: #bb9af7;
--search-form-background-color: #1a1b26;
--border: #565f89;
--footer-fg: #f2efd3;
--footer-bg: #1a1b26;
color-scheme: dark;
}

26
static/css/ubuntu.css Normal file
View File

@ -0,0 +1,26 @@
:root {
--main-bg: #2C001E;
--main-fg: #FFFFFF;
--result-link-fg: #84de32;
--result-fg: #a2a08e;
--button-bg: #5E2750;
--special-result-border: border 0;
--special-text-background: #333333;
--special-text-color: #FFFFFF;
--search-container-text-color: #f2efd3;
--search-container-background-color: #77216F;
--search-container-background-border: #E95420;
--search-form-background-color: #333333;
--border: #77216F;
--footer-fg: #f2efd3;
--footer-bg: #5E2750;
color-scheme: dark;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

View File

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 704 B

BIN
static/images/kofi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 657 B

View File

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 360 B

BIN
static/images/xmr-ahwx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long