first commit
This commit is contained in:
commit
93af5dc4ba
177
.gitignore
vendored
Normal file
177
.gitignore
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
|
||||
# Logs
|
||||
|
||||
logs
|
||||
_.log
|
||||
npm-debug.log_
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Caches
|
||||
|
||||
.cache
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# Runtime data
|
||||
|
||||
pids
|
||||
_.pid
|
||||
_.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
|
||||
testing/domains.txt
|
462
LICENSE
Normal file
462
LICENSE
Normal file
@ -0,0 +1,462 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Deblok Copyright (C) 2024 Deblok
|
||||
This program comes with ABSOLUTELY NO WARRANTY!
|
||||
|
104
README.md
Normal file
104
README.md
Normal file
@ -0,0 +1,104 @@
|
||||
<img align="right" src="readme/preview.png" height="270px"></img>
|
||||
# FilterChecker V2
|
||||
The most powerful unblocked link checker, supporting these filters:
|
||||
* Lightspeed Systems
|
||||
* Palo Alto Systems
|
||||
* FortiGuard
|
||||
|
||||
<br>
|
||||
|
||||
Also comes with **many** QoL (quality of life) features, including:
|
||||
* Ability to be used as a User App for even better convenience
|
||||
* Built-In API that can be enabled (pass `--web <port>`, default port is 10000)
|
||||
* Check all filters, or just a single filter
|
||||
* Made in TypeScript, not Python, so therefore type friendly
|
||||
* Showing results ephemerally is now an option
|
||||
* More detailed and user-friendly outputs
|
||||
|
||||
## Setup
|
||||
Setting up FilterChecker V2 is as easy as pie! <br >
|
||||
Assuming you already cloned the repo, and installed [Bun](https://bun.sh):
|
||||
1. Install packages using `bun i`
|
||||
2. Put your bot token in your `.env` file, use `example.env` as an example
|
||||
3. Start the bot with `bun run start`, if you wish to run the API alongside, you can turn your command into `bun run start --web`, and if you want to specify a custom port, `bun run start --web 8080`
|
||||
|
||||
## API Docs
|
||||
**GET** `/` or `/ping`: Healthcheck, should always respond with `OK`.
|
||||
|
||||
----
|
||||
|
||||
**GET/POST** `/check/[url]/results.txt`:
|
||||
* If a GET request was made, it will show a FilterChecker report of all filters
|
||||
* If a POST reqest was made, you'll have an option to specify what filter in a JSON format, the options are:
|
||||
* `lightspeed` or `ls` for Lightspeed
|
||||
* `fortiguard` or `forti` for FortiGuard
|
||||
* `palo` or `paloalto` for Palo Alto
|
||||
|
||||
**POST** request example:
|
||||
`{"filter":"lightspeed"}` <br>
|
||||
**POST** request example response:
|
||||
```
|
||||
FilterChecker Report for youtu.be:
|
||||
|
||||
Lightspeed:
|
||||
LS Filter: education.videos
|
||||
LS Rocket: education.videos
|
||||
|
||||
```
|
||||
|
||||
**GET** request example response:
|
||||
```
|
||||
FilterChecker Report for youtu.be:
|
||||
|
||||
FortiGuard:
|
||||
Category: Streaming Media and Download
|
||||
|
||||
Lightspeed:
|
||||
LS Filter: education.videos
|
||||
LS Rocket: education.videos
|
||||
|
||||
Palo Alto:
|
||||
Risk: Low-Risk
|
||||
Category: Streaming-Media
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
**GET/POST** `/check/[url]/results.json`:
|
||||
* If a GET request was made, it will show a FilterChecker report of all filters in a JSON format.
|
||||
|
||||
* If a POST reqest was made, you'll have an option to specify what filter in a JSON format, the options are:
|
||||
* `lightspeed` or `ls` for Lightspeed
|
||||
* `fortiguard` or `forti` for FortiGuard
|
||||
* `palo` or `paloalto` for Palo Alto
|
||||
|
||||
**POST** request example:
|
||||
`{"filter":"lightspeed"}` <br>
|
||||
**POST** request example response:
|
||||
```json
|
||||
{
|
||||
"lightspeed": [
|
||||
"education.videos",
|
||||
"education.videos"
|
||||
]
|
||||
}
|
||||
```
|
||||
**GET** request example response:
|
||||
```json
|
||||
{
|
||||
"fortiguard": "Streaming Media and Download",
|
||||
"lightspeed": [
|
||||
"education.videos",
|
||||
"education.videos"
|
||||
],
|
||||
"paloalto": [
|
||||
"Streaming-Media",
|
||||
"Low-Risk"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
----
|
||||
<img src="readme/lyrth.png" width="720px">
|
||||
<br><br>
|
||||
<i>FilterChecker V2 is licensed under the Lesser GNU Public License version 2.1.</i>
|
2
example.env
Normal file
2
example.env
Normal file
@ -0,0 +1,2 @@
|
||||
# THIS IS THE EXAMPLE.ENV FILE
|
||||
BOT_TOKEN=MTE4N...
|
302
index.html
Normal file
302
index.html
Normal file
@ -0,0 +1,302 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>FilterChecker</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #333 /*#2b2b2b*/;
|
||||
color: #f5f5f5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#container {
|
||||
background: #333;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
/*box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);*/
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.input-group {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
input {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
background-color: #555;
|
||||
color: #f5f5f5;
|
||||
box-sizing: border-box;
|
||||
transition: border-radius 0.1s;
|
||||
}
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
background-color: #28a745;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
margin-left: 10px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
#results {
|
||||
text-align: left;
|
||||
}
|
||||
.result {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #444;
|
||||
}
|
||||
.loading-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100px;
|
||||
}
|
||||
.spinner {
|
||||
border: 4px solid rgba(255, 255, 255, 0.3);
|
||||
border-top: 4px solid #fff;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
#rawResultContainer {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.raw-button {
|
||||
padding: 10px 20px;
|
||||
background-color: #28a745;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.raw-button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
.error {
|
||||
color: #ff4d4d;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
background-color: #333;
|
||||
}
|
||||
#container {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
padding: 10px;
|
||||
}
|
||||
.input-group {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
input {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
button {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<h1>FilterChecker</h1>
|
||||
<div class="input-group">
|
||||
<input type="text" id="inputUrl" placeholder="URL to check..." onkeypress="handleKeyPress(event)" />
|
||||
<button onclick="checkFilter()">Check</button>
|
||||
</div>
|
||||
<div id="results"></div>
|
||||
<div id="rawResultContainer"></div>
|
||||
<div id="loading" class="loading-container" style="display: none;">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const domain = urlParams.get('domain');
|
||||
if (domain) {
|
||||
document.getElementById('inputUrl').value = domain;
|
||||
checkFilter();
|
||||
}
|
||||
});
|
||||
|
||||
function handleKeyPress(event) {
|
||||
if (event.key === 'Enter') {
|
||||
checkFilter();
|
||||
}
|
||||
}
|
||||
|
||||
function isValidDomain(domain) {
|
||||
const regex = /^(?!:\/\/)([a-zA-Z0-9-_]+\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\.[a-zA-Z]{2,11}?$/;
|
||||
return regex.test(domain);
|
||||
}
|
||||
|
||||
const filterMapping = {
|
||||
"lightspeed": "lightspeed",
|
||||
"ls": "lightspeed",
|
||||
"fortiguard": "fortiguard",
|
||||
"forti": "fortiguard",
|
||||
"paloalto": "paloalto",
|
||||
"palo": "paloalto"
|
||||
};
|
||||
|
||||
async function checkFilter() {
|
||||
let url = document.getElementById('inputUrl').value.trim();
|
||||
const resultsDiv = document.getElementById('results');
|
||||
const rawResultContainer = document.getElementById('rawResultContainer');
|
||||
const loadingDiv = document.getElementById('loading');
|
||||
resultsDiv.innerHTML = '';
|
||||
rawResultContainer.innerHTML = '';
|
||||
loadingDiv.style.display = 'flex';
|
||||
|
||||
url = url.replace(/^https?:\/\//, '');
|
||||
|
||||
if (!url) {
|
||||
resultsDiv.innerHTML = '<p class="error">Please enter a URL.</p>';
|
||||
loadingDiv.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidDomain(url)) {
|
||||
resultsDiv.innerHTML = '<p class="error">Please enter a valid domain.</p>';
|
||||
loadingDiv.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const encodedUrl = encodeURIComponent(url);
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const filter = urlParams.get('filter');
|
||||
|
||||
const jsonResponse = await fetch(`api/check/${encodedUrl}/results.json`);
|
||||
if (!jsonResponse.ok) {
|
||||
const errorText = await jsonResponse.text();
|
||||
console.error(`Error text: ${errorText}`);
|
||||
throw new Error(`Network response for JSON was not ok: ${errorText}`);
|
||||
}
|
||||
const dataJson = await jsonResponse.json();
|
||||
|
||||
const textResponse = await fetch(`api/check/${encodedUrl}/results.txt`);
|
||||
if (!textResponse.ok) {
|
||||
const errorText = await textResponse.text();
|
||||
console.error(`Error text: ${errorText}`);
|
||||
throw new Error(`Network response for TXT was not ok: ${errorText}`);
|
||||
}
|
||||
let dataTxt = await textResponse.text();
|
||||
|
||||
if (filter) {
|
||||
const normalizedFilter = filterMapping[filter.toLowerCase()];
|
||||
if (normalizedFilter) {
|
||||
const filteredData = { [normalizedFilter]: dataJson[normalizedFilter] };
|
||||
dataTxt = JSON.stringify(filteredData, null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
const blob = new Blob([dataTxt], { type: 'text/plain' });
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
|
||||
displayResults(dataJson, url, filter);
|
||||
|
||||
const rawButton = document.createElement('button');
|
||||
rawButton.innerText = 'Show Raw';
|
||||
rawButton.className = 'raw-button';
|
||||
rawButton.onclick = () => {
|
||||
window.open(blobUrl, '_blank');
|
||||
};
|
||||
rawResultContainer.appendChild(rawButton);
|
||||
|
||||
} catch (error) {
|
||||
resultsDiv.innerHTML = `<p class="error">Error: ${error.message}</p>`;
|
||||
} finally {
|
||||
loadingDiv.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function displayResults(data, url, filter) {
|
||||
const resultsDiv = document.getElementById('results');
|
||||
resultsDiv.innerHTML = `<h2>FilterChecker Report for ${url}:</h2>`;
|
||||
|
||||
if (!data || typeof data !== 'object') {
|
||||
resultsDiv.innerHTML = '<p class="error">No filters found.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedFilter = filter ? filterMapping[filter.toLowerCase()] : null;
|
||||
|
||||
if (normalizedFilter) {
|
||||
if (data[normalizedFilter]) {
|
||||
const resultContent = generateFilterContent(normalizedFilter, data[normalizedFilter]);
|
||||
resultsDiv.innerHTML += `
|
||||
<div class="result">
|
||||
${resultContent}
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
resultsDiv.innerHTML = `<p class="error">Filter ${filter} not found.</p>`;
|
||||
}
|
||||
} else {
|
||||
for (const key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
const resultContent = generateFilterContent(key, data[key]);
|
||||
resultsDiv.innerHTML += `
|
||||
<div class="result">
|
||||
${resultContent}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateFilterContent(filterName, filterData) {
|
||||
let content = `<p><strong>${(filterName.charAt(0).toUpperCase() + filterName.slice(1)).replace('Paloalto', 'Palo Alto')}:</strong></p>`;
|
||||
|
||||
if (filterName === "lightspeed") {
|
||||
content += `<p>LS Filter: ${filterData[0]}</p>`;
|
||||
content += `<p>LS Rocket: ${filterData[1]}</p>`;
|
||||
} else if (filterName === "fortiguard") {
|
||||
content += `<p>Category: ${filterData}</p>`;
|
||||
} else if (filterName === "paloalto") {
|
||||
content += `<p>Risk: ${filterData[1]}</p>`;
|
||||
content += `<p>Category: ${filterData[0]}</p>`;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
20
package.json
Normal file
20
package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "filtercheckerv2",
|
||||
"module": "src/index.ts",
|
||||
"scripts": {
|
||||
"start": "bun run src/index.ts"
|
||||
},
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"elysia": "^1.0.16",
|
||||
"ip-range-check": "^0.2.0",
|
||||
"seyfert": "^1.3.3"
|
||||
}
|
||||
}
|
BIN
readme/lyrth.png
Normal file
BIN
readme/lyrth.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 229 KiB |
BIN
readme/preview.png
Normal file
BIN
readme/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
6
renovate.json
Normal file
6
renovate.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended"
|
||||
]
|
||||
}
|
13
seyfert.config.ts
Normal file
13
seyfert.config.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// @ts-check is better
|
||||
const { config } = require('seyfert');
|
||||
|
||||
module.exports = config.bot({
|
||||
token: process.env.BOT_TOKEN ?? "",
|
||||
intents: ["Guilds"],
|
||||
locations: {
|
||||
base: "src",
|
||||
output: "src", //If you are using bun, set "src" instead
|
||||
commands: "commands",
|
||||
events: "events"
|
||||
}
|
||||
});
|
87
src/commands/check.ts
Normal file
87
src/commands/check.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { Declare, Command, type CommandContext, Options,
|
||||
createStringOption, Embed,
|
||||
createBooleanOption} from 'seyfert';
|
||||
import { MessageFlags } from 'seyfert/lib/types';
|
||||
import filters from "../modules/filters"
|
||||
@Options(
|
||||
{
|
||||
url: createStringOption({
|
||||
required:true,
|
||||
description: "The URL to check",
|
||||
}),
|
||||
filter: createStringOption({
|
||||
required:false,
|
||||
|
||||
description: "The filter to check through",
|
||||
choices: [
|
||||
{ name: 'All', value: 'all' },
|
||||
{ name: 'FortiGuard', value: 'fortiguard' },
|
||||
{ name: 'Palo Alto Systems', value: 'palo' },
|
||||
{ name: 'Lightspeed', value: 'lightspeed' }
|
||||
]
|
||||
}),
|
||||
show: createBooleanOption({
|
||||
required:false,
|
||||
description: "Show the results non-ephemerally",
|
||||
}),
|
||||
}
|
||||
)
|
||||
@Declare({
|
||||
name: 'check',
|
||||
description: 'Check a link against various filters',
|
||||
contexts: ['BOT_DM', 'GUILD', 'PRIVATE_CHANNEL'],
|
||||
integrationTypes: ['GUILD_INSTALL', 'USER_INSTALL']
|
||||
})
|
||||
export default class FilterCheckCommand extends Command {
|
||||
|
||||
async run(ctx: CommandContext) {
|
||||
const re = new RegExp("^(?:https?:\/\/)?(?:www\.)?([^\/]+)");
|
||||
// @ts-ignore
|
||||
let url = re.exec(ctx.options.url)[1];
|
||||
|
||||
const embed = new Embed();
|
||||
embed.setColor('Green')
|
||||
embed.setTitle(`Results for ${url}:`)
|
||||
embed.setDescription("Loading...")
|
||||
await ctx.editOrReply({
|
||||
embeds:[embed],
|
||||
// @ts-ignore
|
||||
flags:ctx.options.show ? undefined : MessageFlags.Ephemeral
|
||||
});
|
||||
embed.setDescription("")
|
||||
embed.setColor('Blue')
|
||||
|
||||
// @ts-ignore
|
||||
if (!ctx.options.filter || ctx.options.filter == "all") {
|
||||
|
||||
let results = [await filters.fortiguard(url),await filters.lightspeed(url),await filters.palo(url)]
|
||||
let formatted = ["Category: " + results[0],`LS Filter: ${results[1][0]}\nLS Rocket: ${results[1][1]}`,`Risk: ${results[2][1]}\nCategory: ${results[2][0].trim().replace(/^\s*$(?:\r\n?|\n)/gm,"")}`]
|
||||
embed.addFields({name:"FortiGuard",value:formatted[0]},{name:"Lightspeed",value:formatted[1]},{name:"Palo Alto",value:formatted[2]})
|
||||
} else {
|
||||
let results;
|
||||
// @ts-ignore
|
||||
switch (ctx.options.filter) {
|
||||
case "palo":
|
||||
results = await filters.palo(url);
|
||||
embed.addFields({name:"Palo Alto",value:`Risk: ${results[1]}\nCategory: ${results[0].trim().replace(/^\s*$(?:\r\n?|\n)/gm,"")}`})
|
||||
break;
|
||||
case "lightspeed":
|
||||
results = await filters.lightspeed(url);
|
||||
embed.addFields({name:"Lightspeed",value:`LS Filter: ${results[0]}\nLS Rocket: ${results[1]}`})
|
||||
break;
|
||||
case "fortiguard":
|
||||
results = await filters.fortiguard(url);
|
||||
embed.addFields({name:"FortiGuard",value:"Category: " + results})
|
||||
break;
|
||||
default:
|
||||
embed.setDescription("No filter passed")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await ctx.editOrReply({
|
||||
embeds:[embed],
|
||||
flags:MessageFlags.Ephemeral
|
||||
});
|
||||
}
|
||||
}
|
19
src/commands/ping.ts
Normal file
19
src/commands/ping.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Declare, Command, type CommandContext } from 'seyfert';
|
||||
|
||||
@Declare({
|
||||
name: 'ping',
|
||||
description: 'Show the ping with discord',
|
||||
contexts: ['BOT_DM', 'GUILD', 'PRIVATE_CHANNEL'],
|
||||
integrationTypes: ['GUILD_INSTALL', 'USER_INSTALL']
|
||||
})
|
||||
export default class PingCommand extends Command {
|
||||
|
||||
async run(ctx: CommandContext) {
|
||||
// @ts-expect-error average latency between shards
|
||||
const ping = ctx.client.gateway.latency;
|
||||
|
||||
await ctx.write({
|
||||
content: `Pong! Ping: \`${ping}ms\``
|
||||
});
|
||||
}
|
||||
}
|
8
src/events/botReady.ts
Normal file
8
src/events/botReady.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { createEvent } from "seyfert";
|
||||
|
||||
export default createEvent({
|
||||
data: { once: true, name: "botReady" },
|
||||
async run(user, client) {
|
||||
client.logger.info(`${user.username} is ready`);
|
||||
}
|
||||
})
|
12
src/index.ts
Normal file
12
src/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Client } from 'seyfert';
|
||||
|
||||
const client = new Client();
|
||||
|
||||
if (process.argv.includes("--web")) {
|
||||
require("./web/api.ts")
|
||||
}
|
||||
if (!process.argv.includes("--no-bot")) {
|
||||
client.start().then(() => client.uploadCommands());
|
||||
} else {
|
||||
setInterval(()=>{},100)
|
||||
}
|
82
src/modules/filters.ts
Normal file
82
src/modules/filters.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import cheerio from 'cheerio';
|
||||
|
||||
// Lightspeed
|
||||
async function lightspeedCategorize(num: number) {
|
||||
let jFile:Blob = Bun.file("src/modules/lightspeed.json")
|
||||
let catJson = await jFile.json();
|
||||
for (let i = 0; i < catJson.length;i++) {
|
||||
if (catJson[i]["CategoryNumber"] == num) {
|
||||
return catJson[i]["CategoryName"]
|
||||
}
|
||||
}
|
||||
return num // No category
|
||||
}
|
||||
|
||||
async function lightspeed(url:string) {
|
||||
let res = await fetch("https://production-archive-proxy-api.lightspeedsystems.com/archiveproxy",
|
||||
{
|
||||
"method":"POST",
|
||||
"headers": {
|
||||
'accept': 'application/json, text/plain, */*',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'authority': 'production-archive-proxy-api.lightspeedsystems.com',
|
||||
'content-type': 'application/json',
|
||||
'origin': 'https://archive.lightspeedsystems.com',
|
||||
'user-agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'x-api-key': 'onEkoztnFpTi3VG7XQEq6skQWN3aFm3h'
|
||||
},
|
||||
// graphQL vvv
|
||||
"body": `{"query":"\\nquery getDeviceCategorization($itemA: CustomHostLookupInput!, $itemB: CustomHostLookupInput!){\\n a: custom_HostLookup(item: $itemA) { cat}\\n b: custom_HostLookup(item: $itemB) { cat \\n }\\n}","variables":{"itemA":{"hostname":"${url}"}, "itemB":{"hostname":"${url}"}}}`
|
||||
}
|
||||
);
|
||||
let body= await res.json();
|
||||
let cat = [body["data"]["a"]["cat"],body["data"]["b"]["cat"]]
|
||||
return [await lightspeedCategorize(cat[0]),await lightspeedCategorize(cat[1])]
|
||||
|
||||
}
|
||||
|
||||
// FortiGuard
|
||||
async function fortiguard(url:string) {
|
||||
let res = await fetch("https://www.fortiguard.com/learnmore/dns",{
|
||||
"method":"POST",
|
||||
"headers": {
|
||||
'Accept':
|
||||
'*/*',
|
||||
'Accept-Language':
|
||||
'en-US,en;q=0.9',
|
||||
'Authority':
|
||||
'www.fortiguard.com',
|
||||
'Content-Type':
|
||||
'application/json;charset=UTF-8',
|
||||
'Cookie':
|
||||
'cookiesession1=678A3E0F33B3CB9D7BEECD2B8A5DD036; privacy_agreement=true',
|
||||
'Origin':
|
||||
'https://www.fortiguard.com',
|
||||
'Referer':
|
||||
'https://www.fortiguard.com/services/sdns',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
||||
},
|
||||
"body": `{"value": "${url}", "version": 9}`
|
||||
})
|
||||
let rJson = await res.json();
|
||||
return rJson["dns"]["categoryname"]
|
||||
}
|
||||
|
||||
// Palo Alto
|
||||
|
||||
async function palo(domain: string): Promise<any> {
|
||||
try {
|
||||
const res = await fetch(`https://urlfiltering.paloaltonetworks.com/single_cr/?url=${domain}`);
|
||||
const html = await res.text();
|
||||
const c = cheerio.load(html);
|
||||
return [c(`*[for="id_new_category"]`).eq(2).parent().find(".form-text").text().trim(),c(`*[for="id_new_category"]`).eq(1).parent().find(".form-text").text().trim()]
|
||||
} catch (error) {
|
||||
console.error('Error fetching or parsing the HTML:', error);
|
||||
return ''; // Return an empty string in case of error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default { palo,fortiguard,lightspeed,lightspeedCategorize }
|
738
src/modules/lightspeed.json
Normal file
738
src/modules/lightspeed.json
Normal file
@ -0,0 +1,738 @@
|
||||
[
|
||||
{
|
||||
"CategoryNumber": -1,
|
||||
"CategoryName": "not reviewed"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 1,
|
||||
"CategoryName": "local-allow"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 2,
|
||||
"CategoryName": "local-block"
|
||||
|
||||
},
|
||||
{"CategoryNumber": 3,"CategoryName": "ads"},
|
||||
{
|
||||
"CategoryNumber": 4,
|
||||
"CategoryName": "adult"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 5,
|
||||
"CategoryName": "audio-video"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 6,
|
||||
"CategoryName": "business"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 7,
|
||||
"CategoryName": "errors"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 8,
|
||||
"CategoryName": "drugs"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 9,
|
||||
"CategoryName": "education"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 10,
|
||||
"CategoryName": "business.finance"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 11,
|
||||
"CategoryName": "forums"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 12,
|
||||
"CategoryName": "gambling"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 13,
|
||||
"CategoryName": "games"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 14,
|
||||
"CategoryName": "general"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 15,
|
||||
"CategoryName": "government"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 16,
|
||||
"CategoryName": "security.hacking"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 17,
|
||||
"CategoryName": "violence.hate"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 18,
|
||||
"CategoryName": "business.jobs"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 19,
|
||||
"CategoryName": "forums.mail"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 20,
|
||||
"CategoryName": "news"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 21,
|
||||
"CategoryName": "porn"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 22,
|
||||
"CategoryName": "porn.de"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 23,
|
||||
"CategoryName": "porn.es"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 24,
|
||||
"CategoryName": "porn.fr"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 25,
|
||||
"CategoryName": "porn.it"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 26,
|
||||
"CategoryName": "porn.jp"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 27,
|
||||
"CategoryName": "porn.nl"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 28,
|
||||
"CategoryName": "security.proxy"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 29,
|
||||
"CategoryName": "shopping"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 30,
|
||||
"CategoryName": "sports"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 31,
|
||||
"CategoryName": "suspicious"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 32,
|
||||
"CategoryName": "violence"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 33,
|
||||
"CategoryName": "security.warez"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 34,
|
||||
"CategoryName": "directory"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 35,
|
||||
"CategoryName": "ads.popup-ads"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 36,
|
||||
"CategoryName": "travel"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 37,
|
||||
"CategoryName": "automobile"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 38,
|
||||
"CategoryName": "forums.newsgroups"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 39,
|
||||
"CategoryName": "forums.personals"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 40,
|
||||
"CategoryName": "humor"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 41,
|
||||
"CategoryName": "education.lifestyles"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 42,
|
||||
"CategoryName": "alcohol"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 43,
|
||||
"CategoryName": "family.health"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 44,
|
||||
"CategoryName": "education.science"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 45,
|
||||
"CategoryName": "entertainment"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 46,
|
||||
"CategoryName": "kids_and_teens"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 47,
|
||||
"CategoryName": "education.arts"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 48,
|
||||
"CategoryName": "education.literature"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 49,
|
||||
"CategoryName": "music"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 50,
|
||||
"CategoryName": "education.music"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 51,
|
||||
"CategoryName": "microsoft"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 52,
|
||||
"CategoryName": "ads.banner-ads"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 53,
|
||||
"CategoryName": "ads.html-ads"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 54,
|
||||
"CategoryName": "ads.javascript-ads"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 55,
|
||||
"CategoryName": "spam"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 56,
|
||||
"CategoryName": "ham"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 57,
|
||||
"CategoryName": "computers"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 58,
|
||||
"CategoryName": "family.religion"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 59,
|
||||
"CategoryName": "world"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 60,
|
||||
"CategoryName": "forums.p2p"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 61,
|
||||
"CategoryName": "forums.im"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 62,
|
||||
"CategoryName": "security.spyware"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 63,
|
||||
"CategoryName": "security.virus"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 64,
|
||||
"CategoryName": "security.test"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 65,
|
||||
"CategoryName": "security.phishing"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 66,
|
||||
"CategoryName": "weapons"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 67,
|
||||
"CategoryName": "access-denied"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 68,
|
||||
"CategoryName": "law"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 69,
|
||||
"CategoryName": "kids_and_teens.chat"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 70,
|
||||
"CategoryName": "adult.language"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 71,
|
||||
"CategoryName": "forums.blogs"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 72,
|
||||
"CategoryName": "security"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 73,
|
||||
"CategoryName": "business.real_estate"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 74,
|
||||
"CategoryName": "education.games"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 75,
|
||||
"CategoryName": "education.social_science"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 76,
|
||||
"CategoryName": "family.food"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 77,
|
||||
"CategoryName": "kids_and_teens.animals"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 78,
|
||||
"CategoryName": "shopping.spam"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 79,
|
||||
"CategoryName": "society"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 80,
|
||||
"CategoryName": "education.sex"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 81,
|
||||
"CategoryName": "shopping.auctions"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 82,
|
||||
"CategoryName": "sports.fantasy"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 83,
|
||||
"CategoryName": "hobby"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 84,
|
||||
"CategoryName": "sports.youth"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 85,
|
||||
"CategoryName": "search"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 86,
|
||||
"CategoryName": "world.de"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 87,
|
||||
"CategoryName": "world.es"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 88,
|
||||
"CategoryName": "world.fr"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 89,
|
||||
"CategoryName": "world.it"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 90,
|
||||
"CategoryName": "world.jp"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 91,
|
||||
"CategoryName": "world.nl"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 92,
|
||||
"CategoryName": "world.pt"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 93,
|
||||
"CategoryName": "world.ru"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 94,
|
||||
"CategoryName": "porn.illicit"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 95,
|
||||
"CategoryName": "family"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 96,
|
||||
"CategoryName": "society.politics"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 97,
|
||||
"CategoryName": "society.crime"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 98,
|
||||
"CategoryName": "sports.martial_arts"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 99,
|
||||
"CategoryName": "education.history"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 100,
|
||||
"CategoryName": "adult.art"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 101,
|
||||
"CategoryName": "adult.bodyart"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 102,
|
||||
"CategoryName": "adult.games"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 103,
|
||||
"CategoryName": "adult.lifestyles"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 104,
|
||||
"CategoryName": "shopping.office_supplies"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 105,
|
||||
"CategoryName": "expired"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 106,
|
||||
"CategoryName": "world.pl"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 107,
|
||||
"CategoryName": "world.cn"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 108,
|
||||
"CategoryName": "world.kr"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 109,
|
||||
"CategoryName": "porn.pl"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 110,
|
||||
"CategoryName": "porn.ru"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 111,
|
||||
"CategoryName": "porn.pt"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 112,
|
||||
"CategoryName": "plagiarism"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 113,
|
||||
"CategoryName": "parked"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 114,
|
||||
"CategoryName": "suspicious.script"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 115,
|
||||
"CategoryName": "business.construction"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 116,
|
||||
"CategoryName": "security.nettools"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 117,
|
||||
"CategoryName": "forums.social_networking"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 118,
|
||||
"CategoryName": "forums.dating"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 119,
|
||||
"CategoryName": "business.manufacturing"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 120,
|
||||
"CategoryName": "G-Rated"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 121,
|
||||
"CategoryName": "PG-Rated"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 122,
|
||||
"CategoryName": "R-Rated"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 123,
|
||||
"CategoryName": "X-Rated"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 124,
|
||||
"CategoryName": "S-Rated"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 125,
|
||||
"CategoryName": "security.potentially_unwanted_applications"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 126,
|
||||
"CategoryName": "offensive"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 127,
|
||||
"CategoryName": "computers.filehosting"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 128,
|
||||
"CategoryName": "computers.consumer_electronics"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 129,
|
||||
"CategoryName": "education.media"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 130,
|
||||
"CategoryName": "security.virus_ignore"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 131,
|
||||
"CategoryName": "entertainment.radio_and_tv"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 132,
|
||||
"CategoryName": "photography"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 133,
|
||||
"CategoryName": "security.shorteners"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 134,
|
||||
"CategoryName": "security.malware"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 135,
|
||||
"CategoryName": "security.translators"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 136,
|
||||
"CategoryName": "computers.storage"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 137,
|
||||
"CategoryName": "violence.extremism"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 138,
|
||||
"CategoryName": "computers.analytics"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 139,
|
||||
"CategoryName": "esports"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 140,
|
||||
"CategoryName": "artificial-intelligence"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 141,
|
||||
"CategoryName": "artificial-Intelligence.generative"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 142,
|
||||
"CategoryName": "artificial-intelligence.detective"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 200,
|
||||
"CategoryName": "facebook"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 201,
|
||||
"CategoryName": "twitter"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 202,
|
||||
"CategoryName": "instagram"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 203,
|
||||
"CategoryName": "pinterest"
|
||||
|
||||
},
|
||||
{
|
||||
"CategoryNumber": 900,
|
||||
"CategoryName": "education.videos"
|
||||
|
||||
}
|
||||
]
|
27
src/modules/whois.ts
Normal file
27
src/modules/whois.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import ipRangeCheck from 'ip-range-check';
|
||||
|
||||
export async function getRDAP(ipv4Address: string): Promise<string | null> {
|
||||
try {
|
||||
const response = await fetch('https://data.iana.org/rdap/ipv4.json');
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch RDAP data');
|
||||
}
|
||||
|
||||
const rdapData = await response.json();
|
||||
const ipv4Services: Array<Array<any>> = rdapData.services;
|
||||
|
||||
for (const service of ipv4Services) {
|
||||
const cidrRanges: Array<string> = service[0] as Array<string>;
|
||||
const endpoints: Array<string> = service[1] as Array<string>;
|
||||
|
||||
if (ipRangeCheck(ipv4Address, cidrRanges)) {
|
||||
return endpoints[0]; // usually https
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('Error fetching RDAP data:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
100
src/web/api.ts
Normal file
100
src/web/api.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import Elysia from "elysia";
|
||||
import filters from "../modules/filters"
|
||||
import { join } from "path";
|
||||
import { readFile } from "fs/promises";
|
||||
const app = new Elysia();
|
||||
app.get("/", async () => {
|
||||
const filePath = join(import.meta.dir, "../../index.html");
|
||||
const fileContent = await readFile(filePath);
|
||||
return new Response(fileContent, { headers: { "Content-Type": "text/html" } });
|
||||
});
|
||||
app.get("/api/",()=>{
|
||||
return "OK"
|
||||
})
|
||||
app.get("/api/ping",()=>{
|
||||
return "OK"
|
||||
})
|
||||
|
||||
app.get("/api/check/:url/results.txt",async ({ params })=>{
|
||||
let url = params.url
|
||||
let results = [await filters.fortiguard(url),await filters.lightspeed(url),await filters.palo(url)]
|
||||
let formatted = ["FortiGuard:\nCategory: " + results[0] + "\n",`Lightspeed:\nLS Filter: ${results[1][0]}\nLS Rocket: ${results[1][1]}\n`,`Palo Alto:\nRisk: ${results[2][1]}\nCategory: ${results[2][0].trim().replace(/^\s*$(?:\r\n?|\n)/gm,"")}\n`]
|
||||
return `FilterChecker Report for ${url}:\n\n${formatted.join("\n")}`
|
||||
})
|
||||
|
||||
app.get("/api/check/:url/results.json",async ({ params })=>{
|
||||
let url = params.url
|
||||
let results = [await filters.fortiguard(url),await filters.lightspeed(url),await filters.palo(url)]
|
||||
return {"fortiguard":results[0],"lightspeed":results[1],"paloalto":results[2]}
|
||||
});
|
||||
app.post("/check/:url/results.txt",async ({ params,body,set })=>{
|
||||
let _:any = body
|
||||
let bj = {"filter": "all"};
|
||||
try {
|
||||
bj = JSON.parse(_)
|
||||
} catch {
|
||||
set.status = 400;
|
||||
return "Bad JSON"
|
||||
}
|
||||
|
||||
let url = params.url
|
||||
if (bj.filter == "all") {
|
||||
let results = [await filters.fortiguard(url),await filters.lightspeed(url),await filters.palo(url)]
|
||||
let formatted = ["FortiGuard:\nCategory: " + results[0] + "\n",`Lightspeed:\nLS Filter: ${results[1][0]}\nLS Rocket: ${results[1][1]}\n`,`Palo Alto:\nRisk: ${results[2][1]}\nCategory: ${results[2][0].trim().replace(/^\s*$(?:\r\n?|\n)/gm,"")}\n`]
|
||||
return `FilterChecker Report for ${url}:\n\n${formatted.join("\n")}`
|
||||
} else {
|
||||
let results; let formatted;
|
||||
switch (bj.filter) {
|
||||
case ("fortiguard" || "forti"):
|
||||
results = await filters.fortiguard(url)
|
||||
formatted = "FortiGuard:\nCategory: " + results[0]
|
||||
return `FilterChecker Report for ${url}:\n\n${formatted}`
|
||||
case ("lightspeed" || "ls"):
|
||||
results = await filters.lightspeed(url)
|
||||
formatted = `Lightspeed:\nLS Filter: ${results[0]}\nLS Rocket: ${results[1]}\n`
|
||||
return `FilterChecker Report for ${url}:\n\n${formatted}`
|
||||
case ("palo" || "paloalto") :
|
||||
results = await filters.palo(url)
|
||||
formatted = `Palo Alto:\nRisk: ${results[2][1]}\nCategory: ${results[2][0].trim().replace(/^\s*$(?:\r\n?|\n)/gm,"")}\n`
|
||||
return `FilterChecker Report for ${url}:\n\n${formatted}`
|
||||
default:
|
||||
set.status = 400
|
||||
return "Unknown filter. Accepted values: fortiguard, forti, lightspeed, ls, palo, paloalto"
|
||||
}
|
||||
}
|
||||
})
|
||||
app.post("/check/:url/results.json",async ({ params,body,set })=>{
|
||||
let _:any = body
|
||||
let bj = {"filter": "all"};
|
||||
try {
|
||||
bj = JSON.parse(_)
|
||||
} catch {
|
||||
set.status = 400;
|
||||
return {"error":"Bad JSON"}
|
||||
}
|
||||
|
||||
let url = params.url
|
||||
if (bj.filter == "all") {
|
||||
let url = params.url
|
||||
let results = [await filters.fortiguard(url),await filters.lightspeed(url),await filters.palo(url)]
|
||||
return {"fortiguard":results[0],"lightspeed":results[1],"paloalto":results[2]}
|
||||
} else {
|
||||
switch (bj.filter) {
|
||||
case ("fortiguard" || "forti"):
|
||||
return {"fortiguard":await filters.fortiguard(url)}
|
||||
case ("lightspeed" || "ls"):
|
||||
return {"lightspeed":await filters.lightspeed(url)}
|
||||
case ("palo" || "paloalto") :
|
||||
return {"palo":await filters.palo(url)}
|
||||
default:
|
||||
set.status = 400
|
||||
return {"error":"Unknown filter. Accepted values: fortiguard, forti, lightspeed, ls, palo, paloalto"}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let port = 10000;
|
||||
if (process.env.PORT) {port = Number(process.env.PORT)}
|
||||
if (!isNaN(Number(process.argv[process.argv.length - 1]))) {port = Number(process.argv[process.argv.length - 1])}
|
||||
console.log(`Listening on port: ${port}`)
|
||||
app.listen(port)
|
13
testing/autocheck.ts
Normal file
13
testing/autocheck.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { stdin } from "bun";
|
||||
import filters from "../src/modules/filters.ts";
|
||||
let inp:any = await stdin.text()
|
||||
inp = inp.split("\n")
|
||||
const re = new RegExp("(?:https?://)?([^/]+)");
|
||||
|
||||
for (let i = 0; i < (inp.length - 1); i++) {
|
||||
// @ts-ignore
|
||||
let url = re.exec(inp[i])[1];
|
||||
let results = [await filters.fortiguard(url),await filters.lightspeed(url),await filters.palo(url)]
|
||||
results[2] = [results[2][0].replaceAll(" ","").replaceAll("\n",""),results[2][1]]
|
||||
console.log(`\n${url}:\n lightspeed: ${results[1]}\n forti: ${results[0]}\n palo: ${results[2]}`)
|
||||
}
|
2
testing/rdapchecker.ts
Normal file
2
testing/rdapchecker.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import { getRDAP } from "../src/modules/whois";
|
||||
console.log(await getRDAP("172.233.190.246"))
|
29
tsconfig.json
Normal file
29
tsconfig.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
// Enable latest features
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user