From 6409aa91ff1bb269bc07db18f7121e35e9591d1d Mon Sep 17 00:00:00 2001
From: QWQAQ
Date: Tue, 24 Aug 2021 11:16:07 +0800
Subject: [PATCH 001/349] Initial commit
---
.gitignore | 15 ++
LICENSE | 674 +++++++++++++++++++++++++++++++++++++++++++++++++++++
README.md | 1 +
3 files changed, 690 insertions(+)
create mode 100644 .gitignore
create mode 100644 LICENSE
create mode 100644 README.md
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..66fd13c90
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, 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
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..dcd625210
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# Artalk-API-Go
\ No newline at end of file
From 6960d5a4fa45e33a5fdc2fa83aecfb2b8b591a35 Mon Sep 17 00:00:00 2001
From: qwqcode
Date: Tue, 24 Aug 2021 13:27:00 +0800
Subject: [PATCH 002/349] =?UTF-8?q?=F0=9F=9A=A7=20Start=20the=20project.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 3 +
artalk-go.example.yaml | 59 ++++
cli/cmd/root.go | 129 +++++++++
cli/cmd/serve.go | 26 ++
cli/main.go | 7 +
config/config.go | 50 ++++
go.mod | 13 +
go.sum | 633 +++++++++++++++++++++++++++++++++++++++++
http/http.go | 5 +
9 files changed, 925 insertions(+)
create mode 100644 artalk-go.example.yaml
create mode 100644 cli/cmd/root.go
create mode 100644 cli/cmd/serve.go
create mode 100644 cli/main.go
create mode 100644 config/config.go
create mode 100644 go.mod
create mode 100644 go.sum
create mode 100644 http/http.go
diff --git a/.gitignore b/.gitignore
index 66fd13c90..1b11232c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,6 @@
# Dependency directories (remove the comment below to include it)
# vendor/
+
+/config.yaml
+/artalk-go.yaml
\ No newline at end of file
diff --git a/artalk-go.example.yaml b/artalk-go.example.yaml
new file mode 100644
index 000000000..02ae377ed
--- /dev/null
+++ b/artalk-go.example.yaml
@@ -0,0 +1,59 @@
+# 网站名
+site_name: 'XXX 的博客'
+
+# HTTP Server 监听地址
+http_addr: ':23366'
+
+# 数据文件
+db_file: ''
+
+# 日志
+log:
+ on: true # 总开关
+ filepath: '' # 日志文件路径
+
+# 支持跨域访问的域名
+allow_origin:
+ - http://localhost:8080 # 或 '*' 跨域无限制
+
+# 管理员账户
+admin_users:
+ -
+ nick: 'admin'
+ email: 'admin@example.com'
+ password: ''
+ badge_name: '管理员'
+ badge_color: '#FF6C00'
+
+# 评论审核
+moderation:
+ pending_default: false # 发表新评论默认为 “待审状态”
+
+# 验证码
+captcha:
+ on: true # 总开关
+ # ↓↓ 在 {timeout} 秒内,若再次评论超过 {limit} 次则需要验证码
+ timeout: 2400 # 超时:重置评论次数统计(单位:秒)
+ limit: 3 # 激活验证码的评论次数(设置为 0 总是需要验证码)
+
+# 邮件通知
+email:
+ on: true # 总开关
+ admin_addr: 'example@example.com' # 管理员邮箱地址(文章收到评论时通知)
+ sender_type: 'smtp' # 发送方式(ali_dm or smtp)
+ mail_title: '您在 [站名] 收到了新的回复'
+ mail_title_to_admin: '您的文章收到了新的回复'
+ mail_tpl_name: 'default.html' # 邮件模板文件(/email-tpl 目录下存放)
+ smtp:
+ host: 'smtp.qq.com'
+ port: 465
+ smtp_auth: true
+ username: 'example@qq.com'
+ password: ''
+ smtp_secure: 'ssl'
+ from_addr: 'example@qq.com' # 发件人邮箱
+ from_name: '站名' # 发件人显示的名称
+ ali_dm: # https://help.aliyun.com/document_detail/29414.html
+ access_key_id: '' # 阿里云颁发给用户的访问服务所用的密钥 ID
+ access_key_secret: '' # 用于加密的密钥
+ account_name: 'example@example.com' # 管理控制台中配置的发信地址
diff --git a/cli/cmd/root.go b/cli/cmd/root.go
new file mode 100644
index 000000000..4fd5f84d6
--- /dev/null
+++ b/cli/cmd/root.go
@@ -0,0 +1,129 @@
+package cmd
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/ArtalkJS/Artalk-API-Go/config"
+ "github.com/rifflock/lfshook"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
+ prefixed "github.com/x-cray/logrus-prefixed-formatter"
+)
+
+var Banner = `
+ ________ ________ _________ ________ ___ ___ __
+|\ __ \|\ __ \|\___ ___\\ __ \|\ \ |\ \|\ \
+\ \ \|\ \ \ \|\ \|___ \ \_\ \ \|\ \ \ \ \ \ \/ /|_
+ \ \ __ \ \ _ _\ \ \ \ \ \ __ \ \ \ \ \ ___ \
+ \ \ \ \ \ \ \\ \| \ \ \ \ \ \ \ \ \ \____\ \ \\ \ \
+ \ \__\ \__\ \__\\ _\ \ \__\ \ \__\ \__\ \_______\ \__\\ \__\
+ \|__|\|__|\|__|\|__| \|__| \|__|\|__|\|_______|\|__| \|__|
+
+Artalk: A Fast, Slight & Funny Comment System.
+More detail on https://github.com/ArtalkJS/Artalk
+(c) 2021 artalk.js.org`
+
+var cfgFile string
+
+var rootCmd = &cobra.Command{
+ Use: "artalk-go",
+ Short: "Artalk: A Fast, Slight & Funny Comment System",
+ Long: Banner,
+ Run: func(cmd *cobra.Command, args []string) {
+ fmt.Println(Banner)
+ fmt.Println()
+ fmt.Println("NOTE: add `-h` flag to show help about any command.")
+ },
+}
+
+func Execute() {
+ cobra.CheckErr(rootCmd.Execute())
+}
+
+func init() {
+ cobra.OnInitialize(initConfig)
+ cobra.OnInitialize(initLog)
+ cobra.OnInitialize(initDB)
+
+ rootCmd.SetVersionTemplate("Artalk-GO {{printf \"version %s\" .Version}}\n")
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径 (defaults are './artalk-go.conf.yaml', './config.yaml')")
+}
+
+func initConfig() {
+ config.Init(cfgFile)
+}
+
+func initLog() {
+ // 初始化日志
+ stdFormatter := &prefixed.TextFormatter{
+ DisableTimestamp: true,
+ ForceFormatting: true,
+ ForceColors: true,
+ DisableColors: false,
+ } // 命令行输出格式
+ fileFormatter := &prefixed.TextFormatter{
+ FullTimestamp: true,
+ TimestampFormat: "2006-01-02.15:04:05.000000",
+ ForceFormatting: true,
+ ForceColors: false,
+ DisableColors: true,
+ } // 文件输出格式
+
+ // logrus.SetLevel(logrus.DebugLevel)
+ logrus.SetFormatter(stdFormatter)
+ logrus.SetOutput(os.Stdout)
+
+ // 文件保存
+ pathMap := lfshook.PathMap{
+ logrus.InfoLevel: config.Instance.LogFile,
+ logrus.DebugLevel: config.Instance.LogFile,
+ logrus.ErrorLevel: config.Instance.LogFile,
+ }
+ logrus.AddHook(lfshook.NewHook(
+ pathMap,
+ fileFormatter,
+ ))
+}
+
+func initDB() {
+}
+
+//// 捷径函数 ////
+
+func flag(cmd *cobra.Command, name string, defaultVal interface{}, usage string) {
+ f := cmd.PersistentFlags()
+ switch y := defaultVal.(type) {
+ case bool:
+ f.Bool(name, y, usage)
+ case int:
+ f.Int(name, y, usage)
+ case string:
+ f.String(name, y, usage)
+ }
+ viper.SetDefault(name, defaultVal)
+}
+
+func flagP(cmd *cobra.Command, name, shorthand string, defaultVal interface{}, usage string) {
+ f := cmd.PersistentFlags()
+ switch y := defaultVal.(type) {
+ case bool:
+ f.BoolP(name, shorthand, y, usage)
+ case int:
+ f.IntP(name, shorthand, y, usage)
+ case string:
+ f.StringP(name, shorthand, y, usage)
+ }
+ viper.SetDefault(name, defaultVal)
+}
+
+func flagV(cmd *cobra.Command, name string, defaultVal interface{}, usage string) {
+ flag(cmd, name, defaultVal, usage)
+ viper.BindPFlag(name, cmd.PersistentFlags().Lookup(name))
+}
+
+func flagPV(cmd *cobra.Command, name, shorthand string, defaultVal interface{}, usage string) {
+ flagP(cmd, name, shorthand, defaultVal, usage)
+ viper.BindPFlag(name, cmd.PersistentFlags().Lookup(name))
+}
diff --git a/cli/cmd/serve.go b/cli/cmd/serve.go
new file mode 100644
index 000000000..cc8a306de
--- /dev/null
+++ b/cli/cmd/serve.go
@@ -0,0 +1,26 @@
+package cmd
+
+import (
+ "fmt"
+
+ "github.com/ArtalkJS/Artalk-API-Go/http"
+ "github.com/spf13/cobra"
+)
+
+var serveCmd = &cobra.Command{
+ Use: "serve",
+ Version: rootCmd.Version,
+ Aliases: []string{"server"},
+ Short: "启动服务器",
+ Long: rootCmd.Long,
+ Run: func(cmd *cobra.Command, args []string) {
+ fmt.Println(Banner)
+ fmt.Println("----------------------")
+ http.Run()
+ },
+ Args: cobra.NoArgs,
+}
+
+func init() {
+ rootCmd.AddCommand(serveCmd)
+}
diff --git a/cli/main.go b/cli/main.go
new file mode 100644
index 000000000..521d9d7a0
--- /dev/null
+++ b/cli/main.go
@@ -0,0 +1,7 @@
+package main
+
+import "github.com/ArtalkJS/Artalk-API-Go/cli/cmd"
+
+func main() {
+ cmd.Execute()
+}
diff --git a/config/config.go b/config/config.go
new file mode 100644
index 000000000..b9211b5cf
--- /dev/null
+++ b/config/config.go
@@ -0,0 +1,50 @@
+package config
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/viper"
+)
+
+// Instance 配置实例
+var Instance *Config
+
+// Config 配置
+// @link https://godoc.org/github.com/mitchellh/mapstructure
+type Config struct {
+ SiteName string `mapstructure:"site_name"` // 网站名
+ HttpAddr string `mapstructure:"http_addr"` // HTTP Server 监听地址
+
+ DbFile string `mapstructure:"db_file"` // 数据文件
+ LogFile string `mapstructure:"log_file"` // 日志文件
+}
+
+// Init 初始化配置
+func Init(cfgFile string) {
+ viper.SetConfigType("yaml")
+
+ if cfgFile != "" {
+ // Use config file from the flag.
+ viper.SetConfigFile(cfgFile)
+ } else {
+ // Find config file in path.
+ viper.AddConfigPath(".")
+ viper.SetConfigName("artalk-go.yaml")
+ }
+
+ viper.SetEnvPrefix("ATG")
+ viper.AutomaticEnv()
+ viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
+
+ if err := viper.ReadInConfig(); err == nil {
+ fmt.Println("Using config file:", viper.ConfigFileUsed())
+ }
+
+ Instance = &Config{}
+ err := viper.Unmarshal(&Instance)
+ if err != nil {
+ logrus.Errorf("unable to decode into struct, %v", err)
+ }
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 000000000..f955bb317
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,13 @@
+module github.com/ArtalkJS/Artalk-API-Go
+
+go 1.16
+
+require (
+ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
+ github.com/onsi/gomega v1.16.0 // indirect
+ github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
+ github.com/sirupsen/logrus v1.8.1
+ github.com/spf13/cobra v1.2.1
+ github.com/spf13/viper v1.8.1
+ github.com/x-cray/logrus-prefixed-formatter v0.5.2
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 000000000..bf1caef61
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,633 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
+cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
+cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
+cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
+cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
+github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
+github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
+github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
+github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
+github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
+github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
+github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
+github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
+github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
+github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
+github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
+github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
+github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
+github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
+github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
+github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
+google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
+google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
+google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
+google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
+google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
+google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
+gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/http/http.go b/http/http.go
new file mode 100644
index 000000000..5e3a0a074
--- /dev/null
+++ b/http/http.go
@@ -0,0 +1,5 @@
+package http
+
+func Run() {
+
+}
From 170ea5a524daeccc2fa575389d9411c267cf4ae5 Mon Sep 17 00:00:00 2001
From: qwqcode
Date: Tue, 24 Aug 2021 20:38:31 +0800
Subject: [PATCH 003/349] Complete the basic model & config.
---
.gitignore | 5 +--
.vscode/launch.json | 7 ++++
.vscode/settings.json | 9 +++++
artalk-go.example.yaml | 20 ++++++-----
cli/cmd/root.go | 38 +++++++++++++--------
config/config.go | 75 +++++++++++++++++++++++++++++++++++++++---
config/config_test.go | 8 +++++
email-tpl/.gitignore | 3 ++
email-tpl/default.html | 7 ++++
go.mod | 10 ++++++
go.sum | 39 ++++++++++++++++++----
lib/db.go | 14 ++++++++
model/comment.go | 26 +++++++++++++++
model/page.go | 9 +++++
model/user.go | 23 +++++++++++++
15 files changed, 257 insertions(+), 36 deletions(-)
create mode 100644 .vscode/launch.json
create mode 100644 .vscode/settings.json
create mode 100644 config/config_test.go
create mode 100644 email-tpl/.gitignore
create mode 100644 email-tpl/default.html
create mode 100644 lib/db.go
create mode 100644 model/comment.go
create mode 100644 model/page.go
create mode 100644 model/user.go
diff --git a/.gitignore b/.gitignore
index 1b11232c8..6f60a2546 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,5 +14,6 @@
# Dependency directories (remove the comment below to include it)
# vendor/
-/config.yaml
-/artalk-go.yaml
\ No newline at end of file
+/artalk-go.yaml
+
+/local
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 000000000..f980ab98c
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,7 @@
+{
+ // 使用 IntelliSense 了解相关属性。
+ // 悬停以查看现有属性的描述。
+ // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": []
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..088284993
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,9 @@
+{
+ "cSpell.words": [
+ "artalk",
+ "gorm",
+ "lfshook",
+ "smpt",
+ "sqlite"
+ ]
+}
\ No newline at end of file
diff --git a/artalk-go.example.yaml b/artalk-go.example.yaml
index 02ae377ed..922353cea 100644
--- a/artalk-go.example.yaml
+++ b/artalk-go.example.yaml
@@ -5,40 +5,42 @@ site_name: 'XXX 的博客'
http_addr: ':23366'
# 数据文件
-db_file: ''
+db:
+ type: 'sqlite' # 支持 mysql 和 sqlite
+ dsn: './local/artalk-go.db'
# 日志
log:
- on: true # 总开关
- filepath: '' # 日志文件路径
+ enabled: true # 总开关
+ filename: './local/artalk-go.log' # 日志文件路径
-# 支持跨域访问的域名
+# 允许跨域访问的域名
allow_origin:
- http://localhost:8080 # 或 '*' 跨域无限制
# 管理员账户
admin_users:
-
- nick: 'admin'
+ name: 'admin'
email: 'admin@example.com'
password: ''
badge_name: '管理员'
badge_color: '#FF6C00'
# 评论审核
-moderation:
+moderator:
pending_default: false # 发表新评论默认为 “待审状态”
# 验证码
captcha:
- on: true # 总开关
+ enabled: true # 总开关
# ↓↓ 在 {timeout} 秒内,若再次评论超过 {limit} 次则需要验证码
timeout: 2400 # 超时:重置评论次数统计(单位:秒)
- limit: 3 # 激活验证码的评论次数(设置为 0 总是需要验证码)
+ comment_limit: 3 # 激活验证码的评论次数(设置为 0 总是需要验证码)
# 邮件通知
email:
- on: true # 总开关
+ enabled: true # 总开关
admin_addr: 'example@example.com' # 管理员邮箱地址(文章收到评论时通知)
sender_type: 'smtp' # 发送方式(ali_dm or smtp)
mail_title: '您在 [站名] 收到了新的回复'
diff --git a/cli/cmd/root.go b/cli/cmd/root.go
index 4fd5f84d6..487283d5a 100644
--- a/cli/cmd/root.go
+++ b/cli/cmd/root.go
@@ -21,7 +21,7 @@ var Banner = `
\ \__\ \__\ \__\\ _\ \ \__\ \ \__\ \__\ \_______\ \__\\ \__\
\|__|\|__|\|__|\|__| \|__| \|__|\|__|\|_______|\|__| \|__|
-Artalk: A Fast, Slight & Funny Comment System.
+Artalk: A Fast, Slight & Delightful Comment System.
More detail on https://github.com/ArtalkJS/Artalk
(c) 2021 artalk.js.org`
@@ -29,7 +29,7 @@ var cfgFile string
var rootCmd = &cobra.Command{
Use: "artalk-go",
- Short: "Artalk: A Fast, Slight & Funny Comment System",
+ Short: "Artalk: A Fast, Slight & Delightful Comment System",
Long: Banner,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(Banner)
@@ -51,40 +51,50 @@ func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径 (defaults are './artalk-go.conf.yaml', './config.yaml')")
}
+// 初始化配置
func initConfig() {
config.Init(cfgFile)
}
+// 初始化日志
func initLog() {
- // 初始化日志
+ if !config.Instance.Log.Enabled {
+ return
+ }
+
+ // 命令行输出格式
stdFormatter := &prefixed.TextFormatter{
DisableTimestamp: true,
ForceFormatting: true,
ForceColors: true,
DisableColors: false,
- } // 命令行输出格式
+ }
+
+ // 文件输出格式
fileFormatter := &prefixed.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02.15:04:05.000000",
ForceFormatting: true,
ForceColors: false,
DisableColors: true,
- } // 文件输出格式
+ }
// logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(stdFormatter)
logrus.SetOutput(os.Stdout)
- // 文件保存
- pathMap := lfshook.PathMap{
- logrus.InfoLevel: config.Instance.LogFile,
- logrus.DebugLevel: config.Instance.LogFile,
- logrus.ErrorLevel: config.Instance.LogFile,
+ if config.Instance.Log.Filename != "" {
+ // 文件保存
+ pathMap := lfshook.PathMap{
+ logrus.InfoLevel: config.Instance.Log.Filename,
+ logrus.DebugLevel: config.Instance.Log.Filename,
+ logrus.ErrorLevel: config.Instance.Log.Filename,
+ }
+ logrus.AddHook(lfshook.NewHook(
+ pathMap,
+ fileFormatter,
+ ))
}
- logrus.AddHook(lfshook.NewHook(
- pathMap,
- fileFormatter,
- ))
}
func initDB() {
diff --git a/config/config.go b/config/config.go
index b9211b5cf..ab4e67f5d 100644
--- a/config/config.go
+++ b/config/config.go
@@ -4,6 +4,7 @@ import (
"fmt"
"strings"
+ "github.com/ArtalkJS/Artalk-API-Go/model"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
@@ -14,13 +15,79 @@ var Instance *Config
// Config 配置
// @link https://godoc.org/github.com/mitchellh/mapstructure
type Config struct {
- SiteName string `mapstructure:"site_name"` // 网站名
- HttpAddr string `mapstructure:"http_addr"` // HTTP Server 监听地址
+ SiteName string `mapstructure:"site_name"` // 网站名
+ HttpAddr string `mapstructure:"http_addr"` // HTTP Server 监听地址
+ DB DBConf `mapstructure:"db"` // 数据文件
+ Log LogConf `mapstructure:"log"` // 日志文件
+ AllowOrigin []string `mapstructure:"allow_origin"` // 允许跨域访问的域名
+ AdminUsers []model.User `mapstructure:"admin_users"`
+ Moderator ModeratorConf `mapstructure:"moderator"`
+ Captcha CaptchaConf `mapstructure:"captcha"`
+ Email EmailConf `mapstructure:"email"`
+}
+
+type DBConf struct {
+ Type DBType `mapstructure:"type"`
+ Dsn string `mapstructure:"dsn"`
+}
+
+type LogConf struct {
+ Enabled bool `mapstructure:"enabled"`
+ Filename string `mapstructure:"filename"`
+}
- DbFile string `mapstructure:"db_file"` // 数据文件
- LogFile string `mapstructure:"log_file"` // 日志文件
+type ModeratorConf struct {
+ PendingDefault bool `mapstructure:"pending_default"`
}
+type CaptchaConf struct {
+ Enabled bool `mapstructure:"enabled"`
+ Timeout uint `mapstructure:"timeout"`
+ CommentLimit uint `mapstructure:"comment_limit"`
+}
+
+type EmailConf struct {
+ Enabled bool `mapstructure:"enabled"`
+ AdminAddr string `mapstructure:"admin_addr"`
+ SenderType EmailSenderType `mapstructure:"sender_type"`
+ MailTitle string `mapstructure:"mail_title"`
+ MailTitleToAdmin string `mapstructure:"mail_title_to_admin"`
+ MailTplName string `mapstructure:"mail_tpl_name"`
+ SMTP SMTPConf `mapstructure:"smtp"`
+ AliDM AliDMConf `mapstructure:"ali_dm"`
+}
+
+type SMTPConf struct {
+ Host string `mapstructure:"host"`
+ Port uint `mapstructure:"port"`
+ SMTPAuth bool `mapstructure:"smtp_auth"`
+ Username string `mapstructure:"username"`
+ Password string `mapstructure:"password"`
+ SMTPSecure string `mapstructure:"smtp_secure"`
+ FromAddr string `mapstructure:"from_addr"`
+ FromName string `mapstructure:"from_name"`
+}
+
+type AliDMConf struct {
+ AccessKeyId string `mapstructure:"access_key_id"`
+ AccessKeySecret string `mapstructure:"access_key_secret"`
+ AccountName string `mapstructure:"account_name"`
+}
+
+type DBType string
+
+const (
+ MySql DBType = "mysql"
+ Sqlite DBType = "sqlite"
+)
+
+type EmailSenderType string
+
+const (
+ SMTP EmailSenderType = "smpt"
+ AliDM EmailSenderType = "ali_dm"
+)
+
// Init 初始化配置
func Init(cfgFile string) {
viper.SetConfigType("yaml")
diff --git a/config/config_test.go b/config/config_test.go
new file mode 100644
index 000000000..6914b2321
--- /dev/null
+++ b/config/config_test.go
@@ -0,0 +1,8 @@
+package config
+
+import "testing"
+
+func TestInit(t *testing.T) {
+ Init("../artalk-go.example.yaml")
+ t.Log(Instance)
+}
diff --git a/email-tpl/.gitignore b/email-tpl/.gitignore
new file mode 100644
index 000000000..b9f7c8625
--- /dev/null
+++ b/email-tpl/.gitignore
@@ -0,0 +1,3 @@
+*
+!.gitignore
+!default.html
\ No newline at end of file
diff --git a/email-tpl/default.html b/email-tpl/default.html
new file mode 100644
index 000000000..93a644aee
--- /dev/null
+++ b/email-tpl/default.html
@@ -0,0 +1,7 @@
+Hi, {{comment.nick}}:
+
+您在 {{conf.site_name}} 收到了回复:
+
{{reply.content_html}}
+
+传送门 >
+Powered By Artalk
diff --git a/go.mod b/go.mod
index f955bb317..fce4bc9fa 100644
--- a/go.mod
+++ b/go.mod
@@ -3,11 +3,21 @@ module github.com/ArtalkJS/Artalk-API-Go
go 1.16
require (
+ github.com/fsnotify/fsnotify v1.5.0 // indirect
+ github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/onsi/gomega v1.16.0 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.8.1
+ github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.8.1
github.com/x-cray/logrus-prefixed-formatter v0.5.2
+ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
+ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
+ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
+ golang.org/x/text v0.3.7 // indirect
+ gorm.io/driver/sqlite v1.1.4
+ gorm.io/gorm v1.21.13
)
diff --git a/go.sum b/go.sum
index bf1caef61..8b9042230 100644
--- a/go.sum
+++ b/go.sum
@@ -68,8 +68,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.5.0 h1:NO5hkcB+srp1x6QmwvNZLeaOgbM8cmBTN32THzjvu2k=
+github.com/fsnotify/fsnotify v1.5.0/go.mod h1:BX0DCEr5pT4jm2CnQdVP1lFV521fcCNcyEeNp4DQQDk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -167,6 +168,11 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
+github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
@@ -182,10 +188,15 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
-github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
+github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
+github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
+github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -237,8 +248,9 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
-github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
+github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
@@ -283,8 +295,9 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -403,6 +416,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -429,9 +443,14 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
+golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -439,8 +458,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -621,6 +641,11 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
+gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
+gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
+gorm.io/gorm v1.21.13 h1:JU5A4yVemRjdMndJ0oZU7VX+Nr2ICE3C60U5bgR6mHE=
+gorm.io/gorm v1.21.13/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/lib/db.go b/lib/db.go
new file mode 100644
index 000000000..74548104f
--- /dev/null
+++ b/lib/db.go
@@ -0,0 +1,14 @@
+package lib
+
+import (
+ "github.com/ArtalkJS/Artalk-API-Go/config"
+ "gorm.io/driver/sqlite"
+ "gorm.io/gorm"
+)
+
+var DB *gorm.DB
+
+func OpenDb(dbFile string) (err error) {
+ DB, err = gorm.Open(sqlite.Open(config.Instance.DB.Dsn), &gorm.Config{})
+ return
+}
diff --git a/model/comment.go b/model/comment.go
new file mode 100644
index 000000000..9161f266e
--- /dev/null
+++ b/model/comment.go
@@ -0,0 +1,26 @@
+package model
+
+import "gorm.io/gorm"
+
+type CommentType string
+
+const (
+ CommentCollapsed CommentType = "collapsed"
+ CommentPending CommentType = "pengding"
+ CommentDeleted CommentType = "deleted"
+)
+
+type Comment struct {
+ gorm.Model
+ Content string
+
+ UserID uint
+ PageID uint
+ User User `gorm:"foreignKey:UserID"`
+ Page Page `gorm:"foreignKey:PageID"`
+
+ Rid uint
+ UA string
+ IP string
+ Type CommentType
+}
diff --git a/model/page.go b/model/page.go
new file mode 100644
index 000000000..a2ffd2cce
--- /dev/null
+++ b/model/page.go
@@ -0,0 +1,9 @@
+package model
+
+import "gorm.io/gorm"
+
+type Page struct {
+ gorm.Model
+ Name string
+ Link string
+}
diff --git a/model/user.go b/model/user.go
new file mode 100644
index 000000000..c11c72b5f
--- /dev/null
+++ b/model/user.go
@@ -0,0 +1,23 @@
+package model
+
+import "gorm.io/gorm"
+
+type UserType string
+
+const (
+ UserBanned UserType = "banned"
+ UserAdmin UserType = "admin"
+)
+
+type User struct {
+ gorm.Model
+ Name string `mapstructure:"name"`
+ Email string `mapstructure:"email"`
+ Link string `mapstructure:"link"`
+ Password string `mapstructure:"password"`
+ BadgeName string `mapstructure:"badge_name"`
+ BadgeColor string `mapstructure:"badge_color"`
+ LastIP string
+ LastUA string
+ Type UserType
+}
From 77d418fa99144f616e9d6dfb1b504145b5aff3df Mon Sep 17 00:00:00 2001
From: qwqcode
Date: Wed, 25 Aug 2021 23:48:52 +0800
Subject: [PATCH 004/349] Basic route, captcha, jwt, makefile.
Signed-off-by: qwqcode
---
.gitignore | 7 ++-
.goreleaser.yml | 32 +++++++++++
artalk-go.example.yaml | 6 ++
cli/main.go | 7 ---
{cli/cmd => cmd}/root.go | 8 ++-
{cli/cmd => cmd}/serve.go | 2 +-
config/config.go | 24 ++++----
config/config_test.go | 5 +-
frontend/index.html | 12 ++++
go.mod | 17 +++++-
go.sum | 63 ++++++++++++++++++---
http/api_admin.go | 20 +++++++
http/api_captcha.go | 42 ++++++++++++++
http/api_main.go | 78 ++++++++++++++++++++++++++
http/http.go | 66 ++++++++++++++++++++++
http/pkged.go | 12 ++++
http/route.go | 56 +++++++++++++++++++
http/utils.go | 112 ++++++++++++++++++++++++++++++++++++++
lib/db.go | 31 ++++++++++-
lib/gorm-logger.go | 61 +++++++++++++++++++++
lib/utils.go | 25 +++++++++
main.go | 7 +++
makefile | 24 ++++++++
model/page.go | 14 ++++-
model/user.go | 4 ++
25 files changed, 699 insertions(+), 36 deletions(-)
create mode 100644 .goreleaser.yml
delete mode 100644 cli/main.go
rename {cli/cmd => cmd}/root.go (94%)
rename {cli/cmd => cmd}/serve.go (93%)
create mode 100644 frontend/index.html
create mode 100644 http/api_admin.go
create mode 100644 http/api_captcha.go
create mode 100644 http/api_main.go
create mode 100644 http/pkged.go
create mode 100644 http/route.go
create mode 100644 http/utils.go
create mode 100644 lib/gorm-logger.go
create mode 100644 lib/utils.go
create mode 100644 main.go
create mode 100644 makefile
diff --git a/.gitignore b/.gitignore
index 6f60a2546..8551dde21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,9 @@
# Dependency directories (remove the comment below to include it)
# vendor/
-/artalk-go.yaml
+artalk-go.yaml
-/local
+local/
+bin/
+
+dist/
diff --git a/.goreleaser.yml b/.goreleaser.yml
new file mode 100644
index 000000000..5dbd55950
--- /dev/null
+++ b/.goreleaser.yml
@@ -0,0 +1,32 @@
+# This is an example .goreleaser.yml file with some sane defaults.
+# Make sure to check the documentation at http://goreleaser.com
+before:
+ hooks:
+ # You may remove this if you don't use go modules.
+ - go mod tidy
+ # you may remove this if you don't need go generate
+ - go generate ./...
+builds:
+ - env:
+ - CGO_ENABLED=0
+ goos:
+ - linux
+ - windows
+ - darwin
+archives:
+ - replacements:
+ darwin: Darwin
+ linux: Linux
+ windows: Windows
+ 386: i386
+ amd64: x86_64
+checksum:
+ name_template: 'checksums.txt'
+snapshot:
+ name_template: "{{ incpatch .Version }}-next"
+changelog:
+ sort: asc
+ filters:
+ exclude:
+ - '^docs:'
+ - '^test:'
diff --git a/artalk-go.example.yaml b/artalk-go.example.yaml
index 922353cea..ead781c20 100644
--- a/artalk-go.example.yaml
+++ b/artalk-go.example.yaml
@@ -4,6 +4,9 @@ site_name: 'XXX 的博客'
# HTTP Server 监听地址
http_addr: ':23366'
+# 加密密钥
+app_key: 'QXJ0YWxrLmpz'
+
# 数据文件
db:
type: 'sqlite' # 支持 mysql 和 sqlite
@@ -27,6 +30,9 @@ admin_users:
badge_name: '管理员'
badge_color: '#FF6C00'
+# 登录超时 (单位:秒)
+login_timeout: 259200
+
# 评论审核
moderator:
pending_default: false # 发表新评论默认为 “待审状态”
diff --git a/cli/main.go b/cli/main.go
deleted file mode 100644
index 521d9d7a0..000000000
--- a/cli/main.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package main
-
-import "github.com/ArtalkJS/Artalk-API-Go/cli/cmd"
-
-func main() {
- cmd.Execute()
-}
diff --git a/cli/cmd/root.go b/cmd/root.go
similarity index 94%
rename from cli/cmd/root.go
rename to cmd/root.go
index 487283d5a..704d0db42 100644
--- a/cli/cmd/root.go
+++ b/cmd/root.go
@@ -5,6 +5,7 @@ import (
"os"
"github.com/ArtalkJS/Artalk-API-Go/config"
+ "github.com/ArtalkJS/Artalk-API-Go/lib"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -22,7 +23,7 @@ var Banner = `
\|__|\|__|\|__|\|__| \|__| \|__|\|__|\|_______|\|__| \|__|
Artalk: A Fast, Slight & Delightful Comment System.
-More detail on https://github.com/ArtalkJS/Artalk
+More details on https://github.com/ArtalkJS/Artalk
(c) 2021 artalk.js.org`
var cfgFile string
@@ -98,6 +99,11 @@ func initLog() {
}
func initDB() {
+ err := lib.OpenDB()
+ if err != nil {
+ logrus.Error("数据库初始化发生错误 ", err)
+ os.Exit(1)
+ }
}
//// 捷径函数 ////
diff --git a/cli/cmd/serve.go b/cmd/serve.go
similarity index 93%
rename from cli/cmd/serve.go
rename to cmd/serve.go
index cc8a306de..8c41d3be1 100644
--- a/cli/cmd/serve.go
+++ b/cmd/serve.go
@@ -11,7 +11,7 @@ var serveCmd = &cobra.Command{
Use: "serve",
Version: rootCmd.Version,
Aliases: []string{"server"},
- Short: "启动服务器",
+ Short: "启动 HTTP 服务",
Long: rootCmd.Long,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(Banner)
diff --git a/config/config.go b/config/config.go
index ab4e67f5d..5f8d549a4 100644
--- a/config/config.go
+++ b/config/config.go
@@ -15,15 +15,17 @@ var Instance *Config
// Config 配置
// @link https://godoc.org/github.com/mitchellh/mapstructure
type Config struct {
- SiteName string `mapstructure:"site_name"` // 网站名
- HttpAddr string `mapstructure:"http_addr"` // HTTP Server 监听地址
- DB DBConf `mapstructure:"db"` // 数据文件
- Log LogConf `mapstructure:"log"` // 日志文件
- AllowOrigin []string `mapstructure:"allow_origin"` // 允许跨域访问的域名
- AdminUsers []model.User `mapstructure:"admin_users"`
- Moderator ModeratorConf `mapstructure:"moderator"`
- Captcha CaptchaConf `mapstructure:"captcha"`
- Email EmailConf `mapstructure:"email"`
+ SiteName string `mapstructure:"site_name"` // 网站名
+ AppKey string `mapstructure:"app_key"` // 加密密钥
+ HttpAddr string `mapstructure:"http_addr"` // HTTP Server 监听地址
+ DB DBConf `mapstructure:"db"` // 数据文件
+ Log LogConf `mapstructure:"log"` // 日志文件
+ AllowOrigin []string `mapstructure:"allow_origin"` // 允许跨域访问的域名
+ AdminUsers []model.User `mapstructure:"admin_users"`
+ LoginTimeout int `mapstructure:"login_timeout"`
+ Moderator ModeratorConf `mapstructure:"moderator"`
+ Captcha CaptchaConf `mapstructure:"captcha"`
+ Email EmailConf `mapstructure:"email"`
}
type DBConf struct {
@@ -77,8 +79,8 @@ type AliDMConf struct {
type DBType string
const (
- MySql DBType = "mysql"
- Sqlite DBType = "sqlite"
+ TypeMySql DBType = "mysql"
+ TypeSqlite DBType = "sqlite"
)
type EmailSenderType string
diff --git a/config/config_test.go b/config/config_test.go
index 6914b2321..39dc52b02 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -1,8 +1,11 @@
package config
-import "testing"
+import (
+ "testing"
+)
func TestInit(t *testing.T) {
Init("../artalk-go.example.yaml")
+
t.Log(Instance)
}
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 000000000..d7f935c12
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Document
+
+
+ Hello World!
+
+
\ No newline at end of file
diff --git a/go.mod b/go.mod
index fce4bc9fa..efbc5e5fb 100644
--- a/go.mod
+++ b/go.mod
@@ -3,10 +3,19 @@ module github.com/ArtalkJS/Artalk-API-Go
go 1.16
require (
- github.com/fsnotify/fsnotify v1.5.0 // indirect
- github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f // indirect
+ github.com/fsnotify/fsnotify v1.5.1 // indirect
+ github.com/golang-jwt/jwt v3.2.2+incompatible
+ github.com/kr/text v0.2.0 // indirect
+ github.com/labstack/echo/v4 v4.5.0
+ github.com/markbates/pkger v0.17.1
github.com/mattn/go-isatty v0.0.13 // indirect
+ github.com/mattn/go-sqlite3 v1.14.8 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
+ github.com/mitchellh/mapstructure v1.4.1
+ github.com/mojocn/base64Captcha v1.3.5 // indirect
+ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
+ github.com/onrik/logrus v0.9.0
github.com/onsi/gomega v1.16.0 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.8.1
@@ -15,9 +24,13 @@ require (
github.com/spf13/viper v1.8.1
github.com/x-cray/logrus-prefixed-formatter v0.5.2
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
+ golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
+ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/text v0.3.7 // indirect
+ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
+ gorm.io/driver/mysql v1.1.2
gorm.io/driver/sqlite v1.1.4
gorm.io/gorm v1.21.13
)
diff --git a/go.sum b/go.sum
index 8b9042230..b1378a7ea 100644
--- a/go.sum
+++ b/go.sum
@@ -56,9 +56,12 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
+github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -69,15 +72,23 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.5.0 h1:NO5hkcB+srp1x6QmwvNZLeaOgbM8cmBTN32THzjvu2k=
-github.com/fsnotify/fsnotify v1.5.0/go.mod h1:BX0DCEr5pT4jm2CnQdVP1lFV521fcCNcyEeNp4DQQDk=
+github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
+github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
+github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -181,22 +192,32 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo/v4 v4.5.0 h1:JXk6H5PAw9I3GwizqUHhYyS4f45iyGebR/c1xNCeOCY=
+github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
+github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
+github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
+github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
+github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
+github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -212,9 +233,17 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mojocn/base64Captcha v1.2.2 h1:NTFnThPVrb3tR66JO/N8/ZHsyFrNc7ho+xRpxBUEIlo=
+github.com/mojocn/base64Captcha v1.2.2/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
+github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
+github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/onrik/logrus v0.9.0 h1:oT7VstCUxWBoX7fswYK61fi9bzRBSpROq5CR2b7wxQo=
+github.com/onrik/logrus v0.9.0/go.mod h1:qfe9NeZVAJfIxviw3cYkZo3kvBtLoPRJriAO8zl7qTk=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
@@ -269,6 +298,11 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
+github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
+github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -296,6 +330,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -309,7 +344,11 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
+golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -371,8 +410,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
+golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -401,6 +441,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -408,6 +449,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -464,6 +506,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
+golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -623,8 +667,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
@@ -634,6 +679,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
@@ -641,9 +687,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M=
+gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM=
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
+gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.21.13 h1:JU5A4yVemRjdMndJ0oZU7VX+Nr2ICE3C60U5bgR6mHE=
gorm.io/gorm v1.21.13/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/http/api_admin.go b/http/api_admin.go
new file mode 100644
index 000000000..880ff427d
--- /dev/null
+++ b/http/api_admin.go
@@ -0,0 +1,20 @@
+package http
+
+import (
+ "github.com/labstack/echo/v4"
+)
+
+func ActionAdminLogin(c echo.Context) error {
+ return nil
+}
+
+func ActionAdminEdit(c echo.Context) error {
+ // user := c.Get("user").(*jwt.Token)
+ // claims := user.Claims.(*jwtCustomClaims)
+ // name := claims.Name
+ return nil
+}
+
+func ActionAdminDel(c echo.Context) error {
+ return nil
+}
diff --git a/http/api_captcha.go b/http/api_captcha.go
new file mode 100644
index 000000000..838d39ba6
--- /dev/null
+++ b/http/api_captcha.go
@@ -0,0 +1,42 @@
+package http
+
+import (
+ "bytes"
+ "encoding/base64"
+ "time"
+
+ "github.com/dchest/captcha"
+ "github.com/labstack/echo/v4"
+)
+
+var caGlobalStore = captcha.NewMemoryStore(100, 10*time.Minute) // TODO: 用 redis 或其他kv数据库来存更多值
+
+func ActionCaptchaRefresh(c echo.Context) error {
+ ip := c.RealIP()
+
+ return RespData(c, Map{
+ "img_data": GetBase64Image(ip, 150, 40),
+ })
+}
+
+func ActionCaptchaCheck(c echo.Context) error {
+ ip := c.RealIP()
+ value := c.QueryParam("value")
+
+ captcha.SetCustomStore(caGlobalStore)
+ if captcha.VerifyString(ip, value) {
+ return RespSuccess(c)
+ } else {
+ return RespError(c, "验证码错误")
+ }
+}
+
+func GetBase64Image(id string, width, height int) string {
+ png := bytes.NewBuffer([]byte{})
+ d := captcha.RandomDigits(6)
+ captcha.SetCustomStore(caGlobalStore)
+ caGlobalStore.Set(id, d)
+ captcha.NewImage(id, d, width, height).WriteTo(png)
+ base64Code := "data:image/png;base64," + base64.StdEncoding.EncodeToString(png.Bytes())
+ return base64Code
+}
diff --git a/http/api_main.go b/http/api_main.go
new file mode 100644
index 000000000..dc430adb3
--- /dev/null
+++ b/http/api_main.go
@@ -0,0 +1,78 @@
+package http
+
+import (
+ "github.com/ArtalkJS/Artalk-API-Go/config"
+ "github.com/ArtalkJS/Artalk-API-Go/lib"
+ "github.com/ArtalkJS/Artalk-API-Go/model"
+ "github.com/labstack/echo/v4"
+ "github.com/mitchellh/mapstructure"
+ "github.com/sirupsen/logrus"
+)
+
+type ParamsAdd struct {
+ Name string `mapstructure:"name"`
+ Content string `mapstructure:"content"`
+ Email string `mapstructure:"email"`
+ Link string `mapstructure:"link"`
+ Rid uint `mapstructure:"rid"`
+ PageKey string `mapstructure:"page_key"`
+ Token string `mapstructure:"token"`
+}
+
+func ActionAdd(c echo.Context) error {
+ var p ParamsAdd
+ mapstructure.Decode(c.QueryParams(), &p)
+
+ ip := c.RealIP()
+ ua := c.Request().UserAgent()
+
+ // find user
+ user := FindUser(p.Name, p.Email)
+ if user.IsEmpty() {
+ user = NewUser(p.Name, p.Email, p.Link) // save a new user
+ }
+
+ user.Link = p.Link
+ user.LastIP = ip
+ user.LastUA = ua
+ UpdateUser(&user)
+
+ // find page
+ page := FindPage(p.PageKey)
+ if page.IsEmpty() {
+ page = NewPage(p.PageKey)
+ }
+
+ // check if the user is allowed to comment
+ if isAllowed, err := CheckIfAllowed(c, user, page); !isAllowed {
+ return err
+ }
+
+ comment := model.Comment{
+ Content: p.Content,
+ Rid: p.Rid,
+ UserID: user.ID,
+ PageID: page.ID,
+ IP: ip,
+ UA: ua,
+ }
+
+ if config.Instance.Moderator.PendingDefault {
+ comment.Type = model.CommentPending
+ }
+
+ err := lib.DB.Create(&comment).Error
+ if err != nil {
+ logrus.Error("Save Comment error: ", err)
+ }
+
+ return nil
+}
+
+func ActionGet(c echo.Context) error {
+ return nil
+}
+
+func ActionUser(c echo.Context) error {
+ return nil
+}
diff --git a/http/http.go b/http/http.go
index 5e3a0a074..7e38a12a8 100644
--- a/http/http.go
+++ b/http/http.go
@@ -1,5 +1,71 @@
package http
+import (
+ "net/http"
+
+ "github.com/ArtalkJS/Artalk-API-Go/config"
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
+ echolog "github.com/onrik/logrus/echo"
+ "github.com/sirupsen/logrus"
+)
+
+type Map = map[string]interface{}
+
func Run() {
+ e := echo.New()
+ e.HideBanner = true
+
+ e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
+ AllowOrigins: config.Instance.AllowOrigin,
+ }))
+ e.Logger = echolog.NewLogger(logrus.StandardLogger(), "")
+ e.Use(echolog.Middleware(echolog.DefaultConfig))
+
+ InitRoute(e)
+
+ e.Logger.Fatal(e.Start(config.Instance.HttpAddr))
+}
+
+// JSONResult JSON 响应数据结构
+type JSONResult struct {
+ Success bool `json:"success"` // 是否成功
+ Msg string `json:"msg,omitempty"` // 消息
+ Data interface{} `json:"data,omitempty"` // 数据
+ Extra interface{} `json:"extra,omitempty"` // 数据
+}
+
+// RespJSON is normal json result
+func RespJSON(c echo.Context, msg string, data interface{}, success bool) error {
+ return c.JSON(http.StatusOK, &JSONResult{
+ Success: success,
+ Msg: msg,
+ Data: data,
+ })
+}
+
+// RespData is just response data
+func RespData(c echo.Context, data interface{}) error {
+ return c.JSON(http.StatusOK, &JSONResult{
+ Success: true,
+ Data: data,
+ })
+}
+
+// RespSuccess is just response success
+func RespSuccess(c echo.Context) error {
+ return c.JSON(http.StatusOK, &JSONResult{
+ Success: true,
+ })
+}
+// RespError is just response error
+func RespError(c echo.Context, msg string, details ...string) error {
+ return c.JSON(http.StatusOK, &JSONResult{
+ Success: false,
+ Msg: msg,
+ Extra: Map{
+ "errDetails": details,
+ },
+ })
}
diff --git a/http/pkged.go b/http/pkged.go
new file mode 100644
index 000000000..8a8e6dba6
--- /dev/null
+++ b/http/pkged.go
@@ -0,0 +1,12 @@
+// Code generated by pkger; DO NOT EDIT.
+
+// +build !skippkger
+
+package http
+
+import (
+ "github.com/markbates/pkger"
+ "github.com/markbates/pkger/pkging/mem"
+)
+
+var _ = pkger.Apply(mem.UnmarshalEmbed([]byte(`1f8b08000000000000ffec594b73db3812fe2b295c230b2425d992aaf6e028b1e28c93d5d88e35f67a6a0a04411216087000508fa4f2dfb7005222453dac642e73e04122bafb03886737f8f57740792814187e0711d571e6b7b148e0a5d488cd3edd1585b3cbc9f5d95818d07b2ac1108c86cfcf5f1591eaf999a45852fefc3c15727697224c9e9fb72bb5c075920aa92748c76078c25b5ae00b4a08188204510e5ae0bdc06008400bdc231911bdfff591787ef64d61abad365912d002b7421ca876a4d79f91c63118fe0fb4c19f2d70a7112360a865460ae19620253818022ef41bca95468c91e08d9fe937688e28433e236f287fe36794056f30c2b1e9ca585c51469469d70caf1d09d37a3e4356fbeafc409c04a6ce7b92da0a7e1652d35f7fa589022d8045924aa2140c19d2a4aa88bed1d4ca5c23ca89848c2a5d28c8d296e42ad5625380286f3117304d63224b39a81a03854a81e06d31f07a3d77b0a380946b22396290040b2403f533301852c2820a98319a6a8a773565fd90a27294304e5005bd0149c4834c53b6c7a4325f33521a92a0570aa65e45c2dd8a509d0d1523774bf27ae75b72cff52a72ed959a55267dd97306db124c6774095a20401af94811a8fe6635110692ceed3a128e454079542942a4b85b954dadf3ee9686722457550d56f3aa189365557c31a7a422a724a98acbc474904829a41959c890e94f9898853aed2c9c84133ca4d149d058ebf424602202c2b691a1e242d370b5296c9b23e167618898803191a46e638847672f0b0d5f16b5c1c748c5140b99c218b32326fb43ea586dfb4b915476071c4749bbf15f83298c383f01a625167cfe1a4c8b19e1c740663b9d30000b3ba16b16b7e7a59463c1552cc99c18470e139129a225aa6d8d17cabfc519a43c64046b2af85e33178b6d3d43bed208cf20c1b180f3ee712b4c681030b240f53db3014622490487eb107004820513f2388489e838c0783a916c631214512c38a212a652a4446a5aef4a82e4cc479a2898cea2faaad48c7b0e481db1f1ca094a8fbfc9fce76eee550c24894f82939009d99982bd38a503b1d33fad398cc4995d0db3bf0ed8a9425ad79c481265fa1b445cd19a9e6a1c13c6623b215a665867f539145cd29959609929bbbbb6cd29618c684aa479b71649cdd7481a864ce01964a18a85986d5b159559aa082f9aaf19d3d0ed401412290e1a76673437e21d8f56e8852fd13ec3cb02314de482201d139920be0f94169166c730a7697d73aacc178a6a0123a149dd87cd115b2186ece133ee9dc85408b61f1322a53549d2e26656412ccfb044ab62eece524942ba24c15928a4d90c7987c4dab78baa6713a5fbb221a42d640497707d83c30939628228d30213a90f60948aa12632a11cb13a84136d83a5fd8b32ad0e01bc8306187bf888314578b6cf4c038eea7ab552a54bc8b8422189090a8a39aa0117940762b1d36133d25ddd524345702609f4694065c67626d462b4445c99f5da6bcd38c522c89b380ae0fb5aa00981b2d833229d456dca21e5b43d77ab9a154a587b9ecfb64cdad4ecd7a2b1528498a14c91ba9689a8f0c955adc23149505d6b6ec766ee4c242d1e104bdc316f8eb5f51ae6012b3b7db332c8a755d11c1ac4a2aa0aa759550c13ad84dd9f1b5524c832259226846fe9a916a82a73a2b54478ebfd42d9ab6655950ac6aa72bd8a2436b833ba3d124579c448c868146ff542ad14468c41b2243877163ba672fb1d32414922aab4bd671fc4a8950ab6bbae89d279f83e7414eca722153054f9938ae25b27af96988ff4fc017d1a95457bba6db9f8ce49a8752ce601938c699a22bb4a56f177263409ec05b2886e9ce8fc7f7dbfdef21eeb65da52161ddbe8d643daa78348614a0b8b394fa914f643d6c89934756c1016caae0b6881341fa979c0903252c8c562db524496e9a600d58a6b64be6c64c6753ef8a20403e26751452e7ba545623f49772cc544efe8d5ca74b3d8f1e59d59694979644d2b8e8b47d97cb133400be4ae08f90b49f3a8912bca93b825e71769a3cd075438a1b204331dbae7db72df8a6657811698131e0809f7c50e1c231c23cf390d950ab6723b4eef15b47d18af712a6efd457b0c9cc93959730f4770f12c088f2376998223e057466c766ec095f9254429141d6a6e5f1c7e15974ab15cbd022c23f021541188f7994d98cd5df93eeb81a87a105a0dae0741b518fb2ace86da3f5be09e28bde1e578c658aeda9072b9eab3084c2787dfc14f30999f11e56bd6f057a8d3b1f82c829fabf5fc1c897622025bfb8148452d4be9b6dd73f0e3c78f1608f3819e40f80e612805d78407064e796829e08068642e00c3ef80e744ed06d5028a7e2360e8b44062fcc8d073bb17dd7ed7ed0dace62feb6786c0733cf7cce99f79bd7bd71b7afda1d36b5ff4bb9ee3f5de3afda1637c06557f0566c6f2c9337e71f81d9845bad45a523f339fba43f7bc05469220f3e97d6fdbfe0e6ec4e23dd22417dd5eafe75d386ecf69818f348a4b4bc71938e717dee0470bdc20a52f31264aed6da3ef0e06dea07fdedbdf44e7bc68626a7ceede16bcdec579cfb9f0baee915e98b1ddd16fc400ec14ae15376201868e5dbb98c886856f58f886856f58f886856f58f886856f58f886856f58f886856f58f886856f58f886856f58f886856f58f886856f58f88685fff7b2f085e333a398453f47c79694fc8f9c515acf4c8aa489c49b36cb2af6853f41f643ca03b26cdb4bc451debf825b33ff5ebfbbe6febb9dfe31d2ff62e8b9ed81dbf5fae7173ba47f88983accfa77bc57587fcf71ba838b8b81e3fd33d6bfd31d7406bfcefabb9d8bbed377fa9d5f66fdbd7ef71ff1fe968eaf93ffe5cef00f50fb255b5f52f0f92e2b18f8627db629f82ab19ea36b873727cbcbb3dd1cf7d38f7bf5506e4e3e988cae3edc3b5fbe4e1fde5d5d8f63c79f2ede8e5e962218bbea7abc8cfd040fae9387ecfaa5fbdb641cb3c7e9ef6f47f432ba1e5df6fde983f378f7ee058daf56d87b7026779f1e1e3e3ceaff8eaeeb18117cbc5ddc4c1f96c1947993bb4f8f370f0fef6ebe7e99fb7fbc8b8331a3fef82bbd1e7f99fbfc96f9fcf7c1f58c5d4da60fb327ef2b9d44c2b4154dc62e0bc61f223fb9d24ff70e0d12c682cebb39e6bf6fd7e541faf4f1564ca6b72c48d8cbd39ddb41d35b078d16119af6d260cc627fe47e7bf4aed4d3bdb3bc79b92cdff1f1360dc64b3699ddce1f3b0ffa69da7326a38183feb8554ff7dddf26a381789a5ecd2691e83f268319b9effe66ea5dbf5f8acf2fbdeba7e952f9ab777ff89d4fea69f4a17fe3452b83bdf13ecd9f3ecede8e5e1673f4f156fbefbbff01aff8dcfcd892265fd7e4eb9a7c5d93af6bf2754dbeaec9d735f9ba265fd7e4eb9a7c5d93af6bf2754dbeaec9d735f9ba265fd7e4eb9a7c5d93af6bf275ff5e02ffc7ff010000ffff010000ffffff1a750f27490000`)))
diff --git a/http/route.go b/http/route.go
new file mode 100644
index 000000000..0dc5ce1a3
--- /dev/null
+++ b/http/route.go
@@ -0,0 +1,56 @@
+package http
+
+import (
+ "net/http"
+
+ "github.com/ArtalkJS/Artalk-API-Go/config"
+ "github.com/ArtalkJS/Artalk-API-Go/model"
+ "github.com/golang-jwt/jwt"
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
+ "github.com/markbates/pkger"
+ "github.com/sirupsen/logrus"
+)
+
+func InitRoute(e *echo.Echo) {
+ f, err := pkger.Open("/frontend")
+ if err != nil {
+ logrus.Fatal(err)
+ return
+ }
+
+ fileServer := http.FileServer(f)
+ e.GET("/*", echo.WrapHandler(fileServer))
+
+ // api
+ api := e.Group("/api")
+
+ api.GET("/add", ActionAdd)
+ api.GET("/get", ActionAdd)
+ api.GET("/user", ActionUser)
+ api.GET("/login-admin", ActionAdminLogin)
+
+ // api/captcha
+ ca := api.Group("/captcha")
+ ca.GET("/refresh", ActionCaptchaRefresh)
+ ca.GET("/check", ActionCaptchaCheck)
+
+ // api/admin
+ admin := api.Group("/admin")
+ admin.GET("/edit", ActionAdminEdit)
+ admin.GET("/del", ActionAdminDel)
+
+ admin.Use(middleware.JWTWithConfig(middleware.JWTConfig{
+ Claims: &jwtCustomClaims{},
+ SigningKey: []byte(config.Instance.AppKey),
+ }))
+}
+
+// jwtCustomClaims are custom claims extending default ones.
+// See https://github.com/golang-jwt/jwt for more examples
+type jwtCustomClaims struct {
+ UserName string `json:"name"`
+ UserEmail string `json:"email"`
+ UserType model.UserType `json:"type"`
+ jwt.StandardClaims
+}
diff --git a/http/utils.go b/http/utils.go
new file mode 100644
index 000000000..e9025adc1
--- /dev/null
+++ b/http/utils.go
@@ -0,0 +1,112 @@
+package http
+
+import (
+ "time"
+
+ "github.com/ArtalkJS/Artalk-API-Go/config"
+ "github.com/ArtalkJS/Artalk-API-Go/lib"
+ "github.com/ArtalkJS/Artalk-API-Go/model"
+ "github.com/golang-jwt/jwt"
+ "github.com/labstack/echo/v4"
+ "github.com/sirupsen/logrus"
+)
+
+func LoginUser(user model.User) string {
+ // Set custom claims
+ claims := &jwtCustomClaims{
+ UserName: user.Name,
+ UserEmail: user.Email,
+ UserType: user.Type,
+ StandardClaims: jwt.StandardClaims{
+ ExpiresAt: time.Now().Add(time.Second * time.Duration(config.Instance.LoginTimeout)).Unix(), // 过期时间
+ },
+ }
+
+ // Create token with claims
+ token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+
+ // Generate encoded token and send it as response.
+ t, err := token.SignedString([]byte(config.Instance.AppKey))
+ if err != nil {
+ return ""
+ }
+
+ return t
+}
+
+func CheckIsAdmin(c echo.Context) bool {
+ jwt := c.Get("user").(*jwt.Token)
+ claims := jwt.Claims.(*jwtCustomClaims)
+ name := claims.UserName
+ email := claims.UserEmail
+
+ if claims.UserType != model.UserAdmin {
+ return false
+ }
+
+ // check user from database
+ user := FindUser(name, email)
+ if user.IsEmpty() {
+ return false
+ }
+
+ return user.Type == model.UserAdmin
+}
+
+func CheckIfAllowed(c echo.Context, user model.User, page model.Page) (bool, error) {
+ return false, nil
+}
+
+func FindUser(name string, email string) model.User {
+ var user model.User
+ lib.DB.Where(&model.User{Name: name, Email: email}).First(&user)
+ return user
+}
+
+func NewUser(name string, email string, link string) model.User {
+ user := model.User{
+ Name: name,
+ Email: email,
+ Link: link,
+ }
+
+ err := lib.DB.Create(&user).Error
+ if err != nil {
+ logrus.Error("Save User error: ", err)
+ }
+
+ return user
+}
+
+func UpdateUser(user *model.User) {
+ err := lib.DB.Save(user).Error
+ if err != nil {
+ logrus.Error("Update User error: ", err)
+ }
+}
+
+func FindPage(key string) model.Page {
+ var page model.Page
+ lib.DB.Where(&model.Page{Key: key}).First(&page)
+ return page
+}
+
+func NewPage(key string) model.Page {
+ page := model.Page{
+ Key: key,
+ }
+
+ err := lib.DB.Create(&page).Error
+ if err != nil {
+ logrus.Error("Save Page error: ", err)
+ }
+
+ return page
+}
+
+func UpdatePage(page *model.Page) {
+ err := lib.DB.Save(page).Error
+ if err != nil {
+ logrus.Error("Update Page error: ", err)
+ }
+}
diff --git a/lib/db.go b/lib/db.go
index 74548104f..819e56826 100644
--- a/lib/db.go
+++ b/lib/db.go
@@ -1,14 +1,41 @@
package lib
import (
+ "path/filepath"
+
"github.com/ArtalkJS/Artalk-API-Go/config"
+ "gorm.io/driver/mysql"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
-func OpenDb(dbFile string) (err error) {
- DB, err = gorm.Open(sqlite.Open(config.Instance.DB.Dsn), &gorm.Config{})
+var gormConfig = &gorm.Config{
+ Logger: NewGormLogger(),
+}
+
+func OpenDB() (err error) {
+ switch config.Instance.DB.Type {
+ case config.TypeMySql:
+ err = OpenMySqlDb()
+ case config.TypeSqlite:
+ err = OpenSqliteDb()
+ }
+ return
+}
+
+func OpenMySqlDb() (err error) {
+ DB, err = gorm.Open(mysql.Open(config.Instance.DB.Dsn), gormConfig)
+ return
+}
+
+func OpenSqliteDb() (err error) {
+ filename := config.Instance.DB.Dsn
+ if err := EnsureDir(filepath.Dir(filename)); err != nil {
+ return err
+ }
+
+ DB, err = gorm.Open(sqlite.Open(filename), gormConfig)
return
}
diff --git a/lib/gorm-logger.go b/lib/gorm-logger.go
new file mode 100644
index 000000000..b8ea2dce3
--- /dev/null
+++ b/lib/gorm-logger.go
@@ -0,0 +1,61 @@
+package lib
+
+import (
+ "context"
+ "errors"
+ "time"
+
+ log "github.com/sirupsen/logrus"
+ "gorm.io/gorm"
+ gormlogger "gorm.io/gorm/logger"
+ "gorm.io/gorm/utils"
+)
+
+type gLogger struct {
+ SlowThreshold time.Duration
+ SourceField string
+ SkipErrRecordNotFound bool
+}
+
+func NewGormLogger() *gLogger {
+ return &gLogger{
+ SkipErrRecordNotFound: true,
+ }
+}
+
+func (l *gLogger) LogMode(gormlogger.LogLevel) gormlogger.Interface {
+ return l
+}
+
+func (l *gLogger) Info(ctx context.Context, s string, args ...interface{}) {
+ log.WithContext(ctx).Infof(s, args)
+}
+
+func (l *gLogger) Warn(ctx context.Context, s string, args ...interface{}) {
+ log.WithContext(ctx).Warnf(s, args)
+}
+
+func (l *gLogger) Error(ctx context.Context, s string, args ...interface{}) {
+ log.WithContext(ctx).Errorf(s, args)
+}
+
+func (l *gLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
+ elapsed := time.Since(begin)
+ sql, _ := fc()
+ fields := log.Fields{}
+ if l.SourceField != "" {
+ fields[l.SourceField] = utils.FileWithLineNum()
+ }
+ if err != nil && !(errors.Is(err, gorm.ErrRecordNotFound) && l.SkipErrRecordNotFound) {
+ fields[log.ErrorKey] = err
+ log.WithContext(ctx).WithFields(fields).Errorf("%s [%s]", sql, elapsed)
+ return
+ }
+
+ if l.SlowThreshold != 0 && elapsed > l.SlowThreshold {
+ log.WithContext(ctx).WithFields(fields).Warnf("%s [%s]", sql, elapsed)
+ return
+ }
+
+ log.WithContext(ctx).WithFields(fields).Debugf("%s [%s]", sql, elapsed)
+}
diff --git a/lib/utils.go b/lib/utils.go
new file mode 100644
index 000000000..9405379ad
--- /dev/null
+++ b/lib/utils.go
@@ -0,0 +1,25 @@
+package lib
+
+import (
+ "errors"
+ "os"
+)
+
+func EnsureDir(dirName string) error {
+ err := os.Mkdir(dirName, os.ModeDir)
+ if err == nil {
+ return nil
+ }
+ if os.IsExist(err) {
+ // check that the existing path is a directory
+ info, err := os.Stat(dirName)
+ if err != nil {
+ return err
+ }
+ if !info.IsDir() {
+ return errors.New("path exists but is not a directory")
+ }
+ return nil
+ }
+ return err
+}
diff --git a/main.go b/main.go
new file mode 100644
index 000000000..98e0717d3
--- /dev/null
+++ b/main.go
@@ -0,0 +1,7 @@
+package main
+
+import "github.com/ArtalkJS/Artalk-API-Go/cmd"
+
+func main() {
+ cmd.Execute()
+}
diff --git a/makefile b/makefile
new file mode 100644
index 000000000..09a6d5e63
--- /dev/null
+++ b/makefile
@@ -0,0 +1,24 @@
+ifndef VERSION
+ VERSION := $(shell git describe --tags --abbrev=0)
+endif
+
+COMMIT_HASH :=$(shell git rev-parse --short HEAD)
+DEV_VERSION := dev-${COMMIT_HASH}
+
+all: install update build
+
+install:
+ go mod tidy
+ go install github.com/markbates/pkger/cmd/pkger
+
+update:
+ pkger -include /frontend -o http
+
+build: update
+ go build -ldflags "-X github.com/ArtalkJS/Artalk-API-Go.Version=${VERSION}" -o bin/artalk-go github.com/ArtalkJS/Artalk-API-Go
+
+run: update build
+ ./bin/artalk-go
+
+test: update
+ go test -cover github.com/ArtalkJS/Artalk-API-Go/...
diff --git a/model/page.go b/model/page.go
index a2ffd2cce..f7bc2d48a 100644
--- a/model/page.go
+++ b/model/page.go
@@ -2,8 +2,18 @@ package model
import "gorm.io/gorm"
+type PageType string
+
+const (
+ PageClosed PageType = "closed"
+)
+
type Page struct {
gorm.Model
- Name string
- Link string
+ Key string
+ Type PageType
+}
+
+func (p Page) IsEmpty() bool {
+ return p.ID == 0
}
diff --git a/model/user.go b/model/user.go
index c11c72b5f..76e99d177 100644
--- a/model/user.go
+++ b/model/user.go
@@ -21,3 +21,7 @@ type User struct {
LastUA string
Type UserType
}
+
+func (u User) IsEmpty() bool {
+ return u.ID == 0
+}
From 4389dba2859e9c2c7d96f00c785abba855acb3e8 Mon Sep 17 00:00:00 2001
From: qwqcode
Date: Thu, 26 Aug 2021 00:26:44 +0800
Subject: [PATCH 005/349] Rename Artalk-API-Go to ArtalkGo
---
README.md | 6 +++++-
cmd/root.go | 4 ++--
cmd/serve.go | 2 +-
config/config.go | 2 +-
docs/artalk-go.png | Bin 0 -> 88142 bytes
go.mod | 2 +-
http/api_main.go | 6 +++---
http/http.go | 2 +-
http/route.go | 4 ++--
http/utils.go | 6 +++---
lib/db.go | 2 +-
main.go | 2 +-
makefile | 4 ++--
13 files changed, 23 insertions(+), 19 deletions(-)
create mode 100644 docs/artalk-go.png
diff --git a/README.md b/README.md
index dcd625210..16b229d54 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,5 @@
-# Artalk-API-Go
\ No newline at end of file
+# ArtalkGo
+
+
+
+
\ No newline at end of file
diff --git a/cmd/root.go b/cmd/root.go
index 704d0db42..00ef7b4ef 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -4,8 +4,8 @@ import (
"fmt"
"os"
- "github.com/ArtalkJS/Artalk-API-Go/config"
- "github.com/ArtalkJS/Artalk-API-Go/lib"
+ "github.com/ArtalkJS/ArtalkGo/config"
+ "github.com/ArtalkJS/ArtalkGo/lib"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
diff --git a/cmd/serve.go b/cmd/serve.go
index 8c41d3be1..fdb3e4550 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -3,7 +3,7 @@ package cmd
import (
"fmt"
- "github.com/ArtalkJS/Artalk-API-Go/http"
+ "github.com/ArtalkJS/ArtalkGo/http"
"github.com/spf13/cobra"
)
diff --git a/config/config.go b/config/config.go
index 5f8d549a4..4ed002311 100644
--- a/config/config.go
+++ b/config/config.go
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
- "github.com/ArtalkJS/Artalk-API-Go/model"
+ "github.com/ArtalkJS/ArtalkGo/model"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
diff --git a/docs/artalk-go.png b/docs/artalk-go.png
new file mode 100644
index 0000000000000000000000000000000000000000..895b00c449d70ba269468f3785947f6df02c14f6
GIT binary patch
literal 88142
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