Merge remote-tracking branch 'librey/main' into librey
This commit is contained in:
commit
7f5950a5ff
27 changed files with 522 additions and 182 deletions
15
Dockerfile
15
Dockerfile
|
@ -1,19 +1,18 @@
|
|||
# syntax = edrevo/dockerfile-plus
|
||||
ARG VERSION="3.18"
|
||||
FROM alpine:${VERSION} AS librex
|
||||
FROM alpine:${VERSION} AS librey
|
||||
WORKDIR "/var/www/html"
|
||||
|
||||
# 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="LibreX" \
|
||||
LABEL name="LibreY" \
|
||||
description="Framework and javascript free privacy respecting meta search engine" \
|
||||
version="1.0" \
|
||||
vendor="Hnhx Femboy<femboy.hu>" \
|
||||
maintainer="Hnhx Femboy<femboy.hu>, Junior L. Botelho<juniorbotelho.com.br>" \
|
||||
url="https://github.com/hnhx/librex" \
|
||||
usage="https://github.com/hnhx/librex/wiki" \
|
||||
authors="https://github.com/hnhx/librex/contributors"
|
||||
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
|
||||
|
@ -31,7 +30,7 @@ RUN apk add gettext --no-cache
|
|||
INCLUDE+ docker/php/php.dockerfile
|
||||
INCLUDE+ docker/server/nginx.dockerfile
|
||||
|
||||
# Include docker scripts, docker images, and the 'GNU License' in the Librex container
|
||||
# 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
|
||||
|
|
60
README.md
60
README.md
|
@ -1,65 +1,39 @@
|
|||
<h1 align="center">LibreX</h1>
|
||||
<h1 align="center">LibreY</h1>
|
||||
|
||||
# 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">Framework and javascript free privacy respecting meta search engine</p>
|
||||
<p align="center"></p>
|
||||
|
||||
<br>
|
||||
|
||||
### Instances
|
||||
|
||||
> If you host using CloudFlare, this will be mentioned in the instances list.
|
||||
|
||||
| Clearnet | TOR | I2P | Country |
|
||||
|-|-|-|-|
|
||||
| [librex.zzls.xyz](https://librex.zzls.xyz/) | [✅](http://librex.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion/) | [✅](http://zzlsaymhcfla7vibo3a223bybeecu3bd5z6rmw2u4y76maqeu76q.b32.i2p) | 🇨🇱 CL |
|
||||
| [search.ahwx.org](https://search.ahwx.org/) | [✅](http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion) | ❌ | 🇫🇷 FR (temp) |
|
||||
| [librex.me](https://librex.me/) | [✅](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/) | [✅](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/) | 🇨🇦 CA |
|
||||
| [s.dyox.in](https://s.dyox.in/) | [✅](http://ddhigxwjz7elcl2erm7qzzukda4qmovoy4cepcueahggpwrpu24mi6qd.onion/) | [✅](http://s.dyoxin.i2p/) | 🇮🇸 IS |
|
||||
| [lx.vern.cc](https://lx.vern.cc/) | [✅](http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/) | [✅](http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/) | 🇺🇸 US |
|
||||
| [search.ahwx.org](https://search.ahwx.org/) | [✅](http://cosrpybbddzdfjquer3zfmb2h5avtacnctnbu4gucwocdb42s63gcqqd.onion/) | ❌ | 🇳🇱 NL |
|
||||
| [search.spaceint.fr](https://search.spaceint.fr/) | [✅](http://6d4nqt2rndvmhogpwrbqfvj2ur6e6nm2r6dzi7ny4wj6ai3j5hnvbhyd.onion/) | ❌ | 🇫🇷 FR |
|
||||
| [search.davidovski.xyz](https://search.davidovski.xyz/) | ❌ | ❌ | 🇬🇧 UK |
|
||||
| [search.madreyk.xyz](https://search.madreyk.xyz/) | ❌ | ❌ | 🇩🇪 DE |
|
||||
| [search.pabloferreiro.es](https://search.pabloferreiro.es/) | ❌ | ❌ | 🇩🇪 DE |
|
||||
| [librex.pufe.org](https://librex.pufe.org/) | ❌ | ❌ | :new_zealand: NZ |
|
||||
| [librex.ratakor.com](https://librex.ratakor.com/) | ❌ | ❌ | 🇫🇷 FR |
|
||||
| [search.tildevarsh.in](https://search.tildevarsh.in/) | ❌ | ❌ | 🇮🇳 IN |
|
||||
| [librex.myroware.eu](https://librex.myroware.eu/) | ❌ | ❌ | 🇩🇪 DE |
|
||||
| [librex.bloatcat.tk](https://librex.bloatcat.tk/) | ❌ | ❌ | 🇮🇸 IS |
|
||||
| [librex.retro-hax.net](https://librex.retro-hax.net/) | ❌ | ❌ | 🇩🇪 DE |
|
||||
| [search.funami.tech](https://search.funami.tech/) | ❌ | ❌ | 🇰🇷 KR |
|
||||
| [search.zeroish.xyz](https://search.zeroish.xyz/) | ❌| ❌ | 🇺🇸 US |
|
||||
| [librex.baczek.me](https://librex.baczek.me/) | ❌| ❌ | 🇵🇱 PL |
|
||||
| [librex.yogeshlamichhane.com.np](https://librex.yogeshlamichhane.com.np/) | ❌| ❌ | 🇺🇸 US |
|
||||
| [lx.benike.monster](https://lx.benike.monster/) | ❌ | ❌ | 🇩🇪 DE |
|
||||
| [librex.nohost.network](https://librex.nohost.network/) | ❌ | ❌ | 🇲🇽 MX |
|
||||
| [search.decentrala.org](https://search.decentrala.org/) | ❌| ❌ | 🇺🇸 US |
|
||||
<br>
|
||||
|
||||
### Thanks rms
|
||||
|
||||
Huge thanks to Richard Stallman for using LibreX and featuring it on his [website](https://stallman.org/stallman-computing.html)!
|
||||
|
||||
> 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.
|
||||
|
||||
<br>
|
||||
|
||||
### About LibreX
|
||||
|
||||
LibreX gives you results from Google, Qwant, Ahmia and popular torrent sites without spying on you.
|
||||
<br>LibreX doesn't save any type of data about the user, there are no logs, no caches.
|
||||
<br>
|
||||
<br>
|
||||
If you would like to learn more about LibreX check out the [Wiki](https://github.com/hnhx/librex/wiki).
|
||||
<br>
|
||||
| [librex.revvy.de](https://librex.revvy.de/) | [✅](http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/) | [✅](http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/) | 🇨🇦 CA |
|
||||
<br>
|
||||
|
||||
|
||||
### LibreX compared to other metasearch engines
|
||||
### About LibreY
|
||||
|
||||
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), no caches.
|
||||
|
||||
### 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 | ❌ | ❌ | ❌ |
|
||||
|
|
|
@ -53,13 +53,6 @@
|
|||
"original_name" => "GitHub",
|
||||
"original_url" => "github.com"
|
||||
),
|
||||
"librarian" => array(
|
||||
"instance_url" => "",
|
||||
"project_url" => "https://codeberg.org/librarian/librarian#clearnet",
|
||||
"original_name" => "Odysee",
|
||||
"original_url" => "odysee.com"
|
||||
),
|
||||
|
||||
"nitter" => array(
|
||||
"instance_url" => "",
|
||||
"project_url" => "https://github.com/zedeus/nitter/wiki/Instances",
|
||||
|
@ -122,6 +115,16 @@
|
|||
"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:
|
||||
|
@ -141,7 +144,7 @@
|
|||
// 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/109.0.0.0 Safari/537.36",
|
||||
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", // For a normal Windows 10 PC running Firefox x64
|
||||
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_WHATEVER,
|
||||
CURLOPT_CUSTOMREQUEST => "GET",
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
version: "2.1"
|
||||
services:
|
||||
librex:
|
||||
image: librex/librex:latest
|
||||
container_name: librex
|
||||
librey:
|
||||
image: ahwxorg/librey:latest
|
||||
container_name: librey
|
||||
network_mode: bridge
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
@ -14,6 +14,8 @@ services:
|
|||
- CONFIG_GOOGLE_DOMAIN=com
|
||||
- CONFIG_GOOGLE_LANGUAGE_SITE=en
|
||||
- CONFIG_GOOGLE_LANGUAGE_RESULTS=en
|
||||
- CONFIG_TEXT_SEARCH_ENGINE=google
|
||||
- CONFIG_INSTANCE_FALLBACK=true
|
||||
- CONFIG_WIKIPEDIA_LANGUAGE=en
|
||||
volumes:
|
||||
- ./nginx_logs:/var/log/nginx
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
- [Search Config](#search-config)
|
||||
- [Wikipedia](#wikipedia)
|
||||
- [Applications](#applications)
|
||||
- [Engines](#engines)
|
||||
- [Curl](#curl)
|
||||
- [Docker version issues](#docker-version-issues)
|
||||
- [Building a docker image](#building-a-docker-image)
|
||||
|
@ -17,21 +18,21 @@
|
|||
|
||||
### Running a docker container
|
||||
|
||||
Dockerized Librex 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.
|
||||
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
|
||||
|
||||
To run librex in a docker container, you can simply use the command:
|
||||
To run librey in a docker container, you can simply use the command:
|
||||
|
||||
```sh
|
||||
docker run -d \
|
||||
--name librex \
|
||||
--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 \
|
||||
librex/librex:latest
|
||||
librey/librey:latest
|
||||
```
|
||||
|
||||
<br>
|
||||
|
@ -41,9 +42,9 @@ docker run -d \
|
|||
```yml
|
||||
version: "2.1"
|
||||
services:
|
||||
librex:
|
||||
image: librex/librex:latest
|
||||
container_name: librex
|
||||
librey:
|
||||
image: librey/librey:latest
|
||||
container_name: librey
|
||||
network_mode: bridge
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
@ -73,11 +74,11 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
|
||||
| Variables | Default | Examples | Description |
|
||||
|:----------|:-------------|:---------|:------|
|
||||
| OPEN_SEARCH_TITLE | "LibreX" | string | [OpenSearch XML](https://developer.mozilla.org/en-US/docs/Web/OpenSearch) |
|
||||
| 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 | "Librex Search" | string | [OpenSearch XML](https://developer.mozilla.org/en-US/docs/Web/OpenSearch) |
|
||||
| OPEN_SEARCH_HOST | "http://localhost:8080" | string | Host used to identify Librex on the network |
|
||||
| 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>
|
||||
|
||||
|
@ -87,6 +88,8 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
|:----------|:-------------|:---------|:------|
|
||||
| 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_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 |
|
||||
|
@ -102,6 +105,13 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
|
||||
<br>
|
||||
|
||||
### Engines
|
||||
| Variables | Default | Examples | Description |
|
||||
|:----------|:-------------|:---------|:------|
|
||||
| CONFIG_TEXT_SEARCH_ENGINE | "google" | "google", "duckduckgo" | Change your text search engine. |
|
||||
|
||||
<br>
|
||||
|
||||
### Applications
|
||||
|
||||
| Variables | Default | Examples | Description |
|
||||
|
@ -109,7 +119,6 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
| APP_INVIDIOUS | "" | 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_LIBRARIAN | "" | 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. |
|
||||
|
@ -130,6 +139,7 @@ This docker image was developed with high configurability in mind, so here is th
|
|||
|:----------|:-------------|:---------|:------|
|
||||
| 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 |
|
||||
|
@ -155,30 +165,30 @@ Docker > 20.10: `docker buildx build`
|
|||
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/hnhx/librex.git -t librex:latest
|
||||
docker build https://github.com/Ahwxorg/librey.git -t librey:latest
|
||||
```
|
||||
|
||||
```sh
|
||||
docker run -d --name librex \
|
||||
docker run -d --name librey \
|
||||
-e CONFIG_GOOGLE_DOMAIN="com" \
|
||||
-e CONFIG_GOOGLE_LANGUAGE="en" \
|
||||
-p 8080:8080 \
|
||||
librex:latest
|
||||
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/hnhx/librex.git
|
||||
cd librex/
|
||||
docker build -t librex:latest .
|
||||
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 Librex 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.
|
||||
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:
|
||||
|
||||
|
@ -186,7 +196,7 @@ In this case, you must run the `build` process specifying the desired architectu
|
|||
docker buildx build \
|
||||
--no-cache \
|
||||
--platform linux/arm/v7 \
|
||||
--tag librex/librex:latest .
|
||||
--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.
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
# 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/librex.conf"
|
||||
export CONFIG_NGINX_TEMPLATE="/etc/nginx/http.d/librey.conf"
|
||||
|
||||
# Configure 'opensearch.xml' with Librex configuration metadata, such as the encoding and the host that stores the site
|
||||
# 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:-"LibreX"}
|
||||
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:-"LibreX Search"}
|
||||
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
|
||||
|
@ -22,21 +22,22 @@ export OPEN_SEARCH_HOST=${OPEN_SEARCH_HOST:-"127.0.0.1"}
|
|||
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_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 libreX search page
|
||||
# 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}}
|
||||
|
||||
# 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 librex
|
||||
# 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_LIBRARIAN=${APP_LIBRARIAN:-""}
|
||||
export APP_GOTHUB=${APP_GOTHUB:-""}
|
||||
export APP_NITTER=${APP_NITTER:-""}
|
||||
export APP_LIBREREDDIT=${APP_LIBREREDDIT:-""}
|
||||
|
@ -49,10 +50,13 @@ 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) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"}"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"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}",
|
||||
"invidious_instance_for_video_results" => "${CONFIG_INVIDIOUS_INSTANCE}",
|
||||
|
@ -10,6 +11,7 @@
|
|||
"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},
|
||||
|
||||
"frontends" => array(
|
||||
"invidious" => array(
|
||||
|
@ -36,13 +38,6 @@
|
|||
"original_name" => "GitHub",
|
||||
"original_url" => "github.com"
|
||||
),
|
||||
"librarian" => array(
|
||||
"instance_url" => "${APP_LIBRARIAN}",
|
||||
"project_url" => "https://codeberg.org/librarian/librarian#clearnet",
|
||||
"original_name" => "Odysee",
|
||||
"original_url" => "odysee.com"
|
||||
),
|
||||
|
||||
"nitter" => array(
|
||||
"instance_url" => "${APP_NITTER}",
|
||||
"project_url" => "https://github.com/zedeus/nitter/wiki/Instances",
|
||||
|
@ -106,9 +101,13 @@
|
|||
)
|
||||
),
|
||||
|
||||
"preferred_engines" => array(
|
||||
"text" => "${CONFIG_TEXT_SEARCH_ENGINE}"
|
||||
),
|
||||
|
||||
"curl_settings" => array(
|
||||
CURLOPT_PROXY => "${CURLOPT_PROXY}",
|
||||
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
|
||||
CURLOPT_PROXYTYPE => "${CURLOPT_PROXYTYPE}",
|
||||
CURLOPT_RETURNTRANSFER => ${CURLOPT_RETURNTRANSFER},
|
||||
CURLOPT_ENCODING => "${CURLOPT_ENCODING}",
|
||||
CURLOPT_USERAGENT => "${CURLOPT_USERAGENT}",
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# 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 Librex configuration metadata, such as the encoding and the host that stores the site
|
||||
# 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="LibreX"
|
||||
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="LibreX search"
|
||||
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
|
||||
|
@ -14,17 +14,18 @@ ENV OPEN_SEARCH_HOST="http://127.0.0.1:${NGINX_PORT}"
|
|||
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 librex
|
||||
# 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_LIBRARIAN=""
|
||||
ENV APP_GOTHUB=""
|
||||
ENV APP_NITTER=""
|
||||
ENV APP_LIBREREDDIT=""
|
||||
|
@ -37,11 +38,14 @@ 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"
|
||||
|
|
|
@ -11,11 +11,11 @@ export OPEN_SEARCH_HOST_FOR_NGINX="$(echo "${OPEN_SEARCH_HOST}" | cut -d "/" -f
|
|||
# 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/librex.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/librex.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
|
||||
|
|
|
@ -4,17 +4,19 @@
|
|||
// 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>
|
||||
<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>
|
||||
|
||||
<?php require "misc/footer.php"; ?>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
{
|
||||
|
||||
$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;
|
||||
$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;
|
||||
|
|
197
engines/duckduckgo/text.php
Normal file
197
engines/duckduckgo/text.php
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
function get_text_results($query, $page)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$mh = curl_multi_init();
|
||||
$query_encoded = urlencode($query);
|
||||
$results = array();
|
||||
|
||||
// $domain = $config->google_domain;
|
||||
$domain = 'com';
|
||||
$site_language = isset($_COOKIE["google_language_site"]) ? trim(htmlspecialchars($_COOKIE["google_language_site"])) : $config->google_language_site;
|
||||
$results_language = isset($_COOKIE["google_language_results"]) ? trim(htmlspecialchars($_COOKIE["google_language_results"])) : $config->google_language_results;
|
||||
$number_of_results = isset($_COOKIE["google_number_of_results"]) ? trim(htmlspecialchars($_COOKIE["google_number_of_results"])) : $config->google_number_of_results;
|
||||
|
||||
$url = "https://html.duckduckgo.$domain/html/?q=$query_encoded&kd=-1&s=" . 3 * $page;
|
||||
if (3 > strlen($site_language) && 0 < strlen($site_language))
|
||||
$url .= "&hl=$site_language";
|
||||
|
||||
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";
|
||||
|
||||
$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:
|
||||
$wikipedia_language = isset($_COOKIE["wikipedia_language"]) ? trim(htmlspecialchars($_COOKIE["wikipedia_language"])) : $config->wikipedia_language;
|
||||
if (in_array($wikipedia_language, json_decode(file_get_contents("static/misc/wikipedia_langs.json"), true)))
|
||||
$url = "https://$wikipedia_language.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("/html/body/div[1]/div[". count($xpath->query('/html/body/div[1]/div')) ."]/div/div/div/div") as $result)
|
||||
{
|
||||
$url = $xpath->evaluate(".//h2[@class='result__title']//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(".//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" => 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>";
|
||||
}
|
||||
?>
|
|
@ -12,7 +12,7 @@
|
|||
$results_language = isset($_COOKIE["google_language_results"]) ? trim(htmlspecialchars($_COOKIE["google_language_results"])) : $config->google_language_results;
|
||||
$number_of_results = isset($_COOKIE["google_number_of_results"]) ? trim(htmlspecialchars($_COOKIE["google_number_of_results"])) : $config->google_number_of_results;
|
||||
|
||||
$url = "https://www.google.$domain/search?q=$query_encoded&start=$page";
|
||||
$url = "https://www.google.$domain/search?q=$query_encoded&nfpr=1&start=$page";
|
||||
|
||||
if (3 > strlen($site_language) && 0 < strlen($site_language))
|
||||
$url .= "&hl=$site_language";
|
||||
|
@ -54,7 +54,8 @@
|
|||
break;
|
||||
case 7:
|
||||
$wikipedia_language = isset($_COOKIE["wikipedia_language"]) ? trim(htmlspecialchars($_COOKIE["wikipedia_language"])) : $config->wikipedia_language;
|
||||
$url = "https://$wikipedia_language.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
|
||||
if (in_array($wikipedia_language, json_decode(file_get_contents("static/misc/wikipedia_langs.json"), true)))
|
||||
$url = "https://$wikipedia_language.wikipedia.org/w/api.php?format=json&action=query&prop=extracts%7Cpageimages&exintro&explaintext&redirects=1&pithumbsize=500&titles=$query_encoded";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -78,9 +79,9 @@
|
|||
}
|
||||
|
||||
|
||||
$special_result = array();
|
||||
if ($special_search != 0)
|
||||
{
|
||||
$special_result = null;
|
||||
|
||||
switch ($special_search)
|
||||
{
|
||||
|
@ -114,13 +115,20 @@
|
|||
$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));
|
||||
|
||||
$didyoumean = $xpath->query(".//a[@class='gL9Hy']")[0];
|
||||
|
||||
if (!is_null($didyoumean))
|
||||
$special_result["did_you_mean"] = $didyoumean->textContent;
|
||||
|
||||
if (!empty($special_result))
|
||||
array_push($results, $special_result);
|
||||
|
||||
|
||||
|
||||
foreach($xpath->query("//div[@id='search']//div[contains(@class, 'g')]") as $result)
|
||||
{
|
||||
$url = $xpath->evaluate(".//div[@class='yuRUbf']//a/@href", $result)[0];
|
||||
|
@ -159,8 +167,19 @@
|
|||
|
||||
function print_text_results($results)
|
||||
{
|
||||
|
||||
$special = $results[0];
|
||||
if (array_key_exists("special_response", $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 ";
|
||||
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"];
|
||||
|
@ -175,14 +194,15 @@
|
|||
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)
|
||||
{
|
||||
if (!array_key_exists("title", $result))
|
||||
continue;
|
||||
|
||||
$title = $result["title"];
|
||||
$url = $result["url"];
|
||||
$base_url = $result["base_url"];
|
||||
|
|
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
Before Width: | Height: | Size: 750 B After Width: | Height: | Size: 26 KiB |
|
@ -1,17 +1,17 @@
|
|||
<?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>
|
||||
<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>
|
||||
|
||||
|
|
137
instances.json
137
instances.json
|
@ -1,136 +1,179 @@
|
|||
{
|
||||
"instances": [
|
||||
{
|
||||
"clearnet": "https://librex.zzls.xyz/",
|
||||
"tor": "http://librex.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion/",
|
||||
"i2p": "http://zzlsaymhcfla7vibo3a223bybeecu3bd5z6rmw2u4y76maqeu76q.b32.i2p/",
|
||||
"country": "CL"
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.me/",
|
||||
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
|
||||
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/",
|
||||
"country": "CA"
|
||||
},
|
||||
{
|
||||
"clearnet": "https://s.dyox.in/",
|
||||
"tor": "http://ddhigxwjz7elcl2erm7qzzukda4qmovoy4cepcueahggpwrpu24mi6qd.onion/",
|
||||
"i2p": "http://s.dyoxin.i2p/",
|
||||
"country": "IS"
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.vern.cc/",
|
||||
"tor": "http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/",
|
||||
"i2p": "http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/",
|
||||
"country": "US"
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.ahwx.org/",
|
||||
"tor": "http://cosrpybbddzdfjquer3zfmb2h5avtacnctnbu4gucwocdb42s63gcqqd.onion/",
|
||||
"clearnet": "https://search.ahwx.org",
|
||||
"tor": "http://hyy7rcvknwb22v4nnoar635wntiwr4uwzhiuyimemyl4fz6k7tahj5id.onion",
|
||||
"i2p": null,
|
||||
"country": "NL"
|
||||
"country": "FR",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.spaceint.fr/",
|
||||
"tor": "http://6d4nqt2rndvmhogpwrbqfvj2ur6e6nm2r6dzi7ny4wj6ai3j5hnvbhyd.onion/",
|
||||
"i2p": null,
|
||||
"country": "FR"
|
||||
"clearnet": "https://librex.me",
|
||||
"tor": "librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion",
|
||||
"i2p": "revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p",
|
||||
"country": "CA",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.revvy.de",
|
||||
"tor": "librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion",
|
||||
"i2p": "revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p",
|
||||
"country": "CA",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.davidovski.xyz/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "UK"
|
||||
"country": "GB",
|
||||
"librey": true
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.zzls.xyz/",
|
||||
"tor": "http://librex.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion/",
|
||||
"i2p": "http://zzlsaymhcfla7vibo3a223bybeecu3bd5z6rmw2u4y76maqeu76q.b32.i2p/",
|
||||
"country": "CL",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.me/",
|
||||
"tor": "http://librex.revvybrr6pvbx4n3j4475h4ghw4elqr4t5xo2vtd3gfpu2nrsnhh57id.onion/",
|
||||
"i2p": "http://revekebotog64xrrammtsmjwtwlg3vqyzwdurzt2pu6botg4bejq.b32.i2p/",
|
||||
"country": "CA",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://s.dyox.in/",
|
||||
"tor": "http://ddhigxwjz7elcl2erm7qzzukda4qmovoy4cepcueahggpwrpu24mi6qd.onion/",
|
||||
"i2p": "http://s.dyoxin.i2p/",
|
||||
"country": "IS",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.vern.cc/",
|
||||
"tor": "http://lx.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/",
|
||||
"i2p": "http://vernziqfqvweijfaacmwazohgpdo2bt2ib2jlupt2pwwu27bhgxq.b32.i2p/",
|
||||
"country": "US",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.ahwx.org/",
|
||||
"tor": "http://cosrpybbddzdfjquer3zfmb2h5avtacnctnbu4gucwocdb42s63gcqqd.onion/",
|
||||
"i2p": null,
|
||||
"country": "NL",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.spaceint.fr/",
|
||||
"tor": "http://6d4nqt2rndvmhogpwrbqfvj2ur6e6nm2r6dzi7ny4wj6ai3j5hnvbhyd.onion/",
|
||||
"i2p": null,
|
||||
"country": "FR",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.madreyk.xyz/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE"
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.pabloferreiro.es/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE"
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.pufe.org/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "NZ"
|
||||
"country": "NZ",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.ratakor.com/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "FR"
|
||||
"country": "FR",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.tildevarsh.in/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "IN"
|
||||
"country": "IN",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.myroware.eu/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE"
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.bloatcat.tk/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "IS"
|
||||
"country": "IS",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.retro-hax.net/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE"
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.funami.tech/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "KR"
|
||||
"country": "KR",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.zeroish.xyz/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "US"
|
||||
"country": "US",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.baczek.me/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "PL"
|
||||
"country": "PL",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.yogeshlamichhane.com.np/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "US"
|
||||
"country": "US",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://lx.benike.monster/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "DE"
|
||||
"country": "DE",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://librex.nohost.network/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "MX"
|
||||
"country": "MX",
|
||||
"librey": false
|
||||
},
|
||||
{
|
||||
"clearnet": "https://search.decentrala.org/",
|
||||
"tor": null,
|
||||
"i2p": null,
|
||||
"country": "US"
|
||||
"country": "US",
|
||||
"librey": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
61
instances.php
Normal file
61
instances.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?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"]) . $instnace["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>
|
||||
|
||||
<center>
|
||||
<h2>Libre<span class="Y">Y</span> instances</h2>
|
||||
<?php
|
||||
list_instances($librey_instances);
|
||||
?>
|
||||
|
||||
<p>The following instnaces are running the older <a href="https://github.com/hnhx/librex">LibreX</a>:</p>
|
||||
<?php
|
||||
list_instances($librex_instances);
|
||||
?>
|
||||
</center>
|
||||
|
||||
|
||||
<?php require "misc/footer.php"; ?>
|
|
@ -1,6 +1,7 @@
|
|||
<div class="footer-container">
|
||||
<a href="./">LibreX</a>
|
||||
<a href="https://github.com/hnhx/librex/" target="_blank">Source & Instances</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="https://zzls.xyz/donate">Donate to the hoster (the one hosting this)</a>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<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"]))
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
$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 = str_replace("{{{s}}}", str_replace('%26quot%3B','%22', urlencode($bang_query)), $bang_url);
|
||||
$request_url = check_for_privacy_frontend($request_url);
|
||||
|
||||
header("Location: " . $request_url);
|
||||
|
@ -237,4 +237,20 @@
|
|||
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);
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>LibreX</ShortName>
|
||||
<ShortName>LibreY</ShortName>
|
||||
<Description>Framework and javascript free privacy respecting meta search engine</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<LongName>LibreX search</LongName>
|
||||
<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"
|
||||
|
|
12
search.php
12
search.php
|
@ -9,11 +9,11 @@
|
|||
<?php
|
||||
$query = htmlspecialchars(trim($_REQUEST["q"]));
|
||||
echo $query;
|
||||
?> - LibreX</title>
|
||||
?> - 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);
|
||||
|
@ -48,7 +48,7 @@
|
|||
continue;
|
||||
}
|
||||
|
||||
echo "<a " . (($category_index == $type) ? "class=\"active\" " : "") . "href=\"/search.php?q=" . $query . "&p=0&t=" . $category_index . "\"><img src=\"static/images/" . $category . "_result.png\" alt=\"" . $category . " result\" />" . ucfirst($category) . "</a>";
|
||||
echo "<a " . (($category_index == $type) ? "class=\"active\" " : "") . "href=\"./search.php?q=" . $query . "&p=0&t=" . $category_index . "\"><img src=\"static/images/" . $category . "_result.png\" alt=\"" . $category . " result\" />" . ucfirst($category) . "</a>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
@ -58,16 +58,18 @@
|
|||
<?php
|
||||
|
||||
$page = isset($_REQUEST["p"]) ? (int) $_REQUEST["p"] : 0;
|
||||
|
||||
$start_time = microtime(true);
|
||||
switch ($type)
|
||||
{
|
||||
case 0:
|
||||
$engine=$config->preferred_engines['text'];
|
||||
if (is_null($engine))
|
||||
$engine = "google";
|
||||
$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";
|
||||
require "engines/$engine/text.php";
|
||||
$results = get_text_results($query, $page);
|
||||
print_elapsed_time($start_time);
|
||||
print_text_results($results);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
require "misc/header.php";
|
||||
?>
|
||||
|
||||
<title>LibreX - Settings</title>
|
||||
<title>LibreY - Settings</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="misc-container">
|
||||
|
@ -99,7 +99,7 @@
|
|||
<input type="checkbox" name="disable_frontends" <?php echo isset($_COOKIE["disable_frontends"]) ? "checked" : ""; ?> >
|
||||
</div>
|
||||
|
||||
<h2>Google settings</h2>
|
||||
<h2>Search settings</h2>
|
||||
<div class="settings-textbox-container">
|
||||
<div>
|
||||
<span>Site language</span>
|
||||
|
|
|
@ -30,6 +30,7 @@ a,
|
|||
|
||||
.text-result-wrapper a:visited h2,
|
||||
.special-result-container a,
|
||||
.did-you-mean a,
|
||||
.sub-search-button-wrapper a,
|
||||
.sub-search-button-wrapper a:visited{
|
||||
color: #bd93f9;
|
||||
|
@ -187,7 +188,8 @@ a:hover,
|
|||
|
||||
.text-result-container,
|
||||
#time,
|
||||
.next-page-button-wrapper {
|
||||
.next-page-button-wrapper,
|
||||
.did-you-mean {
|
||||
margin-left: 170px;
|
||||
}
|
||||
|
||||
|
@ -325,7 +327,7 @@ a[title] {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.X {
|
||||
.Y {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 6.4 KiB |
File diff suppressed because one or more lines are too long
1
static/misc/wikipedia_langs.json
Normal file
1
static/misc/wikipedia_langs.json
Normal file
|
@ -0,0 +1 @@
|
|||
["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