Compare commits

..

1 Commits

Author SHA1 Message Date
Alicia Sykes
bc45b91b51 Refactored Dockerfile 2023-08-29 21:47:39 +01:00
342 changed files with 17638 additions and 12928 deletions

31
.env
View File

@@ -2,26 +2,11 @@
# Be sure to uncomment any line you populate
# Everything is optional, but some features won't work without external API access
# API Keys for external services (backend)
GOOGLE_CLOUD_API_KEY=''
TORRENT_IP_API_KEY=''
SECURITY_TRAILS_API_KEY=''
BUILT_WITH_API_KEY=''
URL_SCAN_API_KEY=''
TRANCO_USERNAME=''
TRANCO_API_KEY=''
CLOUDMERSIVE_API_KEY=''
# API Keys for external services (frontend)
REACT_APP_SHODAN_API_KEY=''
REACT_APP_WHO_API_KEY=''
# Configuration settings
# CHROME_PATH='/usr/bin/chromium' # The path the the Chromium executable
# PORT='3000' # Port to serve the API, when running server.js
# DISABLE_GUI='false' # Disable the GUI, and only serve the API
# API_TIMEOUT_LIMIT='10000' # The timeout limit for API requests, in milliseconds
# API_CORS_ORIGIN='*' # Enable CORS, by setting your allowed hostname(s) here
# API_ENABLE_RATE_LIMIT='true' # Enable rate limiting for the API
# REACT_APP_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote)
# ENABLE_ANALYTICS='false' # Enable Plausible hit counter for the frontend
# GOOGLE_CLOUD_API_KEY=''
# SHODAN_API_KEY=''
# REACT_APP_SHODAN_API_KEY=''
# WHO_API_KEY=''
# REACT_APP_WHO_API_KEY=''
# SECURITY_TRAILS_API_KEY=''
# BUILT_WITH_API_KEY=''
# CI=false

725
.github/README.md vendored
View File

@@ -9,22 +9,6 @@
</p>
---
<p align="center">
<sup>Kindly supported by:</sup><br>
<a href="https://terminaltrove.com/?utm_campaign=github&utm_medium=referral&utm_content=web-check&utm_source=wcgh">
<img src="https://i.ibb.co/8jrrcZ0/IMG-7210.jpg" width="300" alt="Terminal Trove">
<br>
<strong>The $HOME of all things in the terminal.</strong>
</a>
<br>
<a href="https://terminaltrove.com/newsletter?utm_campaign=github&utm_medium=referral&utm_content=web-check&utm_source=wcgh">
<sub>Find your next CLI / TUI tool and more at Terminal Trove,</sub>
<br>
<sup>Get updates on new tools on our newsletter.</sup>
</a>
</p>
---
#### Contents
@@ -35,13 +19,11 @@
- [Mirror](#mirror)
- [Features](#features)
- **[Usage](#usage)**
- [Deployment](#deployment)
- [Option#1: Netlify](#deploying---option-1-netlify)
- [Option#2: Vercel](#deploying---option-2-vercel)
- [Option#3: Docker](#deploying---option-3-docker)
- [Option#4: Source](#deploying---option-4-from-source)
- [Configuration Options](#configuring)
- [Developer Setup](#developing)
- [Deploying, Option#1: Netlify](#deploying---option-1-netlify)
- [Deploying, Option#2: Docker](#deploying---option-2-docker)
- [Deploying, Option#3: Source](#deploying---option-3-from-source)
- [Configuration Options](#configuring)
- **[Community](#community)**
- [Contributing](#contributing)
- [Bugs](#reporting-bugs)
@@ -74,27 +56,18 @@ A hosted version can be accessed at: **[web-check.as93.net](https://web-check.as
### Mirror
The source for this repo is mirrored to CodeBerg, available at: **[codeberg.org/alicia/web-check](https://codeberg.org/alicia/web-check)**
### Status
Build & Deploys: [![Netlify Status](https://api.netlify.com/api/v1/badges/c43453c1-5333-4df7-889b-c1d2b52183c0/deploy-status)](https://app.netlify.com/sites/web-check/deploys)
[![Vercel Status](https://therealsujitk-vercel-badge.vercel.app/?app=web-check-ten)](https://vercel.com/as93/web-check/)
[![🐳 Build + Publish Docker Image](https://github.com/Lissy93/web-check/actions/workflows/docker.yml/badge.svg)](https://github.com/Lissy93/web-check/actions/workflows/docker.yml)
[![🚀 Deploy to AWS](https://github.com/Lissy93/web-check/actions/workflows/deploy-aws.yml/badge.svg)](https://github.com/Lissy93/web-check/actions/workflows/deploy-aws.yml)
<br />
Repo Management & Miscellaneous: [![🪞 Mirror to Codeberg](https://github.com/Lissy93/web-check/actions/workflows/mirror.yml/badge.svg)](https://github.com/Lissy93/web-check/actions/workflows/mirror.yml)
[![💓 Inserts Contributors & Sponsors](https://github.com/Lissy93/web-check/actions/workflows/credits.yml/badge.svg)](https://github.com/Lissy93/web-check/actions/workflows/credits.yml)
### Motivation
Often when you're looking into a website, there's several things you always initially check.
None of this is hard to find with a series of basic curl commands and NPMAP plus a combination of online tools. But it's just so much easier to have everything done all at once, presented clearly and visible in one place :)
### Features
<details open>
<summary><b>Click to expand / collapse section</b></summary>
<details>
<summary><h4>Expand to see all features</h4></summary>
<sup>**Note** _this list needs updating, many more jobs have been added since..._</sup>
The following section outlines the core features, and briefly explains why this data might be useful for you to know, as well as linking to further resources for learning more.
<details>
<summary><b>IP Info</b></summary>
@@ -757,104 +730,14 @@ This may be useful to see what a given website looks like, free of the constrain
</details>
Read more here: **[web-check.xyz/about](https://web-check.xyz/about)**
Read more here: **[web-check.as93.net/about](https://web-check.as93.net/about)**
_Note that not all checks will work for all sites. Sometimes it's not possible to determine some information, and the demo instance has some limitations imposed by Netlify for the lambda functions._
---
## Usage
### Deployment
### Deploying - Option #1: Netlify
Click the button below, to deploy to Netlify 👇
[![Deploy to Netlify](https://img.shields.io/badge/Deploy-Netlify-%2330c8c9?style=for-the-badge&logo=netlify&labelColor=1e0e41 'Deploy Web-Check to Netlify, via 1-Click Script')](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/web-check)
### Deploying - Option #2: Vercel
Click the button below, to deploy to Vercel 👇
[![Deploy with Vercel](https://img.shields.io/badge/Deploy-Vercel-%23ffffff?style=for-the-badge&logo=vercel&labelColor=1e0e41)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flissy93%2Fweb-check&project-name=web-check&repository-name=web-check-fork&demo-title=Web-Check%20Demo&demo-description=Check%20out%20web-check.xyz%20to%20see%20a%20live%20demo%20of%20this%20application%20running.&demo-url=https%3A%2F%2Fweb-check.xyz&demo-image=https%3A%2F%2Fraw.githubusercontent.com%2FLissy93%2Fweb-check%2Fmaster%2F.github%2Fscreenshots%2Fweb-check-screenshot10.png)
### Deploying - Option #3: Docker
Run `docker run -p 3000:3000 lissy93/web-check`, then open [`localhost:3000`](http://localhost:3000)
<details>
<summary>Docker Options</summary>
You can get the Docker image from:
- DockerHub: [`lissy93/web-check`](https://hub.docker.com/r/lissy93/web-check)
- GHCR: [`ghcr.io/lissy93/web-check`](https://github.com/Lissy93/web-check/pkgs/container/web-check)
- Or build the image yourself by cloning the repo and running `docker build -t web-check .`
</details>
### Deploying - Option #4: From Source
Install the prerequisites listed in the [Developing](#developing) section, then run:
```bash
git clone https://github.com/Lissy93/web-check.git # Download the code from GitHub
cd web-check # Navigate into the project dir
yarn install # Install the NPM dependencies
yarn build # Build the app for production
yarn serve # Start the app (API and GUI)
```
---
### Configuring
By default, no configuration is needed.
But there are some optional environmental variables that you can set to give you access to some additional checks, or to increase rate-limits for some checks that use external APIs.
**API Keys & Credentials**:
Key | Value
---|---
`GOOGLE_CLOUD_API_KEY` | A Google API key ([get here](https://cloud.google.com/api-gateway/docs/authenticate-api-keys)). This can be used to return quality metrics for a site
`REACT_APP_SHODAN_API_KEY` | A Shodan API key ([get here](https://account.shodan.io/)). This will show associated host names for a given domain
`REACT_APP_WHO_API_KEY` | A WhoAPI key ([get here](https://whoapi.com/)). This will show more comprehensive WhoIs records than the default job
<details>
<summary><small>Full / Upcoming Vals</small></summary>
- `GOOGLE_CLOUD_API_KEY` - A Google API key ([get here](https://cloud.google.com/api-gateway/docs/authenticate-api-keys)). This can be used to return quality metrics for a site
- `REACT_APP_SHODAN_API_KEY` - A Shodan API key ([get here](https://account.shodan.io/)). This will show associated host names for a given domain
- `REACT_APP_WHO_API_KEY` - A WhoAPI key ([get here](https://whoapi.com/)). This will show more comprehensive WhoIs records than the default job
- `SECURITY_TRAILS_API_KEY` - A Security Trails API key ([get here](https://securitytrails.com/corp/api)). This will show org info associated with the IP
- `CLOUDMERSIVE_API_KEY` - API key for Cloudmersive ([get here](https://account.cloudmersive.com/)). This will show known threats associated with the IP
- `TRANCO_USERNAME` - A Tranco email ([get here](https://tranco-list.eu/)). This will show the rank of a site, based on traffic
- `TRANCO_API_KEY` - A Tranco API key ([get here](https://tranco-list.eu/)). This will show the rank of a site, based on traffic
- `URL_SCAN_API_KEY` - A URLScan API key ([get here](https://urlscan.io/)). This will fetch miscalanious info about a site
- `BUILT_WITH_API_KEY` - A BuiltWith API key ([get here](https://api.builtwith.com/)). This will show the main features of a site
- `TORRENT_IP_API_KEY` - A torrent API key ([get here](https://iknowwhatyoudownload.com/en/api/)). This will show torrents downloaded by an IP
</details>
**Configuration Settings**:
Key | Value
---|---
`PORT` | Port to serve the API, when running server.js (e.g. `3000`)
`API_ENABLE_RATE_LIMIT` | Enable rate-limiting for the /api endpoints (e.g. `true`)
`API_TIMEOUT_LIMIT` | The timeout limit for API requests, in milliseconds (e.g. `10000`)
`API_CORS_ORIGIN` | Enable CORS, by setting your allowed hostname(s) here (e.g. `example.com`)
`CHROME_PATH` | The path the Chromium executable (e.g. `/usr/bin/chromium`)
`DISABLE_GUI` | Disable the GUI, and only serve the API (e.g. `false`)
`REACT_APP_API_ENDPOINT` | The endpoint for the API, either local or remote (e.g. `/api`)
All values are optional.
You can add these as environmental variables. Either put them directly into an `.env` file in the projects root, or via the Netlify / Vercel UI, or by passing to the Docker container with the --env flag, or using your own environmental variable management system
Note that keys that are prefixed with `REACT_APP_` are used client-side, and as such they must be scoped correctly with minimum privileges, since may be made visible when intercepting browser <-> server network requests
---
### Developing
1. Clone the repo, `git clone git@github.com:Lissy93/web-check.git`
@@ -865,6 +748,64 @@ Note that keys that are prefixed with `REACT_APP_` are used client-side, and as
You'll need [Node.js](https://nodejs.org/en) (V 18.16.1 or later) installed, plus [yarn](https://yarnpkg.com/getting-started/install) as well as [git](https://git-scm.com/).
Some checks also require `chromium`, `traceroute` and `dns` to be installed within your environment. These jobs will just be skipped if those packages aren't present.
### Deploying - Option #1: Netlify
Click the button below, to deploy to Netlify 👇
[![Deploy to Netlify](https://img.shields.io/badge/Deploy-Netlify-%2330c8c9?style=for-the-badge&logo=netlify&labelColor=1e0e41 'Deploy Web-Check to Netlify, via 1-Click Script')](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/web-check)
### Deploying - Option #2: Docker
Run `docker run -p 8888:3000 lissy93/web-check`, then open `http://localhost:3000`
You can get the Docker image from:
- DockerHub: [`lissy93/web-check`](https://hub.docker.com/r/lissy93/web-check)
- GHCR: [`ghcr.io/lissy93/web-check`](https://github.com/Lissy93/web-check/pkgs/container/web-check)
- Or build the image yourself by cloning the repo and running `docker build -t web-check .`
### Deploying - Option #3: From Source
Follow the instructions in the [Developing](#developing) section above, then run `yarn build` && `yarn serve` to build and serve the application.
The following commands will work:
```bash
git clone https://github.com/Lissy93/web-check.git # Grab the code
cd web-check # Move into the project directory
yarn install # Install dependencies
yarn build # Build the app for production
yarn serve # Start the app (API and GUI)
```
### Configuring
By default, no configuration is needed.
But there are some optional environmental variables that you can set to give you access to some additional checks, or to increase rate-limits for some checks that use external APIs.
Note that keys that are prefixed with `REACT_APP_` are used client-side, and as such they must be scoped correctly with minimum privileges.
**API Keys & Credentials**:
- `GOOGLE_CLOUD_API_KEY` - A Google API key ([get here](https://cloud.google.com/api-gateway/docs/authenticate-api-keys)). This can be used to return quality metrics for a site
- `REACT_APP_SHODAN_API_KEY` - A Shodan API key ([get here](https://account.shodan.io/)). This will show associated host names for a given domain
- `REACT_APP_WHO_API_KEY` - A WhoAPI key ([get here](https://whoapi.com/)). This will show more comprehensive WhoIs records than the default job
- `SECURITY_TRAILS_API_KEY` - A Security Trails API key ([get here](https://securitytrails.com/corp/api)). This will show org info associated with the IP
- `CLOUDMERSIVE_API_KEY` - API key for Cloudmersive ([get here](https://account.cloudmersive.com/)). This will show known threats associated with the IP
- `TRANCO_USERNAME` - A Tranco email ([get here](https://tranco-list.eu/)). This will show the rank of a site, based on traffic
- `TRANCO_API_KEY` - A Tranco API key ([get here](https://tranco-list.eu/)). This will show the rank of a site, based on traffic
- `URL_SCAN_API_KEY` - A URLScan API key ([get here](https://urlscan.io/)). This will fetch miscalanious info about a site
- `BUILT_WITH_API_KEY` - A BuiltWith API key ([get here](https://api.builtwith.com/)). This will show the main features of a site
- `TORRENT_IP_API_KEY` - A torrent API key ([get here](https://iknowwhatyoudownload.com/en/api/)). This will show torrents downloaded by an IP
**Configuration Settings**:
- `CHROME_PATH` (e.g. `/usr/bin/chromium`) - The path the the Chromium executable
- `PORT` (e.g. `3000`) - Port to serve the API, when running server.js
- `DISABLE_GUI` (e.g. `false`) - Disable the GUI, and only serve the API
- `API_TIMEOUT_LIMIT` (e.g. `10000`) - The timeout limit for API requests, in milliseconds
- `REACT_APP_API_ENDPOINT` (e.g. `/api`) - The endpoint for the API (can be local or remote)
The above can be added into an `.env` file in the projects root, or via the Netlify UI, or by passing directly to the Docker container with the --env flag.
All variables are optional.
---
@@ -890,9 +831,8 @@ For bugs, please outline the steps needed to reproduce, and include relevant inf
### Supporting
The app will remain 100% free and open source.
But due to the amount of traffic that the hosted instance gets, the lambda function usage is costing about $25/month.
Any help with covering the costs via GitHub Sponsorship would be much appreciated.
It's thanks to the support of the community that this project is able to be freely available for everyone :)
But due to the amount of traffic that the hosted instance gets, the lambda function usage is costing about $25/month. Any help with covering the costs via GitHub Sponsorship would be much appreciated. It's thanks to the support of the community that this project is able to be freely available for everyone :)
[![Sponsor Lissy93 on GitHub](https://img.shields.io/badge/Sponsor_on_GitHub-Lissy93-%23ff4dda?style=for-the-badge&logo=githubsponsors&logoColor=ff4dda)](https://github.com/sponsors/Lissy93)
@@ -903,200 +843,49 @@ Credit to the following users for contributing to Web-Check
<!-- readme: contributors -start -->
<table>
<tbody>
<tr>
<td align="center">
<a href="https://github.com/Lissy93">
<img src="https://avatars.githubusercontent.com/u/1862727?v=4" width="80;" alt="Lissy93"/>
<br />
<sub><b>Alicia Sykes</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/liss-bot">
<img src="https://avatars.githubusercontent.com/u/87835202?v=4" width="80;" alt="liss-bot"/>
<br />
<sub><b>Alicia Bot</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/n0a">
<img src="https://avatars.githubusercontent.com/u/14150948?v=4" width="80;" alt="n0a"/>
<br />
<sub><b>Denis Simonov</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/muni106">
<img src="https://avatars.githubusercontent.com/u/65845442?v=4" width="80;" alt="muni106"/>
<br />
<sub><b>Mounir Samite</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ChrisCarini">
<img src="https://avatars.githubusercontent.com/u/6374067?v=4" width="80;" alt="ChrisCarini"/>
<br />
<sub><b>Chris Carini</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bolens">
<img src="https://avatars.githubusercontent.com/u/1218380?v=4" width="80;" alt="bolens"/>
<br />
<sub><b>Michael Bolens</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/HeroGamers">
<img src="https://avatars.githubusercontent.com/u/15278940?v=4" width="80;" alt="HeroGamers"/>
<br />
<sub><b>Marcus Sand</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jinnabaalu">
<img src="https://avatars.githubusercontent.com/u/11784253?v=4" width="80;" alt="jinnabaalu"/>
<br />
<sub><b>Jinna Baalu</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/GreyXor">
<img src="https://avatars.githubusercontent.com/u/79602273?v=4" width="80;" alt="GreyXor"/>
<br />
<sub><b>GreyXor</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/brianteeman">
<img src="https://avatars.githubusercontent.com/u/1296369?v=4" width="80;" alt="brianteeman"/>
<br />
<sub><b>Brian Teeman</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vitalykarasik">
<img src="https://avatars.githubusercontent.com/u/7628795?v=4" width="80;" alt="vitalykarasik"/>
<br />
<sub><b>Vitaly Karasik</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Its-Just-Nans">
<img src="https://avatars.githubusercontent.com/u/56606507?v=4" width="80;" alt="Its-Just-Nans"/>
<br />
<sub><b>n4n5</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/robinson">
<img src="https://avatars.githubusercontent.com/u/237874?v=4" width="80;" alt="robinson"/>
<br />
<sub><b>Lth</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/abhishekMuge">
<img src="https://avatars.githubusercontent.com/u/49590582?v=4" width="80;" alt="abhishekMuge"/>
<br />
<sub><b>Abhishek Muge</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/UlisesGascon">
<img src="https://avatars.githubusercontent.com/u/5110813?v=4" width="80;" alt="UlisesGascon"/>
<br />
<sub><b>Ulises Gascón</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/PhiRequiem">
<img src="https://avatars.githubusercontent.com/u/1323576?v=4" width="80;" alt="PhiRequiem"/>
<br />
<sub><b>PhiRequiem</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/34bits">
<img src="https://avatars.githubusercontent.com/u/108784453?v=4" width="80;" alt="34bits"/>
<br />
<sub><b>Nikolaos G. Ntaiko</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Myzel394">
<img src="https://avatars.githubusercontent.com/u/50424412?v=4" width="80;" alt="Myzel394"/>
<br />
<sub><b>Myzel394</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/murrple-1">
<img src="https://avatars.githubusercontent.com/u/5559656?v=4" width="80;" alt="murrple-1"/>
<br />
<sub><b>Murray Christopherson</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/t3chn0m4g3">
<img src="https://avatars.githubusercontent.com/u/4318452?v=4" width="80;" alt="t3chn0m4g3"/>
<br />
<sub><b>Marco Ochse</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/treatmesubj">
<img src="https://avatars.githubusercontent.com/u/39680353?v=4" width="80;" alt="treatmesubj"/>
<br />
<sub><b>John Hupperts</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/eltociear">
<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="80;" alt="eltociear"/>
<br />
<sub><b>Ikko Eltociear Ashimine</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Gertje823">
<img src="https://avatars.githubusercontent.com/u/36937387?v=4" width="80;" alt="Gertje823"/>
<br />
<sub><b>Gertje823</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/epreston">
<img src="https://avatars.githubusercontent.com/u/347224?v=4" width="80;" alt="epreston"/>
<br />
<sub><b>Ed Preston</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/dimitri-kandassamy">
<img src="https://avatars.githubusercontent.com/u/21193806?v=4" width="80;" alt="dimitri-kandassamy"/>
<br />
<sub><b>Dimitri Kandassamy</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/0xflotus">
<img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="80;" alt="0xflotus"/>
<br />
<sub><b>0xflotus</b></sub>
</a>
</td>
</tr>
<tbody>
<tr>
<td align="center">
<a href="https://github.com/Lissy93">
<img src="https://avatars.githubusercontent.com/u/1862727?v=4" width="80;" alt="Lissy93"/>
<br />
<sub><b>Alicia Sykes</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/muni106">
<img src="https://avatars.githubusercontent.com/u/65845442?v=4" width="80;" alt="muni106"/>
<br />
<sub><b>Mounir Samite</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gso-trifork-security">
<img src="https://avatars.githubusercontent.com/u/69247026?v=4" width="80;" alt="gso-trifork-security"/>
<br />
<sub><b>Gustav Soelberg</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/treatmesubj">
<img src="https://avatars.githubusercontent.com/u/39680353?v=4" width="80;" alt="treatmesubj"/>
<br />
<sub><b>John Hupperts</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/UlisesGascon">
<img src="https://avatars.githubusercontent.com/u/5110813?v=4" width="80;" alt="UlisesGascon"/>
<br />
<sub><b>Ulises Gascón</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/abhishekMuge">
<img src="https://avatars.githubusercontent.com/u/49590582?v=4" width="80;" alt="abhishekMuge"/>
<br />
<sub><b>Abhishek Muge</b></sub>
</a>
</td></tr>
</table>
<!-- readme: contributors -end -->
@@ -1106,177 +895,114 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<!-- readme: sponsors -start -->
<table>
<tbody>
<tr>
<td align="center">
<a href="https://github.com/vincentkoc">
<img src="https://avatars.githubusercontent.com/u/25068?v=4" width="80;" alt="vincentkoc"/>
<br />
<sub><b>Vincent Koc</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/AnandChowdhary">
<img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/>
<br />
<sub><b>Anand Chowdhary</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/shrippen">
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
<br />
<sub><b>Shrippen</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bile0026">
<img src="https://avatars.githubusercontent.com/u/5022496?u=aec96ad173c0ea9baaba93807efa8a848af6595c&v=4" width="80;" alt="bile0026"/>
<br />
<sub><b>Zach Biles</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/UlisesGascon">
<img src="https://avatars.githubusercontent.com/u/5110813?u=3c41facd8aa26154b9451de237c34b0f78d672a5&v=4" width="80;" alt="UlisesGascon"/>
<br />
<sub><b>Ulises Gascón</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/digitalarche">
<img src="https://avatars.githubusercontent.com/u/6546135?u=564756d7f44ab2206819eb3148f6d822673f5066&v=4" width="80;" alt="digitalarche"/>
<br />
<sub><b>Digital Archeology</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/InDieTasten">
<img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/>
<br />
<sub><b>InDieTasten</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/araguaci">
<img src="https://avatars.githubusercontent.com/u/7318668?v=4" width="80;" alt="araguaci"/>
<br />
<sub><b>Araguaci</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bmcgonag">
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
<br />
<sub><b>Brian McGonagill</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vlad-tim">
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-tim"/>
<br />
<sub><b>Vlad</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/helixzz">
<img src="https://avatars.githubusercontent.com/u/12218889?u=d06d0c103dfbdb99450623064f7da3c5a3675fb6&v=4" width="80;" alt="helixzz"/>
<br />
<sub><b>HeliXZz</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/patvdv">
<img src="https://avatars.githubusercontent.com/u/12430107?u=e8911c2fb91af4d30432f76da8c40927b2830bd7&v=4" width="80;" alt="patvdv"/>
<br />
<sub><b>Patrick Van Der Veken</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/MioOgbeni">
<img src="https://avatars.githubusercontent.com/u/24291977?v=4" width="80;" alt="MioOgbeni"/>
<br />
<sub><b>Tomáš Novák</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mryesiller">
<img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/>
<br />
<sub><b>Göksel Yeşiller</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/sushibait">
<img src="https://avatars.githubusercontent.com/u/26634535?v=4" width="80;" alt="sushibait"/>
<br />
<sub><b>Shiverme Timbers</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/forwardemail">
<img src="https://avatars.githubusercontent.com/u/32481436?v=4" width="80;" alt="forwardemail"/>
<br />
<sub><b>Forward Email - Open-source & Privacy-focused Email Service (2023)</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/getumbrel">
<img src="https://avatars.githubusercontent.com/u/59408891?v=4" width="80;" alt="getumbrel"/>
<br />
<sub><b>Umbrel</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/OlliVHH">
<img src="https://avatars.githubusercontent.com/u/84959562?v=4" width="80;" alt="OlliVHH"/>
<br />
<sub><b>HamburgerJung</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/frankdez93">
<img src="https://avatars.githubusercontent.com/u/87549420?v=4" width="80;" alt="frankdez93"/>
<br />
<sub><b>Frankdez93</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/terminaltrove">
<img src="https://avatars.githubusercontent.com/u/121595180?v=4" width="80;" alt="terminaltrove"/>
<br />
<sub><b>Terminal Trove</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/st617">
<img src="https://avatars.githubusercontent.com/u/128325650?v=4" width="80;" alt="st617"/>
<br />
<sub><b>st617</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/nrvo">
<img src="https://avatars.githubusercontent.com/u/151435968?u=e1dcb307fd0efdc45cddbe9490a7b956e4da6835&v=4" width="80;" alt="nrvo"/>
<br />
<sub><b>Nrvo</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/hudsonrock-partnerships">
<img src="https://avatars.githubusercontent.com/u/163282900?u=5f2667f7fe5d284ac7a2da6b0800ea8970b0fcbf&v=4" width="80;" alt="hudsonrock-partnerships"/>
<br />
<sub><b>hudsonrock-partnerships</b></sub>
</a>
</td>
</tr>
<tbody>
<tr>
<td align="center">
<a href="https://github.com/emlazzarin">
<img src="https://avatars.githubusercontent.com/u/1141361?v=4" width="80;" alt="emlazzarin"/>
<br />
<sub><b>Eddy Lazzarin</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/AnandChowdhary">
<img src="https://avatars.githubusercontent.com/u/2841780?v=4" width="80;" alt="AnandChowdhary"/>
<br />
<sub><b>Anand Chowdhary</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/shrippen">
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
<br />
<sub><b>shrippen</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/davidpaulyoung">
<img src="https://avatars.githubusercontent.com/u/3418369?v=4" width="80;" alt="davidpaulyoung"/>
<br />
<sub><b>David Young</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/k-rol">
<img src="https://avatars.githubusercontent.com/u/4050412?v=4" width="80;" alt="k-rol"/>
<br />
<sub><b>Carol Ouellet</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bile0026">
<img src="https://avatars.githubusercontent.com/u/5022496?v=4" width="80;" alt="bile0026"/>
<br />
<sub><b>Zach Biles</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/UlisesGascon">
<img src="https://avatars.githubusercontent.com/u/5110813?v=4" width="80;" alt="UlisesGascon"/>
<br />
<sub><b>Ulises Gascón</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/digitalarche">
<img src="https://avatars.githubusercontent.com/u/6546135?v=4" width="80;" alt="digitalarche"/>
<br />
<sub><b>Digital Archeology</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bmcgonag">
<img src="https://avatars.githubusercontent.com/u/7346620?v=4" width="80;" alt="bmcgonag"/>
<br />
<sub><b>Brian McGonagill</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vlad-timofeev">
<img src="https://avatars.githubusercontent.com/u/11474041?v=4" width="80;" alt="vlad-timofeev"/>
<br />
<sub><b>Vlad Timofeev</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/iJasonWade">
<img src="https://avatars.githubusercontent.com/u/12824479?v=4" width="80;" alt="iJasonWade"/>
<br />
<sub><b>Jason Ash</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/DRXAquosus">
<img src="https://avatars.githubusercontent.com/u/45409262?v=4" width="80;" alt="DRXAquosus"/>
<br />
<sub><b>DRXAquosus</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/Bastii717">
<img src="https://avatars.githubusercontent.com/u/53431819?v=4" width="80;" alt="Bastii717"/>
<br />
<sub><b>Bastii717</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ratty222">
<img src="https://avatars.githubusercontent.com/u/92832598?v=4" width="80;" alt="ratty222"/>
<br />
<sub><b>Brent</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jtfinley72">
<img src="https://avatars.githubusercontent.com/u/96497997?v=4" width="80;" alt="jtfinley72"/>
<br />
<sub><b>jtfinley72</b></sub>
</a>
</td></tr>
</table>
<!-- readme: sponsors -end -->
@@ -1312,11 +1038,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
[![View Dependency Licenses & SBOM on FOSSA](https://app.fossa.com/api/projects/git%2Bgithub.com%2FLissy93%2Fweb-check.svg?type=large&issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2FLissy93%2Fweb-check?ref=badge_large&issueType=license)
</details>
<!-- License + Copyright -->
<p align="center">
<i>© <a href="https://aliciasykes.com">Alicia Sykes</a> 2023</i><br>
@@ -1325,7 +1048,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<sup>Thanks for visiting :)</sup>
</p>
<!-- Dinosaurs are Awesome -->
<!-- Dinosaur -->
<!--
. - ~ ~ ~ - .
.. _ .-~ ~-.

View File

@@ -12,9 +12,9 @@ jobs:
name: Inserts Sponsors 💓
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Updates readme with sponsors
uses: JamesIves/github-sponsors-readme-action@v1
uses: JamesIves/github-sponsors-readme-action@1.0.5
with:
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
file: .github/README.md
@@ -25,7 +25,7 @@ jobs:
name: Inserts Contributors 💓
steps:
- name: Updates readme with contributors
uses: akhilmhdh/contributors-readme-action@v2.3.10
uses: akhilmhdh/contributors-readme-action@v2.3.4
env:
GITHUB_TOKEN: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
with:

View File

@@ -1,128 +0,0 @@
name: 🚀 Deploy to AWS
on:
workflow_dispatch:
push:
branches:
- master
tags:
- '*'
paths:
- api/**
- serverless.yml
- package.json
- .github/workflows/deploy-aws.yml
jobs:
deploy-api:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 16
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Create GitHub deployment for API
uses: chrnorm/deployment-action@releases/v2
id: deployment_api
with:
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
environment: AWS (Backend API)
ref: ${{ github.ref }}
- name: Install Serverless CLI and dependencies
run: |
npm i -g serverless
yarn
- name: Deploy to AWS
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
run: serverless deploy
- name: Update GitHub deployment status (API)
if: always()
uses: chrnorm/deployment-status@v2
with:
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
state: "${{ job.status }}"
deployment_id: ${{ steps.deployment_api.outputs.deployment_id }}
ref: ${{ github.ref }}
deploy-frontend:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 16
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Create GitHub deployment for Frontend
uses: chrnorm/deployment-action@v2
id: deployment_frontend
with:
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
environment: AWS (Frontend Web UI)
ref: ${{ github.ref }}
- name: Install dependencies and build
run: |
yarn install
yarn build
- name: Setup AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Upload to S3
env:
AWS_S3_BUCKET: 'web-check-frontend'
run: aws s3 sync ./build/ s3://$AWS_S3_BUCKET/ --delete
- name: Invalidate CloudFront cache
uses: chetan/invalidate-cloudfront-action@v2
env:
DISTRIBUTION: E30XKAM2TG9FD8
PATHS: '/*'
AWS_REGION: 'us-east-1'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Update GitHub deployment status (Frontend)
if: always()
uses: chrnorm/deployment-status@v2
with:
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
state: "${{ job.status }}"
deployment_id: ${{ steps.deployment_frontend.outputs.deployment_id }}
ref: ${{ github.ref }}

View File

@@ -23,14 +23,14 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
- name: Checkout
uses: actions/checkout@v2
- name: Extract tag name 🏷️
- name: Extract tag name
shell: bash
run: echo "GIT_TAG=$(echo ${GITHUB_REF#refs/tags/} | sed 's/\//_/g')" >> $GITHUB_ENV
- name: Compute tags 🔖
- name: Compute tags
id: compute-tags
run: |
if [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
@@ -41,33 +41,33 @@ jobs:
echo "DOCKERHUB_TAG=${DOCKERHUB_REGISTRY}/${DOCKER_USER}/${IMAGE_NAME}:${GIT_TAG}" >> $GITHUB_ENV
fi
- name: Set up QEMU 🐧
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx 🐳
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry 🔑
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ${{ env.GHCR_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub 🔑
- name: Login to DockerHub
uses: docker/login-action@v1
with:
registry: ${{ env.DOCKERHUB_REGISTRY }}
username: ${{ env.DOCKER_USER }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push Docker images 🛠️
- name: Build and push Docker images
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64,linux/arm64/v8
platforms: linux/amd64
tags: |
${{ env.GHCR_TAG }}
${{ env.DOCKERHUB_TAG }}

View File

@@ -8,7 +8,7 @@ jobs:
codeberg:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with: { fetch-depth: 0 }
- uses: pixta-dev/repository-mirroring-action@v1
with:

71
.gitignore vendored
View File

@@ -1,62 +1,27 @@
# ------------------------
# ENVIRONMENT SETTINGS
# ------------------------
# keys
.env
# ------------------------
# PRODUCTION
# ------------------------
/build/
# dependencies
/node_modules
/.pnp
.pnp.js
# ------------------------
# BUILT FILES
# ------------------------
dist/
.vercel/
.netlify/
.webpack/
.serverless/
.astro/
# ------------------------
# DEPENDENCIES
# ------------------------
node_modules/
.yarn/cache/
.yarn/unplugged/
.yarn/build-state.yml
.yarn/install-state.gz
.pnpm/
.pnp.*
# ------------------------
# LOGS
# ------------------------
logs/
*.log
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# ------------------------
# TESTING
# ------------------------
coverage/
.nyc_output/
# testing
/coverage
# ------------------------
# OS SPECIFIC
# ------------------------
# production
/build
# Random AWS and Netlify crap
.netlify
.serverless
.webpack
# OS generated files
.DS_Store
Thumbs.db
# ------------------------
# EDITORS
# ------------------------
.idea/
.vscode/
*.swp
*.swo

View File

@@ -1,62 +1,22 @@
# Specify the Node.js version to use
ARG NODE_VERSION=21
FROM node:16-buster-slim
# Specify the Debian version to use, the default is "bullseye"
ARG DEBIAN_VERSION=bullseye
RUN apt-get update && \
apt-get install -y chromium traceroute && \
chmod 755 /usr/bin/chromium && \
rm -rf /var/lib/apt/lists/*
# Use Node.js Docker image as the base image, with specific Node and Debian versions
FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS build
# Set the container's default shell to Bash and enable some options
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
# Install Chromium browser and Download and verify Google Chromes signing key
RUN apt-get update -qq --fix-missing && \
apt-get -qqy install --allow-unauthenticated gnupg wget && \
wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \
apt-get update -qq && \
apt-get -qqy --no-install-recommends install chromium traceroute python make g++ && \
rm -rf /var/lib/apt/lists/*
# Run the Chromium browser's version command and redirect its output to the /etc/chromium-version file
RUN /usr/bin/chromium --no-sandbox --version > /etc/chromium-version
# Set the working directory to /app
WORKDIR /app
# Copy package.json and yarn.lock to the working directory
COPY package.json yarn.lock ./
# Run yarn install to install dependencies and clear yarn cache
RUN apt-get update && \
yarn install --frozen-lockfile --network-timeout 100000 && \
rm -rf /app/node_modules/.cache
RUN yarn install
# Copy all files to working directory
COPY . .
# Run yarn build to build the application
RUN yarn build --production
RUN yarn build
# Final stage
FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS final
WORKDIR /app
COPY package.json yarn.lock ./
COPY --from=build /app .
RUN apt-get update && \
apt-get install -y --no-install-recommends chromium traceroute && \
chmod 755 /usr/bin/chromium && \
rm -rf /var/lib/apt/lists/* /app/node_modules/.cache
# Exposed container port, the default is 3000, which can be modified through the environment variable PORT
EXPOSE ${PORT:-3000}
# Set the environment variable CHROME_PATH to specify the path to the Chromium binaries
ENV CHROME_PATH='/usr/bin/chromium'
# Define the command executed when the container starts and start the server.js of the Node.js application
CMD ["yarn", "start"]
CMD ["yarn", "serve"]

View File

@@ -2,130 +2,37 @@ const normalizeUrl = (url) => {
return url.startsWith('http') ? url : `https://${url}`;
};
// If present, set a shorter timeout for API requests
const TIMEOUT = process.env.API_TIMEOUT_LIMIT ? parseInt(process.env.API_TIMEOUT_LIMIT, 10) : 60000;
// If present, set CORS allowed origins for responses
const ALLOWED_ORIGINS = process.env.API_CORS_ORIGIN || '*';
// Set the platform currently being used
let PLATFORM = 'NETLIFY';
if (process.env.PLATFORM) { PLATFORM = process.env.PLATFORM.toUpperCase(); }
else if (process.env.VERCEL) { PLATFORM = 'VERCEL'; }
else if (process.env.WC_SERVER) { PLATFORM = 'NODE'; }
// Define the headers to be returned with each response
const headers = {
'Access-Control-Allow-Origin': ALLOWED_ORIGINS,
'Access-Control-Allow-Credentials': true,
'Content-Type': 'application/json;charset=UTF-8',
};
const timeoutErrorMsg = 'You can re-trigger this request, by clicking "Retry"\n'
+ 'If you\'re running your own instance of Web Check, then you can '
+ 'resolve this issue, by increasing the timeout limit in the '
+ '`API_TIMEOUT_LIMIT` environmental variable to a higher value (in milliseconds), '
+ 'or if you\'re hosting on Vercel increase the maxDuration in vercel.json.\n\n'
+ `The public instance currently has a lower timeout of ${TIMEOUT}ms `
+ 'in order to keep running costs affordable, so that Web Check can '
+ 'remain freely available for everyone.';
// A middleware function used by all API routes on all platforms
const commonMiddleware = (handler) => {
// Create a timeout promise, to throw an error if a request takes too long
const createTimeoutPromise = (timeoutMs) => {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`Request timed-out after ${timeoutMs} ms`));
}, timeoutMs);
});
};
// Vercel
const vercelHandler = async (request, response) => {
const queryParams = request.query || {};
const rawUrl = queryParams.url;
if (!rawUrl) {
return response.status(500).json({ error: 'No URL specified' });
}
const url = normalizeUrl(rawUrl);
try {
// Race the handler against the timeout
const handlerResponse = await Promise.race([
handler(url, request),
createTimeoutPromise(TIMEOUT)
]);
if (handlerResponse.body && handlerResponse.statusCode) {
response.status(handlerResponse.statusCode).json(handlerResponse.body);
} else {
response.status(200).json(
typeof handlerResponse === 'object' ? handlerResponse : JSON.parse(handlerResponse)
);
}
} catch (error) {
let errorCode = 500;
if (error.message.includes('timed-out') || response.statusCode === 504) {
errorCode = 408;
error.message = `${error.message}\n\n${timeoutErrorMsg}`;
}
response.status(errorCode).json({ error: error.message });
}
};
// Netlify
const netlifyHandler = async (event, context, callback) => {
return async (event, context, callback) => {
const queryParams = event.queryStringParameters || event.query || {};
const rawUrl = queryParams.url;
if (!rawUrl) {
callback(null, {
statusCode: 500,
body: JSON.stringify({ error: 'No URL specified' }),
headers,
});
return;
}
const url = normalizeUrl(rawUrl);
try {
// Race the handler against the timeout
const handlerResponse = await Promise.race([
handler(url, event, context),
createTimeoutPromise(TIMEOUT)
]);
if (handlerResponse.body && handlerResponse.statusCode) {
callback(null, handlerResponse);
const response = await handler(url, event, context);
if (response.body && response.statusCode) {
callback(null, response);
} else {
callback(null, {
statusCode: 200,
body: typeof handlerResponse === 'object' ? JSON.stringify(handlerResponse) : handlerResponse,
headers,
body: typeof response === 'object' ? JSON.stringify(response) : response,
});
}
} catch (error) {
callback(null, {
statusCode: 500,
body: JSON.stringify({ error: error.message }),
headers,
});
}
};
// The format of the handlers varies between platforms
const nativeMode = (['VERCEL', 'NODE'].includes(PLATFORM));
return nativeMode ? vercelHandler : netlifyHandler;
};
if (PLATFORM === 'NETLIFY') {
module.exports = commonMiddleware;
}
export default commonMiddleware;
module.exports = commonMiddleware;

View File

@@ -1,5 +1,5 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const convertTimestampToDate = (timestamp) => {
const [year, month, day, hour, minute, second] = [
@@ -46,7 +46,7 @@ const getScanFrequency = (firstScan, lastScan, totalScans, changeCount) => {
};
};
const wayBackHandler = async (url) => {
const getWaybackData = async (url) => {
const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${url}&output=json&fl=timestamp,statuscode,digest,length,offset`;
try {
@@ -80,5 +80,4 @@ const wayBackHandler = async (url) => {
}
};
export const handler = middleware(wayBackHandler);
export default handler;
exports.handler = middleware(getWaybackData);

View File

@@ -1,6 +1,6 @@
import dns from 'dns';
import { URL } from 'url';
import middleware from './_common/middleware.js';
const dns = require('dns');
const { URL } = require('url');
const middleware = require('./_common/middleware');
const DNS_SERVERS = [
{ name: 'AdGuard', ip: '176.103.130.130' },
@@ -94,12 +94,12 @@ const checkDomainAgainstDnsServers = async (domain) => {
return results;
};
export const blockListHandler = async (url) => {
exports.handler = middleware(async (url) => {
const domain = new URL(url).hostname;
const results = await checkDomainAgainstDnsServers(domain);
return { blocklists: results };
};
export const handler = middleware(blockListHandler);
export default handler;
return {
statusCode: 200,
body: JSON.stringify({ blocklists: results })
};
});

View File

@@ -1,7 +1,7 @@
import https from 'https';
import middleware from './_common/middleware.js';
const https = require('https');
const middleware = require('./_common/middleware');
const carbonHandler = async (url) => {
const handler = async (url) => {
// First, get the size of the website's HTML
const getHtmlSize = (url) => new Promise((resolve, reject) => {
@@ -48,5 +48,4 @@ const carbonHandler = async (url) => {
}
};
export const handler = middleware(carbonHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import puppeteer from 'puppeteer';
import middleware from './_common/middleware.js';
const axios = require('axios');
const puppeteer = require('puppeteer');
const middleware = require('./_common/middleware');
const getPuppeteerCookies = async (url) => {
const browser = await puppeteer.launch({
@@ -21,7 +21,7 @@ const getPuppeteerCookies = async (url) => {
}
};
const cookieHandler = async (url) => {
const handler = async (url) => {
let headerCookies = null;
let clientCookies = null;
@@ -54,5 +54,4 @@ const cookieHandler = async (url) => {
return { headerCookies, clientCookies };
};
export const handler = middleware(cookieHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,8 +1,9 @@
import { promises as dnsPromises, lookup } from 'dns';
import axios from 'axios';
import middleware from './_common/middleware.js';
const dns = require('dns');
const dnsPromises = dns.promises;
const axios = require('axios');
const commonMiddleware = require('./_common/middleware');
const dnsHandler = async (url) => {
const handler = async (url) => {
try {
const domain = url.replace(/^(?:https?:\/\/)?/i, "");
const addresses = await dnsPromises.resolve4(domain);
@@ -40,7 +41,4 @@ const dnsHandler = async (url) => {
}
};
export const handler = middleware(dnsHandler);
export default handler;
exports.handler = commonMiddleware(handler);

View File

@@ -1,8 +1,8 @@
import dns from 'dns';
import util from 'util';
import middleware from './_common/middleware.js';
const dns = require('dns');
const util = require('util');
const middleware = require('./_common/middleware');
const dnsHandler = async (url) => {
const handler = async (url) => {
let hostname = url;
// Handle URLs by extracting hostname
@@ -51,5 +51,4 @@ const dnsHandler = async (url) => {
}
};
export const handler = middleware(dnsHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,7 +1,7 @@
import https from 'https';
import middleware from './_common/middleware.js';
const https = require('https');
const commonMiddleware = require('./_common/middleware'); // Make sure this path is correct
const dnsSecHandler = async (domain) => {
const fetchDNSRecords = async (domain, event, context) => {
const dnsTypes = ['DNSKEY', 'DS', 'RRSIG'];
const records = {};
@@ -25,11 +25,7 @@ const dnsSecHandler = async (domain) => {
});
res.on('end', () => {
try {
resolve(JSON.parse(data));
} catch (error) {
reject(new Error('Invalid JSON response'));
}
resolve(JSON.parse(data));
});
res.on('error', error => {
@@ -53,5 +49,4 @@ const dnsSecHandler = async (domain) => {
return records;
};
export const handler = middleware(dnsSecHandler);
export default handler;
exports.handler = commonMiddleware(fetchDNSRecords);

View File

@@ -1,7 +1,7 @@
import https from 'https';
import middleware from './_common/middleware.js';
const https = require('https');
const middleware = require('./_common/middleware');
const featuresHandler = async (url) => {
const builtWithHandler = async (url) => {
const apiKey = process.env.BUILT_WITH_API_KEY;
if (!url) {
@@ -45,5 +45,4 @@ const featuresHandler = async (url) => {
}
};
export const handler = middleware(featuresHandler);
export default handler;
exports.handler = middleware(builtWithHandler);

View File

@@ -1,5 +1,5 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const hasWaf = (waf) => {
return {
@@ -7,7 +7,7 @@ const hasWaf = (waf) => {
}
};
const firewallHandler = async (url) => {
const handler = async (url) => {
const fullUrl = url.startsWith('http') ? url : `http://${url}`;
try {
@@ -91,14 +91,6 @@ const firewallHandler = async (url) => {
return hasWaf('IBM WebSphere DataPower');
}
if (headers['server'] && headers['server'].includes('QRATOR')) {
return hasWaf('QRATOR WAF');
}
if (headers['server'] && headers['server'].includes('ddos-guard')) {
return hasWaf('DDoS-Guard WAF');
}
return {
hasWaf: false,
}
@@ -110,5 +102,4 @@ const firewallHandler = async (url) => {
}
};
export const handler = middleware(firewallHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,5 +1,5 @@
import dns from 'dns';
import middleware from './_common/middleware.js';
const dns = require('dns');
const middleware = require('./_common/middleware');
const lookupAsync = (address) => {
return new Promise((resolve, reject) => {
@@ -13,11 +13,9 @@ const lookupAsync = (address) => {
});
};
const ipHandler = async (url) => {
const handler = async (url) => {
const address = url.replaceAll('https://', '').replaceAll('http://', '');
return await lookupAsync(address);
};
export const handler = middleware(ipHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,7 +1,7 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const headersHandler = async (url, event, context) => {
const handler = async (url, event, context) => {
try {
const response = await axios.get(url, {
validateStatus: function (status) {
@@ -15,5 +15,4 @@ const headersHandler = async (url, event, context) => {
}
};
export const handler = middleware(headersHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,15 +1,18 @@
import https from 'https';
import middleware from './_common/middleware.js';
const https = require('https');
const middleware = require('./_common/middleware');
const hstsHandler = async (url, event, context) => {
exports.handler = middleware(async (url, event, context) => {
const errorResponse = (message, statusCode = 500) => {
return {
statusCode: statusCode,
body: JSON.stringify({ error: message }),
};
};
const hstsIncompatible = (message, compatible = false, hstsHeader = null ) => {
return { message, compatible, hstsHeader };
const hstsIncompatible = (message, statusCode = 200) => {
return {
statusCode: statusCode,
body: JSON.stringify({ message, compatible: false }),
};
};
@@ -32,7 +35,14 @@ const hstsHandler = async (url, event, context) => {
} else if (!preload) {
resolve(hstsIncompatible(`HSTS header does not contain the preload directive.`));
} else {
resolve(hstsIncompatible(`Site is compatible with the HSTS preload list!`, true, hstsHeader));
resolve({
statusCode: 200,
body: JSON.stringify({
message: "Site is compatible with the HSTS preload list!",
compatible: true,
hstsHeader: hstsHeader,
}),
});
}
}
});
@@ -43,7 +53,5 @@ const hstsHandler = async (url, event, context) => {
req.end();
});
};
});
export const handler = middleware(hstsHandler);
export default handler;

View File

@@ -1,14 +1,14 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const httpsSecHandler = async (url) => {
const handler = async (url) => {
const fullUrl = url.startsWith('http') ? url : `http://${url}`;
try {
const response = await axios.get(fullUrl);
const headers = response.headers;
return {
strictTransportPolicy: headers['strict-transport-security'] ? true : false,
strictTransportPolicy: headers['strict-transport-policy'] ? true : false,
xFrameOptions: headers['x-frame-options'] ? true : false,
xContentTypeOptions: headers['x-content-type-options'] ? true : false,
xXSSProtection: headers['x-xss-protection'] ? true : false,
@@ -22,5 +22,4 @@ const httpsSecHandler = async (url) => {
}
};
export const handler = middleware(httpsSecHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,8 +1,8 @@
import axios from 'axios';
import unzipper from 'unzipper';
import csv from 'csv-parser';
import fs from 'fs';
import middleware from './_common/middleware.js';
const axios = require('axios');
const unzipper = require('unzipper');
const csv = require('csv-parser');
const fs = require('fs');
const middleware = require('./_common/middleware');
// Should also work with the following sources:
// https://www.domcop.com/files/top/top10milliondomains.csv.zip
@@ -14,7 +14,7 @@ import middleware from './_common/middleware.js';
const FILE_URL = 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip';
const TEMP_FILE_PATH = '/tmp/top-1m.csv';
const rankHandler = async (url) => {
const handler = async (url) => {
let domain = null;
try {
@@ -66,5 +66,5 @@ return new Promise((resolve, reject) => {
});
};
export const handler = middleware(rankHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,9 +1,9 @@
import axios from 'axios';
import cheerio from 'cheerio';
import urlLib from 'url';
import middleware from './_common/middleware.js';
const axios = require('axios');
const cheerio = require('cheerio');
const urlLib = require('url');
const commonMiddleware = require('./_common/middleware');
const linkedPagesHandler = async (url) => {
const handler = async (url) => {
const response = await axios.get(url);
const html = response.data;
const $ = cheerio.load(html);
@@ -33,17 +33,16 @@ const linkedPagesHandler = async (url) => {
if (internalLinks.length === 0 && externalLinks.length === 0) {
return {
statusCode: 400,
body: {
body: JSON.stringify({
skipped: 'No internal or external links found. '
+ 'This may be due to the website being dynamically rendered, using a client-side framework (like React), and without SSR enabled. '
+ 'That would mean that the static HTML returned from the HTTP request doesn\'t contain any meaningful content for Web-Check to analyze. '
+ 'You can rectify this by using a headless browser to render the page instead.',
},
}),
};
}
return { internal: internalLinks, external: externalLinks };
};
export const handler = middleware(linkedPagesHandler);
export default handler;
exports.handler = commonMiddleware(handler);

View File

@@ -1,10 +1,9 @@
import dns from 'dns';
import URL from 'url-parse';
import middleware from './_common/middleware.js';
const commonMiddleware = require('./_common/middleware');
// TODO: Fix.
const dns = require('dns').promises;
const URL = require('url-parse');
const mailConfigHandler = async (url, event, context) => {
const handler = async (url, event, context) => {
try {
const domain = new URL(url).hostname || new URL(url).pathname;
@@ -55,11 +54,6 @@ const mailConfigHandler = async (url, event, context) => {
if (yahooMx.length > 0) {
mailServices.push({ provider: 'Yahoo', value: yahooMx[0].exchange });
}
// Check MX records for Mimecast
const mimecastMx = mxRecords.filter(record => record.exchange.includes('mimecast.com'));
if (mimecastMx.length > 0) {
mailServices.push({ provider: 'Mimecast', value: mimecastMx[0].exchange });
}
return {
mxRecords,
@@ -72,11 +66,10 @@ const mailConfigHandler = async (url, event, context) => {
} else {
return {
statusCode: 500,
body: { error: error.message },
body: JSON.stringify({ error: error.message }),
};
}
}
};
export const handler = middleware(mailConfigHandler);
export default handler;
module.exports.handler = commonMiddleware(handler);

View File

@@ -1,5 +1,5 @@
import net from 'net';
import middleware from './_common/middleware.js';
const net = require('net');
const middleware = require('./_common/middleware');
// A list of commonly used ports.
const PORTS = [
@@ -34,7 +34,7 @@ async function checkPort(port, domain) {
});
}
const portsHandler = async (url, event, context) => {
const handler = async (url, event, context) => {
const domain = url.replace(/(^\w+:|^)\/\//, '');
const delay = ms => new Promise(res => setTimeout(res, ms));
@@ -72,17 +72,18 @@ const portsHandler = async (url, event, context) => {
if(timeoutReached){
return errorResponse('The function timed out before completing.');
}
// Sort openPorts and failedPorts before returning
openPorts.sort((a, b) => a - b);
failedPorts.sort((a, b) => a - b);
return { openPorts, failedPorts };
return {
statusCode: 200,
body: JSON.stringify({ openPorts, failedPorts }),
};
};
const errorResponse = (message, statusCode = 444) => {
return { error: message };
return {
statusCode: statusCode,
body: JSON.stringify({ error: message }),
};
};
export const handler = middleware(portsHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,22 +1,22 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const qualityHandler = async (url, event, context) => {
const handler = async (url, event, context) => {
const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
if (!apiKey) {
throw new Error(
'Missing Google API. You need to set the `GOOGLE_CLOUD_API_KEY` environment variable'
);
if (!url) {
throw new Error('URL param is required');
}
const endpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?`
+ `url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY`
+ `&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile`
+ `&key=${apiKey}`;
if (!apiKey) {
throw new Error('API key (GOOGLE_CLOUD_API_KEY) not set');
}
return (await axios.get(endpoint)).data;
const endpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile&key=${apiKey}`;
const response = await axios.get(endpoint);
return response.data;
};
export const handler = middleware(qualityHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,7 +1,7 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const rankHandler = async (url) => {
const handler = async (url) => {
const domain = url ? new URL(url).hostname : null;
if (!domain) throw new Error('Invalid URL');
@@ -10,7 +10,7 @@ const rankHandler = async (url) => {
{ auth: { username: process.env.TRANCO_USERNAME, password: process.env.TRANCO_API_KEY } }
: {};
const response = await axios.get(
`https://tranco-list.eu/api/ranks/domain/${domain}`, { timeout: 5000 }, auth,
`https://tranco-list.eu/api/ranks/domain/${domain}`, { timeout: 2000 }, auth,
);
if (!response.data || !response.data.ranks || response.data.ranks.length === 0) {
return { skipped: `Skipping, as ${domain} isn't ranked in the top 100 million sites yet.`};
@@ -21,6 +21,4 @@ const rankHandler = async (url) => {
}
};
export const handler = middleware(rankHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,10 +1,9 @@
import got from 'got';
import middleware from './_common/middleware.js';
const redirectsHandler = async (url) => {
const handler = async (url) => {
const redirects = [url];
const got = await import('got');
try {
await got(url, {
await got.default(url, {
followRedirect: true,
maxRedirects: 12,
hooks: {
@@ -24,5 +23,5 @@ const redirectsHandler = async (url) => {
}
};
export const handler = middleware(redirectsHandler);
export default handler;
const middleware = require('./_common/middleware');
exports.handler = middleware(handler);

View File

@@ -1,5 +1,5 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const parseRobotsTxt = (content) => {
const lines = content.split('\n');
@@ -31,7 +31,7 @@ const parseRobotsTxt = (content) => {
return { robots: rules };
}
const robotsHandler = async function(url) {
const handler = async function(url) {
let parsedURL;
try {
parsedURL = new URL(url);
@@ -67,5 +67,4 @@ const robotsHandler = async function(url) {
}
};
export const handler = middleware(robotsHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,6 +1,6 @@
import puppeteer from 'puppeteer-core';
import chromium from 'chrome-aws-lambda';
import middleware from './_common/middleware.js';
const puppeteer = require('puppeteer-core');
const chromium = require('chrome-aws-lambda');
const middleware = require('./_common/middleware');
const screenshotHandler = async (targetUrl) => {
@@ -21,7 +21,7 @@ const screenshotHandler = async (targetUrl) => {
let browser = null;
try {
browser = await puppeteer.launch({
args: [...chromium.args, '--no-sandbox'], // Add --no-sandbox flag
args: chromium.args,
defaultViewport: { width: 800, height: 600 },
executablePath: process.env.CHROME_PATH || await chromium.executablePath,
headless: chromium.headless,
@@ -58,5 +58,4 @@ const screenshotHandler = async (targetUrl) => {
}
};
export const handler = middleware(screenshotHandler);
export default handler;
exports.handler = middleware(screenshotHandler);

View File

@@ -1,8 +1,6 @@
import { URL } from 'url';
import followRedirects from 'follow-redirects';
import middleware from './_common/middleware.js';
const { https } = followRedirects;
const { https } = require('follow-redirects');
const { URL } = require('url');
const middleware = require('./_common/middleware');
const SECURITY_TXT_PATHS = [
'/security.txt',
@@ -71,6 +69,8 @@ const securityTxtHandler = async (urlParam) => {
return { isPresent: false };
};
exports.handler = middleware(securityTxtHandler);
async function fetchSecurityTxt(baseURL, path) {
return new Promise((resolve, reject) => {
const url = new URL(path, baseURL);
@@ -91,6 +91,3 @@ async function fetchSecurityTxt(baseURL, path) {
});
});
}
export const handler = middleware(securityTxtHandler);
export default handler;

View File

@@ -1,21 +1,20 @@
import axios from 'axios';
import xml2js from 'xml2js';
import middleware from './_common/middleware.js';
const commonMiddleware = require('./_common/middleware');
const sitemapHandler = async (url) => {
const axios = require('axios');
const xml2js = require('xml2js');
const handler = async (url) => {
let sitemapUrl = `${url}/sitemap.xml`;
const hardTimeOut = 5000;
try {
// Try to fetch sitemap directly
let sitemapRes;
try {
sitemapRes = await axios.get(sitemapUrl, { timeout: hardTimeOut });
sitemapRes = await axios.get(sitemapUrl, { timeout: 5000 });
} catch (error) {
if (error.response && error.response.status === 404) {
// If sitemap not found, try to fetch it from robots.txt
const robotsRes = await axios.get(`${url}/robots.txt`, { timeout: hardTimeOut });
const robotsRes = await axios.get(`${url}/robots.txt`, { timeout: 5000 });
const robotsTxt = robotsRes.data.split('\n');
for (let line of robotsTxt) {
@@ -26,10 +25,13 @@ const sitemapHandler = async (url) => {
}
if (!sitemapUrl) {
return { skipped: 'No sitemap found' };
return {
statusCode: 404,
body: JSON.stringify({ skipped: 'No sitemap found' }),
};
}
sitemapRes = await axios.get(sitemapUrl, { timeout: hardTimeOut });
sitemapRes = await axios.get(sitemapUrl, { timeout: 5000 });
} else {
throw error; // If other error, throw it
}
@@ -38,16 +40,25 @@ const sitemapHandler = async (url) => {
const parser = new xml2js.Parser();
const sitemap = await parser.parseStringPromise(sitemapRes.data);
return sitemap;
return {
statusCode: 200,
body: JSON.stringify(sitemap),
};
} catch (error) {
// If error occurs
console.log(error.message);
if (error.code === 'ECONNABORTED') {
return { error: `Request timed-out after ${hardTimeOut}ms` };
return {
statusCode: 500,
body: JSON.stringify({ error: 'Request timed out' }),
};
} else {
return { error: error.message };
return {
statusCode: 500,
body: JSON.stringify({ error: error.message }),
};
}
}
};
export const handler = middleware(sitemapHandler);
export default handler;
exports.handler = commonMiddleware(handler);

View File

@@ -1,8 +1,9 @@
import axios from 'axios';
import cheerio from 'cheerio';
import middleware from './_common/middleware.js';
const commonMiddleware = require('./_common/middleware');
const socialTagsHandler = async (url) => {
const axios = require('axios');
const cheerio = require('cheerio');
const handler = async (url) => {
// Check if url includes protocol
if (!url.startsWith('http://') && !url.startsWith('https://')) {
@@ -49,9 +50,16 @@ const socialTagsHandler = async (url) => {
};
if (Object.keys(metadata).length === 0) {
return { skipped: 'No metadata found' };
return {
statusCode: 200,
body: JSON.stringify({ skipped: 'No metadata found' }),
};
}
return metadata;
return {
statusCode: 200,
body: JSON.stringify(metadata),
};
} catch (error) {
return {
statusCode: 500,
@@ -60,5 +68,4 @@ const socialTagsHandler = async (url) => {
}
};
export const handler = middleware(socialTagsHandler);
export default handler;
exports.handler = commonMiddleware(handler);

View File

@@ -1,7 +1,7 @@
import tls from 'tls';
import middleware from './_common/middleware.js';
const tls = require('tls');
const middleware = require('./_common/middleware');
const sslHandler = async (urlString) => {
const fetchSiteCertificateHandler = async (urlString) => {
try {
const parsedUrl = new URL(urlString);
const options = {
@@ -40,5 +40,4 @@ const sslHandler = async (urlString) => {
}
};
export const handler = middleware(sslHandler);
export default handler;
exports.handler = middleware(fetchSiteCertificateHandler);

View File

@@ -1,8 +1,8 @@
import https from 'https';
import { performance, PerformanceObserver } from 'perf_hooks';
import middleware from './_common/middleware.js';
const https = require('https');
const { performance, PerformanceObserver } = require('perf_hooks');
const middleware = require('./_common/middleware');
const statusHandler = async (url) => {
const checkURLHandler = async (url) => {
if (!url) {
throw new Error('You must provide a URL query parameter!');
}
@@ -55,5 +55,4 @@ const statusHandler = async (url) => {
}
};
export const handler = middleware(statusHandler);
export default handler;
exports.handler = middleware(checkURLHandler);

View File

@@ -1,7 +1,7 @@
import Wappalyzer from 'wappalyzer';
import middleware from './_common/middleware.js';
const Wappalyzer = require('wappalyzer');
const middleware = require('./_common/middleware');
const techStackHandler = async (url) => {
const analyzeSiteTechnologies = async (url) => {
const options = {};
const wappalyzer = new Wappalyzer(options);
@@ -27,5 +27,4 @@ const techStackHandler = async (url) => {
}
};
export const handler = middleware(techStackHandler);
export default handler;
exports.handler = middleware(analyzeSiteTechnologies);

View File

@@ -1,13 +1,10 @@
import axios from 'axios';
import xml2js from 'xml2js';
import middleware from './_common/middleware.js';
const axios = require('axios');
const xml2js = require('xml2js');
const middleware = require('./_common/middleware');
const getGoogleSafeBrowsingResult = async (url) => {
try {
const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
if (!apiKey) {
return { error: 'GOOGLE_CLOUD_API_KEY is required for the Google Safe Browsing check' };
}
const apiEndpoint = `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${apiKey}`;
const requestBody = {
@@ -66,15 +63,11 @@ const getPhishTankResult = async (url) => {
}
const getCloudmersiveResult = async (url) => {
const apiKey = process.env.CLOUDMERSIVE_API_KEY;
if (!apiKey) {
return { error: 'CLOUDMERSIVE_API_KEY is required for the Cloudmersive check' };
}
try {
const endpoint = 'https://api.cloudmersive.com/virus/scan/website';
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Apikey': apiKey,
'Apikey': process.env.CLOUDMERSIVE_API_KEY,
};
const data = `Url=${encodeURIComponent(url)}`;
const response = await axios.post(endpoint, data, { headers });
@@ -84,7 +77,7 @@ const getCloudmersiveResult = async (url) => {
}
};
const threatsHandler = async (url) => {
const handler = async (url) => {
try {
const urlHaus = await getUrlHausResult(url);
const phishTank = await getPhishTankResult(url);
@@ -99,5 +92,4 @@ const threatsHandler = async (url) => {
}
};
export const handler = middleware(threatsHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,9 +1,9 @@
import axios from 'axios';
import middleware from './_common/middleware.js';
const axios = require('axios');
const middleware = require('./_common/middleware');
const MOZILLA_TLS_OBSERVATORY_API = 'https://tls-observatory.services.mozilla.com/api/v1';
const tlsHandler = async (url) => {
const handler = async (url) => {
try {
const domain = new URL(url).hostname;
const scanResponse = await axios.post(`${MOZILLA_TLS_OBSERVATORY_API}/scan?target=${domain}`);
@@ -12,18 +12,17 @@ const tlsHandler = async (url) => {
if (typeof scanId !== 'number') {
return {
statusCode: 500,
body: { error: 'Failed to get scan_id from TLS Observatory' },
body: JSON.stringify({ error: 'Failed to get scan_id from TLS Observatory' }),
};
}
const resultResponse = await axios.get(`${MOZILLA_TLS_OBSERVATORY_API}/results?id=${scanId}`);
return {
statusCode: 200,
body: resultResponse.data,
body: JSON.stringify(resultResponse.data),
};
} catch (error) {
return { error: error.message };
}
};
export const handler = middleware(tlsHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,8 +1,8 @@
import url from 'url';
import traceroute from 'traceroute';
import middleware from './_common/middleware.js';
const traceroute = require('traceroute');
const url = require('url');
const middleware = require('./_common/middleware');
const traceRouteHandler = async (urlString, context) => {
const executeTraceroute = async (urlString, context) => {
// Parse the URL and get the hostname
const urlObject = url.parse(urlString);
const host = urlObject.hostname;
@@ -28,5 +28,4 @@ const traceRouteHandler = async (urlString, context) => {
};
};
export const handler = middleware(traceRouteHandler);
export default handler;
exports.handler = middleware(executeTraceroute);

View File

@@ -1,7 +1,7 @@
import dns from 'dns/promises';
import middleware from './_common/middleware.js';
const dns = require('dns').promises;
const middleware = require('./_common/middleware');
const txtRecordHandler = async (url, event, context) => {
const handler = async (url, event, context) => {
try {
const parsedUrl = new URL(url);
@@ -29,5 +29,4 @@ const txtRecordHandler = async (url, event, context) => {
}
};
export const handler = middleware(txtRecordHandler);
export default handler;
exports.handler = middleware(handler);

View File

@@ -1,7 +1,7 @@
import net from 'net';
import psl from 'psl';
import axios from 'axios';
import middleware from './_common/middleware.js';
const net = require('net');
const psl = require('psl');
const axios = require('axios');
const middleware = require('./_common/middleware');
const getBaseDomain = (url) => {
let protocol = '';
@@ -83,7 +83,7 @@ const fetchFromMyAPI = async (hostname) => {
}
};
const whoisHandler = async (url) => {
const fetchWhoisData = async (url) => {
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'http://' + url;
}
@@ -106,6 +106,4 @@ const whoisHandler = async (url) => {
};
};
export const handler = middleware(whoisHandler);
export default handler;
exports.handler = middleware(fetchWhoisData);

View File

@@ -1,79 +0,0 @@
import { defineConfig } from 'astro/config';
// Integrations
import svelte from '@astrojs/svelte';
import react from "@astrojs/react";
import partytown from '@astrojs/partytown';
import sitemap from '@astrojs/sitemap';
// Adapters
import vercelAdapter from '@astrojs/vercel/serverless';
import netlifyAdapter from '@astrojs/netlify';
import nodeAdapter from '@astrojs/node';
import cloudflareAdapter from '@astrojs/cloudflare';
// Helper function to unwrap both Vite and Node environment variables
const unwrapEnvVar = (varName, fallbackValue) => {
const classicEnvVar = process?.env && process.env[varName];
const viteEnvVar = import.meta.env[varName];
return classicEnvVar || viteEnvVar || fallbackValue;
}
// Determine the deploy target (vercel, netlify, cloudflare, node)
const deployTarget = unwrapEnvVar('PLATFORM', 'node').toLowerCase();
// Determine the output mode (server, hybrid or static)
const output = unwrapEnvVar('OUTPUT', 'hybrid');
// The FQDN of where the site is hosted (used for sitemaps & canonical URLs)
const site = unwrapEnvVar('SITE_URL', 'https://web-check.xyz');
// The base URL of the site (if serving from a subdirectory)
const base = unwrapEnvVar('BASE_URL', '/');
// Should run the app in boss-mode (requires extra configuration)
const isBossServer = unwrapEnvVar('BOSS_SERVER', false);
// Initialize Astro integrations
const integrations = [svelte(), react(), partytown(), sitemap()];
// Set the appropriate adapter, based on the deploy target
function getAdapter(target) {
switch(target) {
case 'vercel':
return vercelAdapter();
case 'netlify':
return netlifyAdapter();
case 'cloudflare':
return cloudflareAdapter();
case 'node':
return nodeAdapter({ mode: 'middleware' });
default:
throw new Error(`Unsupported deploy target: ${target}`);
}
}
const adapter = getAdapter(deployTarget);
// Print build information to console
console.log(
`\n\x1b[1m\x1b[35m Preparing to start build of Web Check.... \x1b[0m\n`,
`\x1b[35m\x1b[2mCompiling for "${deployTarget}" using "${output}" mode, `
+ `to deploy to "${site}" at "${base}"\x1b[0m\n`,
`\x1b[2m\x1b[36m🛟 For documentation and support, visit the GitHub repo: ` +
`https://github.com/lissy93/web-check \n`,
`💖 Found Web-Check useful? Consider sponsoring us on GitHub ` +
`to help fund maintenance & development.\x1b[0m\n`,
);
const redirects = {
'/about': '/check/about',
};
// Skip the marketing homepage for self-hosted users
if (!isBossServer && isBossServer !== true) {
redirects['/'] = '/check';
}
// Export Astro configuration
export default defineConfig({ output, base, integrations, site, adapter, redirects });

View File

@@ -1,17 +0,0 @@
app = 'web-check'
primary_region = 'lhr'
[build]
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ['app']
[[vm]]
memory = '1gb'
cpu_kind = 'shared'
cpus = 1

View File

@@ -2,13 +2,11 @@
[build]
base = "/"
command = "yarn build"
publish = "dist"
publish = "build"
functions = "api"
# Environmental variables and optional secrets
# Environmental variables and optioanl secrets
[build.environment]
PLATFORM = "netlify"
PUBLIC_API_ENDPOINT = "/.netlify/functions"
# Build configuration env vars (uncomment if you want to conigure these)
# CI="false" # Set CI to false, to prevent warnings from exiting the build
# CHROME_PATH='/usr/bin/chromium' # Path to Chromium binary
@@ -27,6 +25,12 @@
status = 301
force = true
# For router history mode, ensure pages land on index
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
# Plugins
[[plugins]]
package = "netlify-plugin-chromium"

View File

@@ -1,73 +1,100 @@
{
"name": "web-check",
"type": "module",
"version": "2.0.0",
"homepage": "https://web-check.xyz",
"version": "1.0.0",
"private": false,
"description": "All-in-one OSINT tool for analyzing any website",
"repository": "github:lissy93/web-check",
"homepage": "https://web-check.as93.net",
"license": "MIT",
"author": {
"name": "Alicia Sykes",
"email": "alicia@omg.lol"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Lissy93"
},
"scripts": {
"start": "node server",
"start-pm": "pm2 start server.js -i max",
"build": "astro check && astro build",
"dev:vercel": "PLATFORM='vercel' npx vercel dev",
"dev:netlify": "PLATFORM='netlify' npx netlify dev",
"dev:api": "DISABLE_GUI='true' PORT='3001' nodemon server",
"dev:astro": "PUBLIC_API_ENDPOINT=http://localhost:3001/api astro dev",
"dev": "concurrently -c magenta,cyan -n backend,frontend 'yarn dev:api' 'yarn dev:astro'"
"dev": "netlify dev",
"serve": "node server",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"dependencies": {
"@astrojs/check": "^0.5.10",
"@astrojs/react": "^3.3.2",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/svelte-fontawesome": "^0.2.2",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"astro": "^4.7.1",
"axios": "^1.4.8",
"@netlify/functions": "^1.6.0",
"@sentry/react": "^7.60.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.5.3",
"@types/node": "^20.4.4",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3",
"@types/react-simple-maps": "^3.0.0",
"@types/styled-components": "^5.1.26",
"aws-serverless-express": "^3.4.0",
"axios": "^1.4.0",
"cheerio": "^1.0.0-rc.12",
"chrome-aws-lambda": "^10.1.0",
"chromium": "^3.0.3",
"connect-history-api-fallback": "^2.0.0",
"cors": "^2.8.5",
"csv-parser": "^3.0.0",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-rate-limit": "^7.2.0",
"framer-motion": "^11.2.6",
"got": "^14.2.1",
"pm2": "^5.3.1",
"dotenv": "^16.3.1",
"flatted": "^3.2.7",
"follow-redirects": "^1.15.2",
"got": "^13.0.0",
"jest-styled-components": "^7.1.1",
"netlify-cli": "^15.9.1",
"perf_hooks": "^0.0.1",
"psl": "^1.9.0",
"puppeteer": "^22.8.0",
"puppeteer-core": "^22.8.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"puppeteer": "^20.9.0",
"puppeteer-core": "^21.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-masonry-css": "^1.0.16",
"react-router-dom": "^6.23.0",
"react-router-dom": "^6.14.2",
"react-scripts": "5.0.1",
"react-simple-maps": "^3.0.0",
"react-toastify": "^10.0.5",
"recharts": "^2.12.6",
"svelte": "^4.2.17",
"react-toastify": "^9.1.3",
"recharts": "^2.7.3",
"styled-components": "^6.0.5",
"traceroute": "^1.0.0",
"typescript": "^5.4.5",
"unzipper": "^0.11.5",
"url-parse": "^1.5.10",
"typescript": "^5.1.6",
"unzipper": "^0.10.14",
"wappalyzer": "^6.10.65",
"web-vitals": "^3.4.0",
"xml2js": "^0.6.2"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"compilerOptions": {
"allowJs": true,
"outDir": "./dist"
},
"devDependencies": {
"@astrojs/cloudflare": "^10.2.5",
"@astrojs/netlify": "^5.2.0",
"@astrojs/node": "^8.2.5",
"@astrojs/partytown": "^2.1.0",
"@astrojs/sitemap": "^3.1.4",
"@astrojs/svelte": "^5.4.0",
"@astrojs/ts-plugin": "^1.6.1",
"@astrojs/vercel": "^7.5.4",
"concurrently": "^8.2.2",
"nodemon": "^3.1.0",
"sass": "^1.77.1"
"serverless-domain-manager": "^7.1.1",
"serverless-offline": "^12.0.4",
"serverless-webpack": "^5.13.0",
"webpack": "^5.88.2",
"webpack-node-externals": "^3.0.0"
}
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="205" height="20" role="img" aria-label="DockerHub: Lissy93/Web Check"><title>DockerHub: Lissy93/Web Check</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="205" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="88" height="20" fill="#1c1d28"/><rect x="88" width="117" height="20" fill="#1fb1f4"/><rect width="205" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkRvY2tlcjwvdGl0bGU+PHBhdGggZD0iTTEzLjk4MyAxMS4wNzhoMi4xMTlhLjE4Ni4xODYgMCAwMC4xODYtLjE4NVY5LjAwNmEuMTg2LjE4NiAwIDAwLS4xODYtLjE4NmgtMi4xMTlhLjE4NS4xODUgMCAwMC0uMTg1LjE4NXYxLjg4OGMwIC4xMDIuMDgzLjE4NS4xODUuMTg1bS0yLjk1NC01LjQzaDIuMTE4YS4xODYuMTg2IDAgMDAuMTg2LS4xODZWMy41NzRhLjE4Ni4xODYgMCAwMC0uMTg2LS4xODVoLTIuMTE4YS4xODUuMTg1IDAgMDAtLjE4NS4xODV2MS44ODhjMCAuMTAyLjA4Mi4xODUuMTg1LjE4NW0wIDIuNzE2aDIuMTE4YS4xODcuMTg3IDAgMDAuMTg2LS4xODZWNi4yOWEuMTg2LjE4NiAwIDAwLS4xODYtLjE4NWgtMi4xMThhLjE4NS4xODUgMCAwMC0uMTg1LjE4NXYxLjg4N2MwIC4xMDIuMDgyLjE4NS4xODUuMTg2bS0yLjkzIDBoMi4xMmEuMTg2LjE4NiAwIDAwLjE4NC0uMTg2VjYuMjlhLjE4NS4xODUgMCAwMC0uMTg1LS4xODVIOC4xYS4xODUuMTg1IDAgMDAtLjE4NS4xODV2MS44ODdjMCAuMTAyLjA4My4xODUuMTg1LjE4Nm0tMi45NjQgMGgyLjExOWEuMTg2LjE4NiAwIDAwLjE4NS0uMTg2VjYuMjlhLjE4NS4xODUgMCAwMC0uMTg1LS4xODVINS4xMzZhLjE4Ni4xODYgMCAwMC0uMTg2LjE4NXYxLjg4N2MwIC4xMDIuMDg0LjE4NS4xODYuMTg2bTUuODkzIDIuNzE1aDIuMTE4YS4xODYuMTg2IDAgMDAuMTg2LS4xODVWOS4wMDZhLjE4Ni4xODYgMCAwMC0uMTg2LS4xODZoLTIuMTE4YS4xODUuMTg1IDAgMDAtLjE4NS4xODV2MS44ODhjMCAuMTAyLjA4Mi4xODUuMTg1LjE4NW0tMi45MyAwaDIuMTJhLjE4NS4xODUgMCAwMC4xODQtLjE4NVY5LjAwNmEuMTg1LjE4NSAwIDAwLS4xODQtLjE4NmgtMi4xMmEuMTg1LjE4NSAwIDAwLS4xODQuMTg1djEuODg4YzAgLjEwMi4wODMuMTg1LjE4NS4xODVtLTIuOTY0IDBoMi4xMTlhLjE4NS4xODUgMCAwMC4xODUtLjE4NVY5LjAwNmEuMTg1LjE4NSAwIDAwLS4xODQtLjE4NmgtMi4xMmEuMTg2LjE4NiAwIDAwLS4xODYuMTg2djEuODg3YzAgLjEwMi4wODQuMTg1LjE4Ni4xODVtLTIuOTIgMGgyLjEyYS4xODUuMTg1IDAgMDAuMTg0LS4xODVWOS4wMDZhLjE4NS4xODUgMCAwMC0uMTg0LS4xODZoLTIuMTJhLjE4NS4xODUgMCAwMC0uMTg0LjE4NXYxLjg4OGMwIC4xMDIuMDgyLjE4NS4xODUuMTg1TTIzLjc2MyA5Ljg5Yy0uMDY1LS4wNTEtLjY3Mi0uNTEtMS45NTQtLjUxLS4zMzguMDAxLS42NzYuMDMtMS4wMS4wODctLjI0OC0xLjctMS42NTMtMi41My0xLjcxNi0yLjU2NmwtLjM0NC0uMTk5LS4yMjYuMzI3Yy0uMjg0LjQzOC0uNDkuOTIyLS42MTIgMS40My0uMjMuOTctLjA5IDEuODgyLjQwMyAyLjY2MS0uNTk1LjMzMi0xLjU1LjQxMy0xLjc0NC40MkguNzUxYS43NTEuNzUxIDAgMDAtLjc1Ljc0OCAxMS4zNzYgMTEuMzc2IDAgMDAuNjkyIDQuMDYyYy41NDUgMS40MjggMS4zNTUgMi40OCAyLjQxIDMuMTI0IDEuMTguNzIzIDMuMSAxLjEzNyA1LjI3NSAxLjEzNy45ODMuMDAzIDEuOTYzLS4wODYgMi45My0uMjY2YTEyLjI0OCAxMi4yNDggMCAwMDMuODIzLTEuMzg5Yy45OC0uNTY3IDEuODYtMS4yODggMi42MS0yLjEzNiAxLjI1Mi0xLjQxOCAxLjk5OC0yLjk5NyAyLjU1My00LjRoLjIyMWMxLjM3MiAwIDIuMjE1LS41NDkgMi42OC0xLjAwOS4zMDktLjI5My41NS0uNjUuNzA3LTEuMDQ2bC4wOTgtLjI4OFoiLz48L3N2Zz4="/><text aria-hidden="true" x="535" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="610">DockerHub</text><text x="535" y="140" transform="scale(.1)" fill="#fff" textLength="610">DockerHub</text><text aria-hidden="true" x="1455" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1070">Lissy93/Web Check</text><text x="1455" y="140" transform="scale(.1)" fill="#fff" textLength="1070">Lissy93/Web Check</text></g></svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="181" height="20" role="img" aria-label="GitHub: Lissy93/Web Check"><title>GitHub: Lissy93/Web Check</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="181" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="64" height="20" fill="#1c1d28"/><rect x="64" width="117" height="20" fill="#a832fc"/><rect width="181" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdpdEh1YjwvdGl0bGU+PHBhdGggZD0iTTEyIC4yOTdjLTYuNjMgMC0xMiA1LjM3My0xMiAxMiAwIDUuMzAzIDMuNDM4IDkuOCA4LjIwNSAxMS4zODUuNi4xMTMuODItLjI1OC44Mi0uNTc3IDAtLjI4NS0uMDEtMS4wNC0uMDE1LTIuMDQtMy4zMzguNzI0LTQuMDQyLTEuNjEtNC4wNDItMS42MUM0LjQyMiAxOC4wNyAzLjYzMyAxNy43IDMuNjMzIDE3LjdjLTEuMDg3LS43NDQuMDg0LS43MjkuMDg0LS43MjkgMS4yMDUuMDg0IDEuODM4IDEuMjM2IDEuODM4IDEuMjM2IDEuMDcgMS44MzUgMi44MDkgMS4zMDUgMy40OTUuOTk4LjEwOC0uNzc2LjQxNy0xLjMwNS43Ni0xLjYwNS0yLjY2NS0uMy01LjQ2Ni0xLjMzMi01LjQ2Ni01LjkzIDAtMS4zMS40NjUtMi4zOCAxLjIzNS0zLjIyLS4xMzUtLjMwMy0uNTQtMS41MjMuMTA1LTMuMTc2IDAgMCAxLjAwNS0uMzIyIDMuMyAxLjIzLjk2LS4yNjcgMS45OC0uMzk5IDMtLjQwNSAxLjAyLjAwNiAyLjA0LjEzOCAzIC40MDUgMi4yOC0xLjU1MiAzLjI4NS0xLjIzIDMuMjg1LTEuMjMuNjQ1IDEuNjUzLjI0IDIuODczLjEyIDMuMTc2Ljc2NS44NCAxLjIzIDEuOTEgMS4yMyAzLjIyIDAgNC42MS0yLjgwNSA1LjYyNS01LjQ3NSA1LjkyLjQyLjM2LjgxIDEuMDk2LjgxIDIuMjIgMCAxLjYwNi0uMDE1IDIuODk2LS4wMTUgMy4yODYgMCAuMzE1LjIxLjY5LjgyNS41N0MyMC41NjUgMjIuMDkyIDI0IDE3LjU5MiAyNCAxMi4yOTdjMC02LjYyNy01LjM3My0xMi0xMi0xMiIvPjwvc3ZnPg=="/><text aria-hidden="true" x="415" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">GitHub</text><text x="415" y="140" transform="scale(.1)" fill="#fff" textLength="370">GitHub</text><text aria-hidden="true" x="1215" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1070">Lissy93/Web Check</text><text x="1215" y="140" transform="scale(.1)" fill="#fff" textLength="1070">Lissy93/Web Check</text></g></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="147" height="20" role="img" aria-label="Sponsor: Alicia Sykes"><title>Sponsor: Alicia Sykes</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="147" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="72" height="20" fill="#1c1d28"/><rect x="72" width="75" height="20" fill="#f2159a"/><rect width="147" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdpdEh1YiBTcG9uc29yczwvdGl0bGU+PHBhdGggZD0iTTE3LjYyNSAxLjQ5OWMtMi4zMiAwLTQuMzU0IDEuMjAzLTUuNjI1IDMuMDMtMS4yNzEtMS44MjctMy4zMDUtMy4wMy01LjYyNS0zLjAzQzMuMTI5IDEuNDk5IDAgNC4yNTMgMCA4LjI0OWMwIDQuMjc1IDMuMDY4IDcuODQ3IDUuODI4IDEwLjIyN2EzMy4xNCAzMy4xNCAwIDAgMCA1LjYxNiAzLjg3NmwuMDI4LjAxNy4wMDguMDAzLS4wMDEuMDAzYy4xNjMuMDg1LjM0Mi4xMjYuNTIxLjEyNS4xNzkuMDAxLjM1OC0uMDQxLjUyMS0uMTI1bC0uMDAxLS4wMDMuMDA4LS4wMDMuMDI4LS4wMTdhMzMuMTQgMzMuMTQgMCAwIDAgNS42MTYtMy44NzZDMjAuOTMyIDE2LjA5NiAyNCAxMi41MjQgMjQgOC4yNDljMC0zLjk5Ni0zLjEyOS02Ljc1LTYuMzc1LTYuNzV6bS0uOTE5IDE1LjI3NWEzMC43NjYgMzAuNzY2IDAgMCAxLTQuNzAzIDMuMzE2bC0uMDA0LS4wMDItLjAwNC4wMDJhMzAuOTU1IDMwLjk1NSAwIDAgMS00LjcwMy0zLjMxNmMtMi42NzctMi4zMDctNS4wNDctNS4yOTgtNS4wNDctOC41MjMgMC0yLjc1NCAyLjEyMS00LjUgNC4xMjUtNC41IDIuMDYgMCAzLjkxNCAxLjQ3OSA0LjU0NCAzLjY4NC4xNDMuNDk1LjU5Ni43OTcgMS4wODYuNzk2LjQ5LjAwMS45NDMtLjMwMiAxLjA4NS0uNzk2LjYzLTIuMjA1IDIuNDg0LTMuNjg0IDQuNTQ0LTMuNjg0IDIuMDA0IDAgNC4xMjUgMS43NDYgNC4xMjUgNC41IDAgMy4yMjUtMi4zNyA2LjIxNi01LjA0OCA4LjUyM3oiLz48L3N2Zz4="/><text aria-hidden="true" x="455" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="450">Sponsor</text><text x="455" y="140" transform="scale(.1)" fill="#fff" textLength="450">Sponsor</text><text aria-hidden="true" x="1085" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="650">Alicia Sykes</text><text x="1085" y="140" transform="scale(.1)" fill="#fff" textLength="650">Alicia Sykes</text></g></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="155" height="20" role="img" aria-label="Website: web-check.zyz"><title>Website: web-check.zyz</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="155" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="70" height="20" fill="#1c1d28"/><rect x="70" width="85" height="20" fill="#9fef00"/><rect width="155" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdvb2dsZSBDbG91ZCBTdG9yYWdlPC90aXRsZT48cGF0aCBkPSJNMjQgMi40djguNGgtMi40VjIuNEgyNHpNMCAxMC44aDIuNFYyLjRIMHY4LjR6bTMtOC40aDE4djguNEgzVjIuNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwem0tMTAuOC42SDEyVjZINC44djEuMnptMTYuOCAxNC40SDI0di04LjRoLTIuNHY4LjR6TTAgMjEuNmgyLjR2LTguNEgwdjguNHptMy04LjRoMTh2OC40SDN2LTguNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwek00LjggMThIMTJ2LTEuMkg0LjhWMTh6Ii8+PC9zdmc+"/><text aria-hidden="true" x="445" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Website</text><text x="445" y="140" transform="scale(.1)" fill="#fff" textLength="430">Website</text><text aria-hidden="true" x="1115" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="750">web-check.zyz</text><text x="1115" y="140" transform="scale(.1)" fill="#333" textLength="750">webcheck.zyz</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,9 +0,0 @@
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="a" patternUnits="userSpaceOnUse" width="30" height="30">
<rect width="100%" height="100%" fill="var(--background, #111211)" />
<circle cx="5" cy="5" r="1.75" fill="var(--background-lighter, #3A3B3A)" opacity="0.3" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#a)" />
</svg>

Before

Width:  |  Height:  |  Size: 408 B

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Docker</title><path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>

Before

Width:  |  Height:  |  Size: 823 B

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Netlify</title><path d="M6.49 19.04h-.23L5.13 17.9v-.23l1.73-1.71h1.2l.15.15v1.2L6.5 19.04ZM5.13 6.31V6.1l1.13-1.13h.23L8.2 6.68v1.2l-.15.15h-1.2L5.13 6.31Zm9.96 9.09h-1.65l-.14-.13v-3.83c0-.68-.27-1.2-1.1-1.23-.42 0-.9 0-1.43.02l-.07.08v4.96l-.14.14H8.9l-.13-.14V8.73l.13-.14h3.7a2.6 2.6 0 0 1 2.61 2.6v4.08l-.13.14Zm-8.37-2.44H.14L0 12.82v-1.64l.14-.14h6.58l.14.14v1.64l-.14.14Zm17.14 0h-6.58l-.14-.14v-1.64l.14-.14h6.58l.14.14v1.64l-.14.14ZM11.05 6.55V1.64l.14-.14h1.65l.14.14v4.9l-.14.14h-1.65l-.14-.13Zm0 15.81v-4.9l.14-.14h1.65l.14.13v4.91l-.14.14h-1.65l-.14-.14Z"/></svg>

Before

Width:  |  Height:  |  Size: 657 B

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Swagger</title><path d="M12 0C5.383 0 0 5.383 0 12s5.383 12 12 12c6.616 0 12-5.383 12-12S18.616 0 12 0zm0 1.144c5.995 0 10.856 4.86 10.856 10.856 0 5.995-4.86 10.856-10.856 10.856-5.996 0-10.856-4.86-10.856-10.856C1.144 6.004 6.004 1.144 12 1.144zM8.37 5.868a6.707 6.707 0 0 0-.423.005c-.983.056-1.573.517-1.735 1.472-.115.665-.096 1.348-.143 2.017-.013.35-.05.697-.115 1.038-.134.609-.397.798-1.016.83a2.65 2.65 0 0 0-.244.042v1.463c1.126.055 1.278.452 1.37 1.629.033.429-.013.858.015 1.287.018.406.073.808.156 1.2.259 1.075 1.307 1.435 2.575 1.218v-1.283c-.203 0-.383.005-.558 0-.43-.013-.591-.12-.632-.535-.056-.535-.042-1.08-.075-1.62-.064-1.001-.175-1.988-1.153-2.625.503-.37.868-.812.983-1.398.083-.41.134-.821.166-1.237.028-.415-.023-.84.014-1.25.06-.665.102-.937.9-.91.12 0 .235-.017.369-.027v-1.31c-.16 0-.31-.004-.454-.006zm7.593.009a4.247 4.247 0 0 0-.813.06v1.274c.245 0 .434 0 .623.005.328.004.577.13.61.494.032.332.031.669.064 1.006.065.669.101 1.347.217 2.007.102.544.475.95.941 1.283-.817.549-1.057 1.333-1.098 2.215-.023.604-.037 1.213-.069 1.822-.028.554-.222.734-.78.748-.157.004-.31.018-.484.028v1.305c.327 0 .627.019.927 0 .932-.055 1.495-.507 1.68-1.412.078-.498.124-1 .138-1.504.032-.461.028-.927.074-1.384.069-.715.397-1.01 1.112-1.057a.972.972 0 0 0 .199-.046v-1.463c-.12-.014-.204-.027-.291-.032-.536-.023-.804-.203-.937-.71a5.146 5.146 0 0 1-.152-.993c-.037-.618-.033-1.241-.074-1.86-.08-1.192-.794-1.753-1.887-1.786zm-6.89 5.28a.844.844 0 0 0-.083 1.684h.055a.83.83 0 0 0 .877-.78v-.046a.845.845 0 0 0-.83-.858zm2.911 0a.808.808 0 0 0-.834.78c0 .027 0 .05.004.078 0 .503.342.826.859.826.507 0 .826-.332.826-.853-.005-.503-.342-.836-.855-.831zm2.963 0a.861.861 0 0 0-.876.835c0 .47.378.849.849.849h.009c.425.074.853-.337.881-.83.023-.457-.392-.854-.863-.854z"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Vercel</title><path d="M24 22.525H0l12-21.05 12 21.05z"/></svg>

Before

Width:  |  Height:  |  Size: 142 B

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>WebAuthn</title><path d="M15.2872 3.641a8.407 8.407 0 00-8.05 7.593h.55a7.805 7.805 0 012.24-4.713 5.825 5.825 0 00.923.695c-.608 1.177-.98 2.556-1.082 4.018h.135c.105-1.467.485-2.819 1.065-3.947.745.434 1.623.754 2.577.94a27.83 27.83 0 00-.25 3.763h-.847v.135h.847c.003 1.334.09 2.617.25 3.764-.954.185-1.832.506-2.577.94a9.997 9.997 0 01-.978-3.137h-.137c.164 1.16.502 2.25.997 3.208a5.825 5.825 0 00-.924.695 7.805 7.805 0 01-2.255-4.875h-.55a8.407 8.407 0 0016.779-.675 8.398 8.398 0 00-.689-3.333 8.407 8.407 0 00-8.025-5.072zm.315.546c.155 0 .31.005.464.014.365.34.708 1.07.983 2.114a16.518 16.518 0 01.357 1.79 10.173 10.173 0 01-1.804.16 10.173 10.173 0 01-1.805-.16 16.519 16.519 0 01.357-1.79c.275-1.045.618-1.775.983-2.114a7.97 7.97 0 01.465-.014zm-.665.028c-.345.392-.658 1.093-.913 2.065a16.639 16.639 0 00-.36 1.8c-.939-.183-1.802-.498-2.533-.926.686-1.283 1.635-2.264 2.73-2.775a7.874 7.874 0 011.076-.164zm1.33 0a7.856 7.856 0 011.084.168c1.092.513 2.037 1.492 2.721 2.771-.73.428-1.594.743-2.533.927a16.64 16.64 0 00-.36-1.8c-.255-.972-.568-1.673-.912-2.066zm-2.972.314c-.655.407-1.257.989-1.776 1.73a8.166 8.166 0 00-.506.825 5.69 5.69 0 01-.89-.67 7.814 7.814 0 013.172-1.885zm4.624.006a7.862 7.862 0 013.164 1.877 5.692 5.692 0 01-.893.672 8.166 8.166 0 00-.506-.825c-.516-.738-1.115-1.318-1.765-1.724zm3.26 1.985a7.858 7.858 0 011.638 2.419 7.802 7.802 0 01.642 3.051h-2.095c-.01-1.74-.398-3.396-1.11-4.774a5.823 5.823 0 00.925-.696zm-1.044.767c.68 1.32 1.084 2.945 1.094 4.703h-3.42a27.863 27.863 0 00-.25-3.763c.953-.186 1.832-.506 2.576-.94zm-6.357.965a10.299 10.299 0 001.824.16 10.299 10.299 0 001.823-.16c.16 1.138.246 2.413.25 3.738h-1.179a1.03 1.03 0 01-.093.135h1.27a27.71 27.71 0 01-.248 3.739 10.397 10.397 0 00-3.647 0 27.733 27.733 0 01-.248-3.739h1.294a.99.99 0 01-.09-.135h-1.204c.003-1.325.088-2.6.248-3.738zm-11.22 1.129a2.585 2.585 0 00-2.547 2.35c-.142 1.541 1.064 2.842 2.566 2.842 1.26 0 2.312-.917 2.533-2.124h4.44v.972h.946v-.972h.837v1.431h.945v-2.376h-7.168a2.586 2.586 0 00-2.552-2.123zm-.058.965a1.639 1.639 0 011.707 1.637 1.64 1.64 0 01-1.639 1.638 1.639 1.639 0 01-.068-3.275zm13.09.388a.75.75 0 00-.345 1.404l-.383 1.958h1.5l-.383-1.958a.75.75 0 00.384-.654.75.75 0 00-.773-.75zm2.218 1.391h3.421c-.01 1.758-.415 3.384-1.094 4.704-.744-.434-1.623-.755-2.577-.94a27.81 27.81 0 00.25-3.764zm3.556 0h2.095a7.805 7.805 0 01-2.28 5.47 5.825 5.825 0 00-.925-.696c.712-1.378 1.1-3.033 1.11-4.774zm-5.52 3.703a10.284 10.284 0 011.562.156 16.518 16.518 0 01-.357 1.791c-.275 1.045-.618 1.774-.982 2.114a7.972 7.972 0 01-.93 0c-.365-.34-.708-1.07-.983-2.114a16.519 16.519 0 01-.357-1.79 10.284 10.284 0 012.048-.157zm1.695.181c.94.184 1.803.5 2.533.926-.686 1.284-1.635 2.265-2.73 2.776a7.874 7.874 0 01-1.075.164c.344-.393.657-1.094.913-2.065a16.64 16.64 0 00.36-1.8zm-3.874 0a16.648 16.648 0 00.36 1.8c.254.973.567 1.674.912 2.066a7.873 7.873 0 01-1.075-.164c-1.096-.511-2.045-1.492-2.73-2.775.73-.428 1.593-.743 2.533-.927zm-2.652.997a8.16 8.16 0 00.506.825c.52.741 1.121 1.323 1.776 1.73a7.814 7.814 0 01-3.174-1.884 5.694 5.694 0 01.892-.67zm9.178 0a5.694 5.694 0 01.891.67 7.814 7.814 0 01-3.173 1.885c.654-.407 1.256-.989 1.775-1.73a8.16 8.16 0 00.507-.825z"/></svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,39 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web-Check</title>
</head>
<body>
<section>
<a class="t" href="/"><h1><img src="https://i.ibb.co/q1gZN2p/web-check-logo.png" width="48" />Web-Check</h1></a>
<p class="moji">😪</p>
<p>There was an error finding this route.</p>
<span>Docs and Source: <a href="https://github.com/lissy93/web-check">github.com/lissy93/web-check</a></span>
</section>
<style>
body { background: #141d2b; color: #fff; }
h1 {
color: #9fef00; text-shadow: #0f1620 2px 2px 0px;
font-size: 3rem; margin: 1rem auto; flex-wrap: wrap;
display: flex; align-items: flex-start; gap: 1rem;
}
section {
display: flex; flex-direction: column; align-items: center; margin: 1rem; gap: 0.5rem;
background: #1a2332; box-shadow: #0f1620 4px 4px 0px; border-radius: 8px; padding: 1rem;
max-width: 800px; margin: 1rem auto;
}
p { font-size: 1.2rem; }
a { color: #9fef00; font-family: monospace; }
a.t { text-decoration: none; margin: 0;}
span { opacity: 0.8; font-size: 0.85rem; }
h1 {
font-family: PTMono, Ubuntu, Fira Sans, Helvetica, sans-serif;
}
p, span, a, section, div { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; }
code { color: #9fef00cc;}
.moji { font-size: 8rem; margin: 0; }
</style>
</body>
</html>

View File

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="8.424 15.685618729096989 38.844 37.92642140468227" style="max-height: 500px" width="38.844" height="37.92642140468227">
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="2.8" stroke="white" d="M43.3 30.1V20.3C43.3 19.9287 43.1525 19.5726 42.89 19.31C42.6274 19.0475 42.2713 18.9 41.9 18.9H13.9C13.5287 18.9 13.1726 19.0475 12.9101 19.31C12.6475 19.5726 12.5 19.9287 12.5 20.3V30.1C12.5 46.9 27.9 51.1 27.9 51.1C27.9 51.1 43.3 46.9 43.3 30.1Z"/>
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="2.8" stroke="#D6FB41" d="M20.8999 34.3L25.0999 38.5L34.8999 28.7"/>
<path fill="white" d="M60.07 45.5L55.78 23.63H61.6L63.76 37.82L64.12 40.28H64.36L67.66 23.63H73.7801L77.08 40.28H77.35L77.62 38.21L79.7801 23.63H85.63L81.4001 45.5H73.72L71.1701 33.05L70.84 31.22H70.63L70.3 33.05L67.72 45.5H60.07ZM94.42 45.8C92.58 45.8 91.05 45.45 89.83 44.75C88.63 44.05 87.72 43.08 87.1 41.84C86.5 40.58 86.2 39.12 86.2 37.46V37.13C86.2 35.39 86.53 33.91 87.19 32.69C87.85 31.47 88.76 30.54 89.92 29.9C91.1 29.26 92.45 28.94 93.97 28.94C95.67 28.94 97.11 29.26 98.29 29.9C99.49 30.52 100.4 31.4 101.02 32.54C101.64 33.68 101.95 35 101.95 36.5V38.72H91.57V39.47C91.57 40.17 91.82 40.74 92.32 41.18C92.82 41.6 93.46 41.81 94.24 41.81C94.94 41.81 95.51 41.67 95.95 41.39C96.39 41.09 96.65 40.7 96.73 40.22H101.77C101.71 41.34 101.36 42.32 100.72 43.16C100.08 43.98 99.22 44.63 98.14 45.11C97.06 45.57 95.82 45.8 94.42 45.8ZM91.57 35.36V35.51H96.73V35.36C96.73 34.5 96.49 33.87 96.01 33.47C95.55 33.05 94.93 32.84 94.15 32.84C93.39 32.84 92.77 33.06 92.29 33.5C91.81 33.92 91.57 34.54 91.57 35.36ZM114.879 45.8C113.859 45.8 112.929 45.58 112.089 45.14C111.269 44.7 110.659 44.08 110.259 43.28H110.019L109.719 45.5H104.709V23.63H110.019V31.49H110.259C110.659 30.69 111.269 30.07 112.089 29.63C112.929 29.17 113.859 28.94 114.879 28.94C116.359 28.94 117.549 29.28 118.449 29.96C119.349 30.62 120.009 31.55 120.429 32.75C120.849 33.95 121.059 35.36 121.059 36.98V37.76C121.059 40.62 120.499 42.68 119.379 43.94C118.259 45.18 116.759 45.8 114.879 45.8ZM112.719 41.51C113.579 41.51 114.239 41.27 114.699 40.79C115.179 40.29 115.419 39.6 115.419 38.72V36.05C115.419 35.17 115.179 34.48 114.699 33.98C114.239 33.48 113.579 33.23 112.719 33.23C111.899 33.23 111.249 33.48 110.769 33.98C110.289 34.46 110.049 35.15 110.049 36.05V38.69C110.049 39.61 110.289 40.31 110.769 40.79C111.249 41.27 111.899 41.51 112.719 41.51Z"/>
<path fill="#D6FB41" d="M133.77 45.8C131.61 45.8 129.77 45.41 128.25 44.63C126.73 43.83 125.56 42.71 124.74 41.27C123.94 39.83 123.54 38.15 123.54 36.23V35.96C123.54 33.38 123.99 31.15 124.89 29.27C125.79 27.37 127.1 25.91 128.82 24.89C130.54 23.85 132.61 23.33 135.03 23.33C136.99 23.33 138.71 23.67 140.19 24.35C141.67 25.01 142.83 25.94 143.67 27.14C144.51 28.34 144.96 29.75 145.02 31.37H139.17C139.05 30.41 138.59 29.64 137.79 29.06C137.01 28.48 136.02 28.19 134.82 28.19C133.4 28.19 132.27 28.52 131.43 29.18C130.59 29.82 130.05 30.83 129.81 32.21L129.24 35.36C128.94 37.1 129.21 38.47 130.05 39.47C130.89 40.45 132.13 40.94 133.77 40.94C134.99 40.94 135.97 40.69 136.71 40.19C137.47 39.67 137.97 38.97 138.21 38.09H144C143.7 39.73 143.08 41.13 142.14 42.29C141.2 43.43 140.01 44.3 138.57 44.9C137.13 45.5 135.53 45.8 133.77 45.8ZM145.633 45.5L149.503 23.63H154.873L153.553 31.19H153.883C154.343 30.49 154.973 29.95 155.773 29.57C156.593 29.17 157.463 28.97 158.383 28.97C160.283 28.97 161.693 29.62 162.613 30.92C163.553 32.2 163.813 34.02 163.393 36.38L161.773 45.5H156.373L157.963 36.47C158.163 35.41 158.063 34.6 157.663 34.04C157.263 33.48 156.603 33.2 155.683 33.2C154.843 33.2 154.173 33.47 153.673 34.01C153.173 34.53 152.843 35.22 152.683 36.08L151.063 45.5H145.633ZM173.599 45.8C171.219 45.8 169.339 45.14 167.959 43.82C166.599 42.5 165.919 40.67 165.919 38.33V38.09C165.919 36.25 166.249 34.65 166.909 33.29C167.569 31.91 168.539 30.85 169.819 30.11C171.099 29.35 172.639 28.97 174.439 28.97C176.179 28.97 177.649 29.32 178.849 30.02C180.069 30.7 180.949 31.67 181.489 32.93C182.049 34.17 182.209 35.63 181.969 37.31L181.759 38.72H171.049C171.049 38.78 171.039 38.85 171.019 38.93C171.019 38.99 171.019 39.06 171.019 39.14C170.899 39.94 171.099 40.59 171.619 41.09C172.139 41.57 172.849 41.81 173.749 41.81C174.429 41.81 174.999 41.68 175.459 41.42C175.939 41.16 176.259 40.78 176.419 40.28H181.489C181.209 41.98 180.379 43.33 178.999 44.33C177.619 45.31 175.819 45.8 173.599 45.8ZM171.679 35.21L171.619 35.51H176.989C177.049 34.63 176.849 33.97 176.389 33.53C175.949 33.07 175.299 32.84 174.439 32.84C173.579 32.84 172.929 33.07 172.489 33.53C172.049 33.97 171.779 34.53 171.679 35.21ZM191.498 45.8C189.098 45.8 187.218 45.14 185.858 43.82C184.518 42.5 183.848 40.75 183.848 38.57V38.33C183.848 36.43 184.178 34.78 184.838 33.38C185.518 31.98 186.488 30.9 187.748 30.14C189.028 29.36 190.568 28.97 192.368 28.97C194.648 28.97 196.478 29.55 197.858 30.71C199.258 31.87 199.988 33.44 200.048 35.42H194.918C194.878 34.68 194.618 34.14 194.138 33.8C193.678 33.46 193.088 33.29 192.368 33.29C191.528 33.29 190.878 33.51 190.418 33.95C189.958 34.37 189.668 34.97 189.548 35.75L189.158 38.15C188.978 39.21 189.118 40.03 189.578 40.61C190.038 41.19 190.738 41.48 191.678 41.48C192.378 41.48 192.958 41.3 193.418 40.94C193.878 40.58 194.178 40.1 194.318 39.5H199.478C199.398 40.76 199.008 41.86 198.308 42.8C197.628 43.74 196.708 44.48 195.548 45.02C194.388 45.54 193.038 45.8 191.498 45.8ZM201.092 45.5L204.932 23.63H210.332L208.232 35.42L214.622 29.27H221.222L214.052 35.69L218.402 45.5H212.552L209.852 38.96L207.212 41.27L206.462 45.5H201.092Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -1,93 +0,0 @@
Copyright (c) 2022, GitHub https://github.com/github/hubot-sans
with Reserved Font Name "Hubot Sans"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting — in part or in whole — any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Some files were not shown because too many files have changed in this diff Show More