Merge remote-tracking branch 'librey/main' into librey
This commit is contained in:
commit
517839ae24
53 changed files with 640 additions and 434 deletions
10
.dockerignore
Normal file
10
.dockerignore
Normal file
|
@ -0,0 +1,10 @@
|
|||
.github/
|
||||
.git/
|
||||
.gitignore
|
||||
.dockerignore
|
||||
config.php.example
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
opensearch.xml.example
|
||||
README.md
|
||||
docker-old/
|
4
.github/workflows/docker-image.yml
vendored
4
.github/workflows/docker-image.yml
vendored
|
@ -22,10 +22,14 @@ jobs:
|
|||
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
|
||||
|
|
33
Dockerfile
33
Dockerfile
|
@ -1,10 +1,10 @@
|
|||
# syntax = edrevo/dockerfile-plus
|
||||
ARG VERSION="3.18"
|
||||
FROM alpine:${VERSION} AS librey
|
||||
FROM alpine:3.18
|
||||
|
||||
WORKDIR "/var/www/html"
|
||||
|
||||
ADD "." "."
|
||||
|
||||
# Docker metadata contains information about the maintainer, such as the name, repository, and support email
|
||||
# Please add any necessary information or correct any incorrect information
|
||||
# See more: https://docs.docker.com/config/labels-custom-metadata/
|
||||
LABEL name="LibreY" \
|
||||
description="Framework and javascript free privacy respecting meta search engine" \
|
||||
|
@ -18,28 +18,25 @@ LABEL name="LibreY" \
|
|||
# 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"
|
||||
|
||||
RUN apk add gettext --no-cache
|
||||
# Install required packages
|
||||
RUN apk add gettext php82 php82-fpm php82-dom php82-curl php82-json php82-apcu nginx --no-cache
|
||||
|
||||
# The following lines import all Dockerfiles from other folders so that they can be built together in the final build
|
||||
INCLUDE+ docker/php/php.dockerfile
|
||||
INCLUDE+ docker/server/nginx.dockerfile
|
||||
|
||||
# Include docker scripts, docker images, and the 'GNU License' in the LibreY container
|
||||
ADD "." "/var/www/html"
|
||||
|
||||
# Set permissions for script files as executable scripts inside 'docker/scripts' directory
|
||||
RUN chmod u+x "${DOCKER_SCRIPTS}/php/prepare.sh" &&\
|
||||
chmod u+x "${DOCKER_SCRIPTS}/server/prepare.sh" &&\
|
||||
chmod u+x "${DOCKER_SCRIPTS}/entrypoint.sh" &&\
|
||||
chmod u+x "${DOCKER_SCRIPTS}/attributes.sh"
|
||||
# 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"]
|
||||
ENTRYPOINT ["/bin/sh", "-c", "docker/entrypoint.sh"]
|
27
README.md
27
README.md
|
@ -15,17 +15,22 @@
|
|||
|
||||
### Instances
|
||||
|
||||
> If you host using CloudFlare, this will be mentioned in the instances list.
|
||||
|
||||
You can access the full list of LibreX and LibreY instances on one of the following updated LibreY instances:
|
||||
|
||||
| Clearnet | TOR | I2P | Country |
|
||||
|-|-|-|-|
|
||||
| [search.ahwx.org](https://search.ahwx.org/) | [✅](http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion) | ❌ | 🇳🇱 NL |
|
||||
| [librex.me](https://librex.me/) | [✅](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/) | [✅](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/) | 🇨🇦 CA |
|
||||
| [librex.revvy.de](https://librex.revvy.de/) | [✅](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/) | [✅](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/) | 🇨🇦 CA |
|
||||
| [search.davidovski.xyz](https://search.davidovski.xyz/) | ❌ | ❌ | 🇬🇧 GB |
|
||||
| [librey.nohost.network](https://librey.nohost.network/) | ❌ | ❌ | 🇲🇽 MX |
|
||||
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 instance:<br>
|
||||
[search.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>
|
||||
|
||||
|
||||
|
|
9
SECURITY.md
Normal file
9
SECURITY.md
Normal 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
|
6
auto_updater.sh
Normal file
6
auto_updater.sh
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
while true; do
|
||||
git stash
|
||||
git pull
|
||||
sleep 60
|
||||
done
|
|
@ -23,6 +23,9 @@
|
|||
// 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 the settings
|
||||
e.g.: Preset the invidious instance URL: "instance_url" => "https://yewtu.be",
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
version: "2.1"
|
||||
version: "3"
|
||||
services:
|
||||
librey:
|
||||
image: ahwxorg/librey:latest
|
||||
image: ghcr.io/ahwxorg/librey:latest
|
||||
container_name: librey
|
||||
network_mode: bridge
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- VERSION=docker
|
||||
- TZ=America/New_York
|
||||
- CONFIG_GOOGLE_DOMAIN=com
|
||||
- CONFIG_GOOGLE_LANGUAGE_SITE=en
|
||||
- CONFIG_GOOGLE_LANGUAGE_RESULTS=en
|
||||
- CONFIG_TEXT_SEARCH_ENGINE=google
|
||||
- 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_WIKIPEDIA_LANGUAGE=en
|
||||
- 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
|
||||
|
|
148
docker/README.md
148
docker/README.md
|
@ -3,15 +3,14 @@
|
|||
|
||||
- [Introduction](#introduction)
|
||||
- [Running a docker container](#running-a-docker-container)
|
||||
- [Running a Docker container through the Docker hub](#running-a-docker-container-through-the-docker-hub)
|
||||
- [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)
|
||||
- [OpenSearch](#opensearch)
|
||||
- [Search Config](#search-config)
|
||||
- [Wikipedia](#wikipedia)
|
||||
- [Applications](#applications)
|
||||
- [Engines](#engines)
|
||||
- [Curl](#curl)
|
||||
- [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)
|
||||
|
@ -20,7 +19,7 @@
|
|||
|
||||
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 the Docker hub
|
||||
### Running a Docker container through ghcr
|
||||
|
||||
To run librey in a docker container, you can simply use the command:
|
||||
|
||||
|
@ -32,7 +31,15 @@ docker run -d \
|
|||
-e CONFIG_GOOGLE_LANGUAGE="en" \
|
||||
-e CONFIG_WIKIPEDIA_LANGUAGE="en" \
|
||||
-p 8080:8080 \
|
||||
librey/librey:latest
|
||||
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>
|
||||
|
@ -40,26 +47,38 @@ docker run -d \
|
|||
### Running a Docker container with composer
|
||||
|
||||
```yml
|
||||
version: "2.1"
|
||||
version: "3"
|
||||
services:
|
||||
librey:
|
||||
image: librey/librey:latest
|
||||
image: ghcr.io/ahwxorg/librey:latest
|
||||
container_name: librey
|
||||
network_mode: bridge
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- VERSION=docker
|
||||
- TZ="America/New_York"
|
||||
- CONFIG_GOOGLE_DOMAIN="com"
|
||||
- CONFIG_GOOGLE_LANGUAGE="en"
|
||||
- CONFIG_WIKIPEDIA_LANGUAGE="en"
|
||||
- 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>
|
||||
|
@ -70,53 +89,25 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
|
||||
<br>
|
||||
|
||||
### OpenSearch
|
||||
### Search
|
||||
|
||||
| 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:8080" | string | Host used to identify librey on the network |
|
||||
|
||||
<br>
|
||||
|
||||
### Search Config
|
||||
|
||||
| Variables | Default | Examples | Description |
|
||||
|:----------|:-------------|:---------|:------|
|
||||
| CONFIG_GOOGLE_DOMAIN | "com" | "com", "com.br", "com.es" | Defines which Google domain the search will be done, change according to your country |
|
||||
| CONFIG_GOOGLE_LANGUAGE | "en" | "pt", "es", "ru" | 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_GOOGLE_NUMBER_OF_RESULTS | "10" | "10", "20", "30" | Number of results for Google to return each page. |
|
||||
| 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_INVIDIOUS_INSTANCE | "https://invidious.namazso.eu" | string | Defines the host that will be used to do video searches using invidious |
|
||||
| CONFIG_HIDDEN_SERVICE_SEARCH | false | boolean | Defines whether safesearch will be enabled or disabled |
|
||||
| CONFIG_DISABLE_BITTORRENT_SEARCH | false | boolean | Defines whether bittorrent support will be enabled or disabled |
|
||||
| CONFIG_BITTORRENT_TRACKERS | "http://nyaa.tracker.wf:7777/announce" | string | Bittorrent trackers, see the complete example in the `config.php` file. |
|
||||
|
||||
<br>
|
||||
|
||||
### Wikipedia
|
||||
| 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 |
|
||||
|:----------|:-------------|:---------|:------|
|
||||
| CONFIG_WIKIPEDIA_LANGUAGE | "en" | "pt", "es", "hu" | Adds language support for Wikipedia results |
|
||||
|
||||
<br>
|
||||
|
||||
### Engines
|
||||
| Variables | Default | Examples | Description |
|
||||
|:----------|:-------------|:---------|:------|
|
||||
| CONFIG_TEXT_SEARCH_ENGINE | "google" | "google", "duckduckgo" | Change your text search engine. |
|
||||
|
||||
<br>
|
||||
|
||||
### Applications
|
||||
|
||||
| Variables | Default | Examples | Description |
|
||||
|:----------|:-------------|:---------|:------|
|
||||
| APP_INVIDIOUS | "" | string | Integration with external self-hosted apps, configure the desired host. |
|
||||
| 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. |
|
||||
|
@ -131,22 +122,37 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
| 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. |
|
||||
|
||||
<br>
|
||||
|
||||
### Curl
|
||||
### 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 | "" | "127.0.0.1:8080" | 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 | **TODO** |
|
||||
| CURLOPT_ENCODING | "" | string | Defines the encode that curl should use to display the texts correctly |
|
||||
| CURLOPT_USERAGENT | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" | string | This variable defines the 'User-Agent' that curl will use to attempt to avoid being blocked |
|
||||
| CURLOPT_CUSTOMREQUEST | "GET" | "HEAD", "OPTIONS" | Defines the HTTP method that curl will use to make the request |
|
||||
| CURLOPT_MAXREDIRS | 5 | number | **TODO** |
|
||||
| CURLOPT_TIMEOUT | 18 | number | Sets the maximum time curl will wait for a response before timing out |
|
||||
| CURLOPT_VERBOSE | false | boolean | Specifies whether curl should display detailed information on stdout about the request and response when making requests. Setting to 'true' enables verbose mode |
|
||||
| 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>
|
||||
|
||||
|
@ -190,7 +196,7 @@ docker build -t librey:latest .
|
|||
|
||||
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 `build` process specifying the desired architecture as shown in the example below:
|
||||
In this case, you must run the `buildx` process specifying the desired architecture as shown in the example below:
|
||||
|
||||
```sh
|
||||
docker buildx build \
|
||||
|
|
|
@ -19,19 +19,16 @@ 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_GOOGLE_LANGUAGE_SITE="${CONFIG_GOOGLE_LANGUAGE_SITE:-"en"}"
|
||||
export CONFIG_GOOGLE_LANGUAGE_RESULTS="${CONFIG_GOOGLE_LANGUAGE_RESULTS:-"en"}"
|
||||
export CONFIG_GOOGLE_NUMBER_OF_RESULTS="${CONFIG_GOOGLE_NUMBER_OF_RESULTS:-"10"}"
|
||||
export CONFIG_INSTANCE_FALLBACK="${CONFIG_INSTANCE_FALLBACK:-true}"
|
||||
export CONFIG_INVIDIOUS_INSTANCE="${CONFIG_INVIDIOUS_INSTANCE:-"invidious.snopyta.org"}"
|
||||
export CONFIG_HIDDEN_SERVICE_SEARCH=${CONFIG_HIDDEN_SERVICE_SEARCH:-false}
|
||||
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"}"
|
||||
|
||||
# The settings that will be used to handle Wikipedia results displayed on the librey search page
|
||||
# the settings below can be edited via environment variables.
|
||||
export CONFIG_WIKIPEDIA_LANGUAGE=${CONFIG_WIKIPEDIA_LANGUAGE:-${CONFIG_GOOGLE_LANGUAGE}}
|
||||
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
|
||||
|
@ -59,11 +56,13 @@ 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) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"}"
|
||||
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:-18}
|
||||
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'; }
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
<?php
|
||||
return (object) array(
|
||||
|
||||
"google_domain" => "${CONFIG_GOOGLE_DOMAIN}",
|
||||
"google_language_site" => "${CONFIG_GOOGLE_LANGUAGE_SITE}",
|
||||
"google_language_results" => "${CONFIG_GOOGLE_LANGUAGE_RESULTS}",
|
||||
"google_number_of_results" => "${CONFIG_GOOGLE_NUMBER_OF_RESULTS}",
|
||||
|
||||
"wikipedia_language" => "${CONFIG_WIKIPEDIA_LANGUAGE}",
|
||||
"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(
|
||||
|
@ -34,7 +33,7 @@
|
|||
),
|
||||
"gothub" => array(
|
||||
"instance_url" => "${APP_GOTHUB}",
|
||||
"project_url" => "https://codeberg.org/gothub/gothub/wiki/Instances",
|
||||
"project_url" => "https://codeberg.org/gothub/gothub#instances",
|
||||
"original_name" => "GitHub",
|
||||
"original_url" => "github.com"
|
||||
),
|
||||
|
@ -44,10 +43,9 @@
|
|||
"original_name" => "Twitter",
|
||||
"original_url" => "twitter.com"
|
||||
),
|
||||
|
||||
"libreddit" => array(
|
||||
"instance_url" => "${APP_LIBREREDDIT}",
|
||||
"project_url" => "https://github.com/spikecodes/libreddit",
|
||||
"project_url" => "https://github.com/libreddit/libreddit-instances/blob/master/instances.md",
|
||||
"original_name" => "Reddit",
|
||||
"original_url" => "reddit.com"
|
||||
),
|
||||
|
@ -61,23 +59,23 @@
|
|||
"instance_url" => "${APP_WIKILESS}",
|
||||
"project_url" => "https://github.com/Metastem/wikiless#instances",
|
||||
"original_name" => "Wikipedia",
|
||||
"original_url" => "wikipedia.com"
|
||||
"original_url" => "wikipedia.org"
|
||||
),
|
||||
"quetre" => array(
|
||||
"instance_url" => "${APP_QUETRE}",
|
||||
"project_url" => "https://github.com/zyachel/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",
|
||||
"project_url" => "https://github.com/zyachel/libremdb#instances",
|
||||
"original_name" => "IMDb",
|
||||
"original_url" => "imdb.com"
|
||||
),
|
||||
"breezewiki" => array(
|
||||
"instance_url" => "${APP_BREEZEWIKI}",
|
||||
"project_url" => "https://gitdab.com/cadence/breezewiki",
|
||||
"project_url" => "https://docs.breezewiki.com/Links.html",
|
||||
"original_name" => "Fandom",
|
||||
"original_url" => "fandom.com"
|
||||
),
|
||||
|
@ -101,23 +99,25 @@
|
|||
)
|
||||
),
|
||||
|
||||
|
||||
"preferred_engines" => array(
|
||||
"text" => "${CONFIG_TEXT_SEARCH_ENGINE}"
|
||||
),
|
||||
|
||||
"curl_settings" => array(
|
||||
CURLOPT_PROXY => "${CURLOPT_PROXY}",
|
||||
CURLOPT_PROXYTYPE => "${CURLOPT_PROXYTYPE}",
|
||||
CURLOPT_PROXYTYPE => ${CURLOPT_PROXYTYPE},
|
||||
CURLOPT_RETURNTRANSFER => ${CURLOPT_RETURNTRANSFER},
|
||||
CURLOPT_ENCODING => "${CURLOPT_ENCODING}",
|
||||
CURLOPT_USERAGENT => "${CURLOPT_USERAGENT}",
|
||||
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_WHATEVER,
|
||||
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_VERBOSE => ${CURLOPT_VERBOSE},
|
||||
CURLOPT_FOLLOWLOCATION => ${CURLOPT_FOLLOWLOCATION}
|
||||
)
|
||||
);
|
||||
?>
|
|
@ -1,10 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Due to an issue with Docker's 'CMD' directive, the following scripts are not executing as expected.
|
||||
# This workaround has been implemented to resolve the issue for now
|
||||
sh "docker/php/prepare.sh"
|
||||
sh "docker/server/prepare.sh"
|
||||
/bin/sh -c docker/env-substitution.sh
|
||||
|
||||
/bin/sh -c /usr/sbin/php-fpm8
|
||||
/bin/sh -c /usr/sbin/php-fpm82
|
||||
|
||||
exec nginx -g "daemon off;"
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo "[PREPARE] docker/server/prepare.sh'"
|
||||
|
||||
# Load all environment variables from 'attributes.sh' using the command 'source /path/attributes.sh'
|
||||
source "docker/attributes.sh"
|
||||
|
||||
# This condition creates the Unix socket if 'php-fpm8.sock' does not already exist.
|
||||
# This fixes an issue where Nginx starts but does not serve content
|
||||
if [ ! -d "/run/php8" ] || [ ! -S "/run/php8/php-fpm8.sock" ]; then
|
||||
mkdir "/run/php8"
|
||||
touch "/run/php8/php-fpm8.sock"
|
||||
chmod 660 "/run/php8/php-fpm8.sock"
|
||||
chown nginx:nginx "/run/php8/php-fpm8.sock"
|
||||
fi
|
||||
|
||||
# The lines below will replace the environment variables in the templates with the corresponding variables listed above. To accomplish this, the GNU 'envsubst' package will be used
|
||||
# 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/php/config.php' | envsubst > ${CONFIG_PHP_TEMPLATE};
|
||||
[[ ! -s ${CONFIG_OPEN_SEARCH_TEMPLATE} ]] && cat 'docker/php/opensearch.xml' | envsubst > ${CONFIG_OPEN_SEARCH_TEMPLATE};
|
||||
|
||||
[[ ! -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'
|
|
@ -2,6 +2,10 @@ 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;
|
||||
|
||||
|
@ -10,7 +14,7 @@ server {
|
|||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass unix:/run/php8/php-fpm8.sock;
|
||||
fastcgi_pass unix:/run/php-fpm82.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi.conf;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
# Set this argument during build time to indicate that the path is for php's www.conf
|
||||
ARG WWW_CONFIG="/etc/php8/php-fpm.d/www.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
|
||||
ENV OPEN_SEARCH_TITLE="LibreY"
|
||||
ENV OPEN_SEARCH_DESCRIPTION="Framework and javascript free privacy respecting meta search engine"
|
||||
ENV OPEN_SEARCH_ENCODING="UTF-8"
|
||||
ENV OPEN_SEARCH_LONG_NAME="LibreY search"
|
||||
ENV OPEN_SEARCH_HOST="http://127.0.0.1:${NGINX_PORT}"
|
||||
|
||||
# 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
|
||||
ENV CONFIG_GOOGLE_DOMAIN="com"
|
||||
ENV CONFIG_GOOGLE_LANGUAGE_SITE="en"
|
||||
ENV CONFIG_GOOGLE_LANGUAGE_RESULTS="en"
|
||||
ENV CONFIG_GOOGLE_NUMBER_OF_RESULTS="10"
|
||||
ENV CONFIG_INSTANCE_FALLBACK=true
|
||||
ENV CONFIG_INVIDIOUS_INSTANCE="https://invidious.snopyta.org"
|
||||
ENV CONFIG_HIDDEN_SERVICE_SEARCH=false
|
||||
ENV CONFIG_DISABLE_BITTORRENT_SEARCH=false
|
||||
ENV 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"
|
||||
|
||||
# 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
|
||||
ENV APP_INVIDIOUS=""
|
||||
ENV APP_RIMGO=""
|
||||
ENV APP_SCRIBE=""
|
||||
ENV APP_GOTHUB=""
|
||||
ENV APP_NITTER=""
|
||||
ENV APP_LIBREREDDIT=""
|
||||
ENV APP_PROXITOK=""
|
||||
ENV APP_WIKILESS=""
|
||||
ENV APP_QUETRE=""
|
||||
ENV APP_LIBREMDB=""
|
||||
ENV APP_BREEZEWIKI=""
|
||||
ENV APP_ANONYMOUS_OVERFLOW=""
|
||||
ENV APP_SUDS=""
|
||||
ENV APP_BIBLIOREADS=""
|
||||
|
||||
# Preferred search engines.
|
||||
ENV 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
|
||||
ENV CURLOPT_PROXY_ENABLED=false
|
||||
ENV CURLOPT_PROXY=""
|
||||
ENV CURLOPT_PROXYTYPE="CURLPROXY_HTTP"
|
||||
ENV CURLOPT_RETURNTRANSFER=true
|
||||
ENV CURLOPT_ENCODING=""
|
||||
ENV CURLOPT_USERAGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
|
||||
ENV CURLOPT_CUSTOMREQUEST="GET"
|
||||
ENV CURLOPT_MAXREDIRS=5
|
||||
ENV CURLOPT_TIMEOUT=18
|
||||
ENV CURLOPT_VERBOSE=true
|
||||
|
||||
# Install PHP-FPM using Alpine's package manager, apk
|
||||
# Configure PHP-FPM to listen on a Unix socket instead of a TCP port, which is more secure and efficient
|
||||
RUN apk add php8 php8-fpm php8-dom php8-curl php8-json php8-apcu --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing &&\
|
||||
sed -i 's/^\s*listen = 127.0.0.1:9000/listen = \/run\/php8\/php-fpm8.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}
|
||||
|
||||
CMD [ "/bin/sh", "-c", "docker/php/prepare.sh" ]
|
|
@ -1,9 +0,0 @@
|
|||
# Install Nginx with FastCGI enabled, optimizing its performance for serving content
|
||||
RUN apk add nginx
|
||||
|
||||
# Forward request and error logs to docker log collector
|
||||
# RUN ln -sf /dev/stdout /var/log/nginx/access.log &&\
|
||||
# ln -sf /dev/stderr /var/log/nginx/error.log
|
||||
|
||||
# After executing the 'docker run' command, run the 'prepare.sh' script
|
||||
CMD [ "/bin/sh", "-c", "docker/server/prepare.sh" ]
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo "[PREPARE] docker/server/prepare.sh'"
|
||||
|
||||
# Load all environment variables from 'attributes.sh' using the command 'source /path/attributes.sh'
|
||||
source "docker/attributes.sh"
|
||||
|
||||
export OPEN_SEARCH_HOST_FOR_NGINX="$(echo "${OPEN_SEARCH_HOST}" | cut -d "/" -f 3 | cut -d ":" -f 1)"
|
||||
|
||||
# The lines below will replace the environment variables in the templates with the corresponding variables listed above. 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
|
||||
if [[ ! -s ${CONFIG_NGINX_TEMPLATE} ]]; then
|
||||
cp "docker/server/fastcgi.conf" /etc/nginx/fastcgi.conf
|
||||
cp "docker/server/nginx.conf" /etc/nginx/http.d/librey.conf
|
||||
|
||||
# To address issues with 'nginx.conf', the following lines will ensure that these configurations remain executable
|
||||
chmod u+x "/etc/nginx/fastcgi.conf"
|
||||
chmod u+x "/etc/nginx/http.d/librey.conf"
|
||||
|
||||
cat 'docker/server/nginx.conf' | envsubst '${OPEN_SEARCH_HOST_FOR_NGINX}' > ${CONFIG_NGINX_TEMPLATE};
|
||||
fi
|
90
donate.php
90
donate.php
|
@ -7,16 +7,86 @@
|
|||
<title>LibreY - Donate</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="misc-container">
|
||||
<h1>Donate to the original developer of LibreX, a project LibreY tries to improve.</h1>
|
||||
<h2>Bitcoin (BTC):</h2>
|
||||
<p>bc1qs43kh6tvhch02dtsp7x7hcrwj8fwe4rzy7lp0h</p>
|
||||
<img src="static/images/btc.png" alt="btc qr code" width="150" height="150"/>
|
||||
<h2>Monero (XMR):</h2>
|
||||
<p>41dGQr9EwZBfYBY3fibTtJZYfssfRuzJZDSVDeneoVcgckehK3BiLxAV4FvEVJiVqdiW996zvMxhFB8G8ot9nBFqQ84VkuC</p>
|
||||
<img src="static/images/xmr.png" alt="xmr qr code" width="150" height="150"/>
|
||||
<h1>Donate to the person that forked LibreX into LibreY</h1>
|
||||
<a href="https://ahwx.org/donate.php">Click here</a>
|
||||
<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"; ?>
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
return "https://ahmia.fi/search/?q=" . urlencode($this->query);
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
$xpath = get_xpath($response);
|
||||
|
||||
|
@ -24,6 +23,7 @@
|
|||
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)
|
||||
)
|
||||
|
@ -33,8 +33,8 @@
|
|||
return $results;
|
||||
}
|
||||
|
||||
public static function print_results($results) {
|
||||
TextSearch::print_results($results);
|
||||
public static function print_results($results, $opts) {
|
||||
TextSearch::print_results($results, $opts);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
return "https://1337x.to/search/$query/1/";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
|
||||
public function parse_results($response) {
|
||||
$xpath = get_xpath($response);
|
||||
$results = array();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
);
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
foreach ($this->requests as $request) {
|
||||
if ($request->successful())
|
||||
|
@ -34,7 +34,7 @@
|
|||
return $results;
|
||||
}
|
||||
|
||||
public static function print_results($results) {
|
||||
public static function print_results($results, $opts) {
|
||||
echo "<div class=\"text-result-container\">";
|
||||
|
||||
if (empty($results)) {
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
return "https://$this->SOURCE/?q=" . urlencode($this->query);
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
public function parse_results($response) {
|
||||
$xpath = get_xpath($response);
|
||||
$results = array();
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
return "http://rutor.info/search/" . urlencode($this->query);
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
public function parse_results($response) {
|
||||
$xpath = get_xpath($response);
|
||||
$results = array();
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
return "https://apibay.org/q.php?q=" . urlencode($this->query);
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
$json_response = json_decode($response, true);
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
return "https://torrentgalaxy.to/torrents.php?search=$query#results";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
public function parse_results($response) {
|
||||
$xpath = get_xpath($response);
|
||||
$results = array();
|
||||
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
return "https://yts.mx/api/v2/list_movies.json?query_term=" . urlencode($this->query);
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
public function parse_results($response) {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
global $config;
|
||||
$results = array();
|
||||
$json_response = json_decode($response, true);
|
||||
|
||||
|
|
|
@ -6,16 +6,14 @@
|
|||
return "$this->instance_url/api/v1/search?q=$query";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
$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"];
|
||||
$url = check_for_privacy_frontend($url, $this->opts);
|
||||
$uploader = $response["author"];
|
||||
$views = $response["viewCount"];
|
||||
$date = $response["publishedText"];
|
||||
|
@ -25,6 +23,7 @@
|
|||
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),
|
||||
|
@ -38,13 +37,14 @@
|
|||
return $results;
|
||||
}
|
||||
|
||||
public static function print_results($results) {
|
||||
public static function print_results($results, $opts) {
|
||||
echo "<div class=\"text-result-container\">";
|
||||
|
||||
foreach($results as $result) {
|
||||
$title = $result["title"];
|
||||
$url = $result["url"];
|
||||
$base_url = $result["base_url"];
|
||||
$url = check_for_privacy_frontend($url, $opts);
|
||||
$base_url = get_base_url($url);
|
||||
$uploader = $result["uploader"];
|
||||
$views = $result["views"];
|
||||
$date = $result["date"];
|
||||
|
|
|
@ -7,11 +7,10 @@
|
|||
}
|
||||
|
||||
public function get_request_url() {
|
||||
return $this->instance . "api.php?" . opts_to_params($this->opts);
|
||||
return $this->instance . "api.php?" . opts_to_params($this->opts) . "&nfb=1";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_exec($this->ch);
|
||||
public function parse_results($response) {
|
||||
$response = json_decode($response, true);
|
||||
if (!$response)
|
||||
return array();
|
||||
|
@ -47,13 +46,17 @@
|
|||
|
||||
$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 (count($results) > 1)
|
||||
if (!empty($results))
|
||||
return $results;
|
||||
|
||||
// on fail then do this
|
||||
|
@ -62,7 +65,11 @@
|
|||
|
||||
} while (!empty($instances));
|
||||
|
||||
return array();
|
||||
return array(
|
||||
"error" => array(
|
||||
"message" => "No results found. Unable to fallback to other instances."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
return "https://lite.qwant.com/?q=$query&t=images&p=$page";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
$xpath = get_xpath(curl_multi_getcontent($this->ch));
|
||||
$xpath = get_xpath($response);
|
||||
|
||||
if (!$xpath)
|
||||
return $results;
|
||||
|
@ -24,7 +24,6 @@
|
|||
$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, $this->opts);
|
||||
|
||||
$alt = $image->getAttribute("alt");
|
||||
$thumbnail = urlencode($image->getAttribute("src"));
|
||||
|
@ -43,7 +42,7 @@
|
|||
return $results;
|
||||
}
|
||||
|
||||
public static function print_results($results) {
|
||||
public static function print_results($results, $opts) {
|
||||
echo "<div class=\"image-result-container\">";
|
||||
|
||||
foreach($results as $result)
|
||||
|
@ -51,6 +50,7 @@
|
|||
$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\">";
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
return "https://cdn.moneyconvert.net/api/latest.json";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
|
||||
public function parse_results($response) {
|
||||
$split_query = explode(" ", $this->query);
|
||||
|
||||
$base_currency = strtoupper($split_query[1]);
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
return "https://api.dictionaryapi.dev/api/v2/entries/en/$word_to_define";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
|
||||
public function parse_results($response) {
|
||||
$json_response = json_decode($response, true);
|
||||
|
||||
if (!array_key_exists("title", $json_response))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
class IPRequest extends EngineRequest {
|
||||
function get_results() {
|
||||
public function parse_results($response) {
|
||||
return array(
|
||||
"special_response" => array(
|
||||
"response" => $_SERVER["REMOTE_ADDR"],
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
return "https://check.torproject.org/torbulkexitlist";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($ch);
|
||||
|
||||
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";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
class UserAgentRequest extends EngineRequest {
|
||||
function get_results() {
|
||||
public function parse_results($response) {
|
||||
return array(
|
||||
"special_response" => array(
|
||||
"response" => $_SERVER["HTTP_USER_AGENT"],
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
return "https://wttr.in/@" . $_SERVER["REMOTE_ADDR"] . "?format=j1";
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
public function parse_results($response) {
|
||||
$json_response = json_decode($response, true);
|
||||
|
||||
if (!$json_response)
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<?php
|
||||
class WikipediaRequest extends EngineRequest {
|
||||
public function get_request_url() {
|
||||
$this->wikipedia_language = $this->opts->language;
|
||||
$this->wikipedia_domain = "wikipedia.org";
|
||||
$query_encoded = urlencode($this->query);
|
||||
|
||||
if (!in_array($this->wikipedia_language, json_decode(file_get_contents("static/misc/wikipedia_langs.json"), true)))
|
||||
$this->wikipedia_language = "en";
|
||||
$languages = json_decode(file_get_contents("static/misc/languages.json"), true);
|
||||
|
||||
return "https://$this->wikipedia_language.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
|
||||
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 get_results() {
|
||||
$response = curl_multi_getcontent($this->ch);
|
||||
|
||||
public function parse_results($response) {
|
||||
$json_response = json_decode($response, true);
|
||||
|
||||
$first_page = array_values($json_response["query"]["pages"])[0];
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
$description = substr($first_page["extract"], 0, 250) . "...";
|
||||
|
||||
$source = check_for_privacy_frontend("https://$this->wikipedia_language.wikipedia.org/wiki/$this->query", $this->opts);
|
||||
$source = "https://$this->wikipedia_domain/wiki/$this->query";
|
||||
$response = array(
|
||||
"special_response" => array(
|
||||
"response" => htmlspecialchars($description),
|
||||
|
|
|
@ -19,30 +19,30 @@
|
|||
|
||||
if (isset($_COOKIE["safe_search"]))
|
||||
$url .= "&safe=medium";
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function get_results() {
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
$xpath = get_xpath(curl_multi_getcontent($this->ch));
|
||||
$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/div") as $result)
|
||||
{
|
||||
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 (!empty($results)) { // filter duplicate results
|
||||
if (end($results)["url"] == $url->textContent)
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = $url->textContent;
|
||||
|
||||
$url = check_for_privacy_frontend($url, $this->opts);
|
||||
|
||||
$title = $xpath->evaluate(".//h2[@class='result__title']", $result)[0];
|
||||
$description = $xpath->evaluate(".//a[@class='result__snippet']", $result)[0];
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
|||
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." :
|
||||
|
@ -57,7 +58,7 @@
|
|||
)
|
||||
);
|
||||
}
|
||||
return $results;
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
}
|
||||
|
||||
|
||||
public function get_results() {
|
||||
public function parse_results($response) {
|
||||
$results = array();
|
||||
$xpath = get_xpath(curl_multi_getcontent($this->ch));
|
||||
$xpath = get_xpath($response);
|
||||
|
||||
if (!$xpath)
|
||||
return $results;
|
||||
|
@ -53,7 +53,6 @@
|
|||
}
|
||||
|
||||
$url = $url->textContent;
|
||||
$url = check_for_privacy_frontend($url, $this->opts);
|
||||
|
||||
$title = $xpath->evaluate(".//h3", $result)[0];
|
||||
$description = $xpath->evaluate(".//div[contains(@class, 'VwiC3b')]", $result)[0];
|
||||
|
@ -62,6 +61,7 @@
|
|||
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." :
|
||||
|
@ -70,6 +70,12 @@
|
|||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
if (substr($this->query, 0, 1) == "!" || substr($last_word_query, 0, 1) == "!")
|
||||
check_ddg_bang($this->query, $opts);
|
||||
|
||||
if (has_cooldown($this->engine, $this->opts->cooldowns))
|
||||
return;
|
||||
|
||||
if ($this->engine == "google") {
|
||||
|
||||
require "engines/text/google.php";
|
||||
|
@ -26,38 +23,53 @@
|
|||
$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 get_results() {
|
||||
if (!$this->engine_request)
|
||||
public function parse_results($response) {
|
||||
if (!isset($this->engine_request))
|
||||
return array();
|
||||
|
||||
$results = $this->engine_request->get_results();
|
||||
|
||||
if ($this->special_request) {
|
||||
$special_result = $this->special_request->get_results();
|
||||
|
||||
if ($special_result)
|
||||
$results = array_merge(array($special_result), $results);
|
||||
}
|
||||
|
||||
if (count($results) <= 1)
|
||||
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) {
|
||||
public static function print_results($results, $opts) {
|
||||
|
||||
if (empty($results))
|
||||
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))
|
||||
{
|
||||
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 ";
|
||||
|
@ -65,33 +77,34 @@
|
|||
echo "?</p>";
|
||||
}
|
||||
|
||||
if (array_key_exists("special_response", $special))
|
||||
{
|
||||
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"]))
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
foreach($results as $result) {
|
||||
if (!array_key_exists("title", $result))
|
||||
continue;
|
||||
|
||||
$title = $result["title"];
|
||||
$url = $result["url"];
|
||||
$base_url = $result["base_url"];
|
||||
$url = check_for_privacy_frontend($url, $opts);
|
||||
|
||||
$base_url = get_base_url($url);
|
||||
$description = $result["description"];
|
||||
|
||||
echo "<div class=\"text-result-wrapper\">";
|
||||
|
@ -107,8 +120,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function check_ddg_bang($query, $opts)
|
||||
{
|
||||
function check_ddg_bang($query, $opts) {
|
||||
|
||||
$bangs_json = file_get_contents("static/misc/ddg_bang.json");
|
||||
$bangs = json_decode($bangs_json, true);
|
||||
|
@ -120,22 +132,18 @@
|
|||
|
||||
$bang_url = null;
|
||||
|
||||
foreach($bangs as $bang)
|
||||
{
|
||||
if ($bang["t"] == $search_word)
|
||||
{
|
||||
foreach($bangs as $bang) {
|
||||
if ($bang["t"] == $search_word) {
|
||||
$bang_url = $bang["u"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bang_url)
|
||||
{
|
||||
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);
|
||||
$request_url = check_for_privacy_frontend($request_url, $opts);
|
||||
|
||||
header("Location: " . $request_url);
|
||||
die();
|
||||
|
|
|
@ -2,11 +2,18 @@
|
|||
"instances": [
|
||||
{
|
||||
"clearnet": "https://search.ahwx.org/",
|
||||
"tor": "http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion/",
|
||||
"tor": "http://wn5jl6fxlzzfenlyu3lc4q7jpw2saplrywxvxtvqbguotwd4y5cjeuqd.onion/",
|
||||
"i2p": null,
|
||||
"country": "NL",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search2.ahwx.org/",
|
||||
"tor": "http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion/",
|
||||
"i2p": null,
|
||||
"country": "FR",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.me/",
|
||||
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
|
||||
|
@ -28,6 +35,13 @@
|
|||
"country": "CL",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.vern.cc/",
|
||||
"tor": "http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/",
|
||||
"i2p": "http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/",
|
||||
"country": "US",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librey.org/",
|
||||
"tor": "http://jxhkfulu6wpdl4apuy4dyivuowmpprvsd7e3el2z73crq7fmyv7rjkyd.onion/",
|
||||
|
@ -35,6 +49,13 @@
|
|||
"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,
|
||||
|
@ -77,47 +98,47 @@
|
|||
"country": "MX",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.vern.cc/",
|
||||
"tor": "http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/",
|
||||
"i2p": "http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/",
|
||||
"country": "US",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.owo.si/",
|
||||
"tor": "http://lx.pk47sgwhncn5cgidm7bofngmh7lc7ukjdpk5bjwfemmyp27ovl25ikyd.onion/",
|
||||
"i2p": "http://d4vi3tvfui2rfzsxr33tin4a6542heulf4mhkokdpbhbcejlg3la.b32.i2p/",
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.spaceint.fr/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "FR",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.pabloferreiro.es/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.ratakor.com/",
|
||||
"clearnet": "https://search.ratakor.com/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "FR",
|
||||
"librey": false
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.tildevarsh.in/",
|
||||
"clearnet": "https://librex.yogeshlamichhane.com.np/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "IN",
|
||||
"librey": false
|
||||
"country": "FI",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librey.baczek.me/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "PL",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.benike.me/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.seitan-ayoub.lol/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.myroware.eu/",
|
||||
|
@ -139,20 +160,6 @@
|
|||
"i2p": null,
|
||||
"country": "PL",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.benike.monster/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.pardesicat.xyz/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "KR",
|
||||
"librey": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<title>LibreY - instances</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="misc-container">
|
||||
<center>
|
||||
<h2>Libre<span class="Y">Y</span> instances</h2>
|
||||
<?php
|
||||
|
@ -56,6 +56,7 @@
|
|||
list_instances($librex_instances);
|
||||
?>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
|
||||
<?php require "misc/footer.php"; ?>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<?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();
|
||||
|
@ -19,4 +23,23 @@
|
|||
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();
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
<?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;
|
||||
|
||||
$url = $this->get_request_url();
|
||||
if (!$url)
|
||||
$this->url = $this->get_request_url();
|
||||
if (!$this->url)
|
||||
return;
|
||||
|
||||
$this->ch = curl_init($url);
|
||||
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);
|
||||
|
@ -23,17 +29,39 @@
|
|||
}
|
||||
|
||||
public function successful() {
|
||||
return curl_getinfo($this->ch)['http_code'] == '200';
|
||||
return (isset($this->ch) && curl_getinfo($this->ch)['http_code'] == '200')
|
||||
|| has_cached_results($this->url);
|
||||
}
|
||||
|
||||
abstract function get_results();
|
||||
static public function print_results($results){}
|
||||
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);
|
||||
|
@ -47,7 +75,7 @@
|
|||
|
||||
$opts->disable_frontends = (int) ($_REQUEST["nf"] ?? 0) == 1 || isset($_COOKIE["disable_frontends"]);
|
||||
|
||||
$opts->language = $_REQUEST["lang"] ?? trim(htmlspecialchars($_COOKIE["language"] ?? $opts->language));
|
||||
$opts->language = $_REQUEST["lang"] ?? trim(htmlspecialchars($_COOKIE["language"] ?? $opts->language ?? "en"));
|
||||
|
||||
$opts->do_fallback = (int) ($_REQUEST["nfb"] ?? 0) == 0;
|
||||
if (!$opts->instance_fallback) {
|
||||
|
@ -60,6 +88,8 @@
|
|||
$opts->frontends[$frontend]["instance_url"] = $_COOKIE[$frontend] ?? $opts->frontends[$frontend]["instance_url"];
|
||||
}
|
||||
|
||||
$opts->curl_settings[CURLOPT_FOLLOWLOCATION] ??= true;
|
||||
|
||||
return $opts;
|
||||
}
|
||||
|
||||
|
@ -70,7 +100,6 @@
|
|||
$params .= "p=$opts->page";
|
||||
$params .= "&q=$query";
|
||||
$params .= "&t=$opts->type";
|
||||
$params .= "&nfb=" . ($opts->do_fallback ? 0 : 1);
|
||||
$params .= "&safe=" . ($opts->safe_search ? 1 : 0);
|
||||
$params .= "&nf=" . ($opts->disable_frontends ? 1 : 0);
|
||||
$params .= "&ns=" . ($opts->disable_special ? 1 : 0);
|
||||
|
@ -113,7 +142,6 @@
|
|||
}
|
||||
|
||||
function fetch_search_results($opts, $do_print) {
|
||||
require "misc/cooldowns.php";
|
||||
$opts->cooldowns = load_cooldowns();
|
||||
|
||||
$start_time = microtime(true);
|
||||
|
@ -128,7 +156,7 @@
|
|||
|
||||
$results = $search_category->get_results();
|
||||
|
||||
if (count($results) <= 1) {
|
||||
if (empty($results)) {
|
||||
require "engines/librex/fallback.php";
|
||||
$results = get_librex_results($opts);
|
||||
}
|
||||
|
@ -137,7 +165,7 @@
|
|||
return $results;
|
||||
|
||||
print_elapsed_time($start_time);
|
||||
$search_category->print_results($results);
|
||||
$search_category->print_results($results, $opts);
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?php
|
||||
function get_base_url($url) {
|
||||
$split_url = explode("/", $url);
|
||||
$base_url = $split_url[0] . "//" . $split_url[2] . "/";
|
||||
return $base_url;
|
||||
$parsed = parse_url($url);
|
||||
return $parsed["scheme"] . "://" . $parsed["host"] . "/";
|
||||
}
|
||||
|
||||
function get_root_domain($url) {
|
||||
|
|
29
settings.php
29
settings.php
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
require "misc/search_engine.php";
|
||||
$opts = load_opts();
|
||||
|
||||
// Reset all cookies when resetting, or before saving new cookies
|
||||
if (isset($_REQUEST["reset"]) || isset($_REQUEST["save"])) {
|
||||
|
@ -29,6 +28,8 @@
|
|||
die();
|
||||
}
|
||||
|
||||
$opts = load_opts();
|
||||
|
||||
require "misc/header.php";
|
||||
?>
|
||||
|
||||
|
@ -59,7 +60,7 @@
|
|||
<option value=\"ubuntu\">Ubuntu</option>
|
||||
<option value=\"tokyo_night\">Tokyo night</option>";
|
||||
|
||||
if (isset($_COOKIE["theme"])) {
|
||||
if (isset($opts->theme)) {
|
||||
$theme = $opts->theme;
|
||||
$themes = str_replace($theme . "\"", $theme . "\" selected", $themes);
|
||||
}
|
||||
|
@ -97,19 +98,31 @@
|
|||
<div class="settings-textbox-container">
|
||||
<div>
|
||||
<span>Language</span>
|
||||
<select name="language">
|
||||
<?php
|
||||
// TODO make this a dropdown
|
||||
echo "<input type=\"text\" name=\"language\" placeholder=\"any\" value=\"" . htmlspecialchars($opts->language ?? "") . "\">";
|
||||
|
||||
$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>
|
||||
<label>Safe search</label>
|
||||
<input type="checkbox" name="safe_search" <?php echo $opts->safe_search ? "checked" : ""; ?> >
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label>Safe search</label>
|
||||
<input type="checkbox" name="safe_search" <?php echo $opts->safe_search ? "checked" : ""; ?> >
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
@ -151,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;
|
||||
|
@ -319,8 +319,7 @@ a[title] {
|
|||
}
|
||||
|
||||
.footer-container a {
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.hide {
|
||||
|
@ -339,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;
|
||||
|
@ -485,4 +538,53 @@ a[title] {
|
|||
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 */
|
||||
|
||||
|
||||
}
|
BIN
static/images/buy-me-a-coffee.png
Normal file
BIN
static/images/buy-me-a-coffee.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
BIN
static/images/kofi.png
Normal file
BIN
static/images/kofi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8 KiB |
BIN
static/images/xmr-ahwx.png
Normal file
BIN
static/images/xmr-ahwx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
1
static/misc/languages.json
Normal file
1
static/misc/languages.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
["ab","ace","ady","af","ak","als","am","an","ang","ar","arc","ary","arz","as","ast","atj","av","avk","awa","ay","az","azb","ba","ban","bar","bat-smg","bcl","be","be-tarask","bg","bh","bi","bjn","bm","bn","bo","bpy","br","bs","bug","bxr","ca","cbk-zam","cdo","ce","ceb","ch","chr","chy","ckb","co","cr","crh","cs","csb","cu","cv","cy","da","de","din","diq","dsb","dty","dv","dz","ee","el","eml","en","eo","es","et","eu","ext","fa","ff","fi","fiu-vro","fj","fo","fr","frp","frr","fur","fy","ga","gag","gan","gcr","gd","gl","glk","gn","gom","gor","got","gu","gv","ha","hak","haw","he","hi","hif","hr","hsb","ht","hu","hy","hyw","ia","id","ie","ig","ik","ilo","inh","io","is","it","iu","ja","jam","jbo","jv","ka","kaa","kab","kbd","kbp","kg","ki","kk","kl","km","kn","ko","koi","krc","ks","ksh","ku","kv","kw","ky","la","lad","lb","lbe","lez","lfn","lg","li","lij","lld","lmo","ln","lo","lt","ltg","lv","mad","mai","map-bms","mdf","mg","mhr","mi","min","mk","ml","mn","mnw","mr","mrj","ms","mt","mwl","my","myv","mzn","na","nah","nap","nds","nds-nl","ne","new","nia","nl","nn","no","nostalgia","nov","nqo","nrm","nso","nv","ny","oc","olo","om","or","os","pa","pag","pam","pap","pcd","pdc","pfl","pi","pih","pl","pms","pnb","pnt","ps","pt","qu","rm","rmy","rn","ro","roa-rup","roa-tara","ru","rue","rw","sa","sah","sat","sc","scn","sco","sd","se","sg","sh","shn","si","simple","sk","skr","sl","sm","smn","sn","so","sq","sr","srn","ss","st","stq","su","sv","sw","szl","szy","ta","tcy","te","tet","tg","th","ti","tk","tl","tn","to","tpi","tr","ts","tt","tum","tw","ty","tyv","udm","ug","uk","ur","uz","ve","vec","vep","vi","vls","vo","wa","war","wo","wuu","xal","xh","xmf","yi","yo","za","zea","zh","zh-classical","zh-min-nan","zh-yue","zu","zh-hans","zh-hant","zh-cn","zh-hk","zh-mo","zh-my","zh-sg","zh-tw"]
|
Loading…
Reference in a new issue