commit 80097f742baa9984b37e4c27b9f5e21322352dd9
Author: Lexzach <53662039+Lexzach@users.noreply.github.com>
Date: Mon May 6 20:21:44 2024 -0400
archive
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..bbba84b
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,617 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 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 Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are 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.
+
+ 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.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ 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 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 work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero 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 Affero 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 Affero 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 Affero 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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2f73080
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+# TF2 Virtual Trading (unbox.tf) v1.3
+This is effectively the first code that ran unbox.tf
+
+No help will be given for running this. It is here purely for archival purposes.
\ No newline at end of file
diff --git a/itemServ.db b/itemServ.db
new file mode 100644
index 0000000..8e9c3f1
Binary files /dev/null and b/itemServ.db differ
diff --git a/items.py b/items.py
new file mode 100644
index 0000000..4b0db5c
--- /dev/null
+++ b/items.py
@@ -0,0 +1,1259 @@
+itemList = [
+"Ghostly Gibus",
+"Dead of Night",
+"Lo-Fi Longwave",
+"Flair!",
+"Salty Dog",
+"Point and Shoot",
+"Cheater's Lament",
+"Ghastly Gibus",
+"Mildly Disturbing Halloween Mask",
+"Bill's Hat",
+"Modest Pile of Hat",
+"Noble Amassment of Hats",
+"Towering Pillar of Hats",
+"Max's Severed Head",
+"Alien Swarm Parasite",
+"Ellis' Cap",
+"Earbuds",
+"Wiki Cap",
+"Mann Co. Cap",
+"Horseless Headless Horsemann's Head",
+"Spine-Chilling Skull",
+"Hat of Undeniable Wealth And Respect",
+"A Rather Festive Tree",
+"Companion Cube Pin",
+"License to Maim",
+"World Traveler's Hat",
+"Athletic Supporter",
+"Aperture Labs Hard Hat",
+"Frontline Field Recorder",
+"Professor Speks",
+"Resurrection Associate Pin",
+"Proof of Purchase",
+"Summer Shades",
+"Seal Mask",
+"MONOCULUS!",
+"Brown Bomber",
+"B.M.O.C.",
+"Full Head of Steam",
+"Holiday Headcase",
+"Something Special For Someone Special",
+"Pyrovision Goggles",
+"Gentle Munitionne of Leisure",
+"Balloonicorn",
+"Robot Chicken Hat",
+"Human Cannonball",
+"Marxman",
+"RoBro 3000",
+"Crone's Dome",
+"Executioner",
+"Rump-o'-Lantern",
+"Skull Island Topper",
+"Unknown Monkeynaut",
+"That '70s Chapeau",
+"Antlers",
+"Reindoonicorn",
+"Mann Co. Online Cap",
+"Cockfighter",
+"Tough Stuff Muffs",
+"Conspiracy Cap",
+"TF2VRH",
+"Public Accessor",
+"Galvanized Gibus",
+"Hong Kong Cone",
+"One-Way Ticket",
+"Kiss King",
+"Haunted Hat",
+"Law",
+"Polar Pullover",
+"Bruiser's Bandanna",
+"Dadliest Catch",
+"Co-Pilot",
+"Finder's Fee",
+"Potassium Bonnet",
+"Phononaut",
+"Patriot Peak",
+"Prinny Hat",
+"Woolen Warmer",
+"Pocket Saxton",
+"Saxton",
+"Sledder's Sidekick",
+"Pocket Yeti",
+"Balloonihoodie",
+"Slithering Scarf",
+"Monstrous Memento",
+"Deadbeats",
+"Bread Heads",
+"Citizen Cane",
+"Globetrotter",
+"Breadcrab",
+"Yule Hog",
+"Loaf Loafers",
+"Hollowed Helm",
+"Eye-See-You",
+"Balloonicorpse",
+"All Hallows' Hatte",
+"Towering Pillar of Beanies",
+"Festive Flip-thwomps",
+"Festive Fascinator",
+"Candy Cantlers",
+"Jolly Jingler",
+"Reindoonibeanie",
+"Smissmas Sorcerer",
+"Shoestring Santa",
+"Towering Pile of Presents",
+"Impish Ears",
+"Candy Crown",
+"Bread Biter",
+"Brotherhood of Arms",
+"Hot Dogger",
+"Party Hat",
+"Killer Exclusive",
+"Audio File",
+"Towering Pillar of Hats",
+"Crosslinker's Coil",
+"Virtual Viewfinder",
+"Cotton Head",
+"Grandmaster",
+"Prinny Hat",
+"Batter's Helmet",
+"Bonk Helm",
+"Baseball Bill's Sports Shine",
+"Ye Olde Baker Boy",
+"Troublemaker's Tossle Cap",
+"Whoopee Cap",
+"Bombing Run",
+"Milkman",
+"Flipped Trilby",
+"Essential Accessories",
+"Superfan",
+"Hero's Tail",
+"Sign of the Wolf's School",
+"Planeswalker Goggles",
+"Bonk Boy",
+"Flip-Flops",
+"Lucky No. 42",
+"El Jefe",
+"Ball-Kicking Boots",
+"Backwards Ballcap",
+"Hermes",
+"Stereoscopic Shades",
+"B-ankh!",
+"Futankhamun",
+"Wrap Battler",
+"Big Elfin Deal",
+"Bootie Time",
+"Boston Boom-Bringer",
+"Fast Learner",
+"Teufort Tooth Kicker",
+"Front Runner",
+"Cross-Comm Express",
+"Dillinger's Duffel",
+"Fed-Fightin' Fedora",
+"Champ Stamp",
+"Triad Trinket",
+"Void Monk Hair",
+"Robot Running Man",
+"Crafty Hair",
+"Track Terrorizer",
+"Spooky Sleeves Spooky Shoes",
+"Voodoo-Cursed Scout Soul",
+"Digit Divulger",
+"Flight of the Monarch",
+"Flunkyware",
+"Hanger-On Hood",
+"Mutton Mann",
+"Buck Turner All-Stars",
+"Tomb Wrapper",
+"Long Fall Loafers",
+"Wilson Weave",
+"Bolt Boy",
+"Bonk Leadwear",
+"Ye Oiled Baker Boy",
+"Bacteria Blocker",
+"Beastly Bonnet",
+"Cheet Sheet",
+"Bigg Mann on Campus",
+"Caffeine Cooler",
+"Cool Cat Cardigan",
+"Delinquent's Down Vest",
+"Greased Lightning",
+"Half-Pipe Hurdler",
+"Macho Mann",
+"Beep Boy",
+"Flapjack",
+"Weight Room Warmer",
+"Frenchman's Formals",
+"Face Plante",
+"Faun Feet",
+"Halloweiner",
+"Horrific Head of Hare",
+"Hound's Hood",
+"Sprinting Cephalopod",
+"Terrier Trousers",
+"Baphomet Trotters",
+"Sack Fulla Smissmas",
+"Chucklenuts",
+"Little Drummer Mann",
+"Runner's Warm-Up",
+"Scout Shako",
+"Ticket Boy",
+"Sole Saviors",
+"Argyle Ace",
+"Frickin' Sweet Ninja Hood",
+"Paisley Pro",
+"Pomade Prince",
+"Red Socks",
+"Southie Shinobi",
+"Alien Cranium",
+"Biomech Backpack",
+"Xeno Suit",
+"Thirst Blood",
+"Claws And Infect",
+"Crazy Legs",
+"Fowl Fists",
+"Head Hunter",
+"Nugget Noggin",
+"Talon Trotters",
+"Brooklyn Booties",
+"Thermal Tracker",
+"Courtier's Collar",
+"Harlequin's Hooves",
+"Mountebank's Masque",
+"Bootenkhamuns",
+"Orion's Belt",
+"Fortunate Son",
+"Flak Jack",
+"Cadet Visor",
+"B'aaarrgh-n-Bicorne",
+"B'aaarrgh-n-Britches",
+"Death Racer's Helmet",
+"Thrilling Tracksuit",
+"Bat Backup",
+"Buttler",
+"Crook Combatant",
+"Sidekick's Side Slick",
+"Teufort Knight",
+"Bonk Batter's Backup",
+"Hot Heels",
+"Airdog",
+"Courtly Cuirass",
+"Squire's Sabatons",
+"Herald's Helm",
+"Pestering Jester",
+"Wing Mann",
+"Electric Twanger",
+"Reader's Choice",
+"Snowwing",
+"Airborne Attire",
+"Lightning Lid",
+"Messenger's Mail Bag",
+"Pocket Pauling",
+"Speedster's Spandex",
+"Aloha Apparel",
+"Forest Footwear",
+"Jungle Jersey",
+"Transparent Trousers",
+"Trucker's Topper",
+"Punk's Pomp",
+"Wipe Out Wraps",
+"Blizzard Britches",
+"Antarctic Eyewear",
+"Athenian Attire",
+"Hephaistos' Handcraft",
+"Olympic Leapers",
+"Catcher's Companion",
+"Juvenile's Jumper",
+"Millennial Mercenary",
+"Bottle Cap",
+"Pompous Privateer",
+"Speedy Scoundrel",
+"Fuel Injector",
+"Remorseless Raptor",
+"Wild Whip",
+"California Cap",
+"Poolside Polo",
+"Soda Specs",
+"Tools of the Tourist",
+"Boom Boxers",
+"Grounded Flyboy",
+"Particulate Protector", #end scout
+"Soldier's Stash",
+"Stainless Pot",
+"Tyrant's Helm",
+"Killer's Kabuto",
+"Grenadier's Softcap",
+"Stout Shako",
+"Chieftain's Challenge",
+"Lumbricus Lid",
+"Sergeant's Drill Hat",
+"Defiant Spartan",
+"Exquisite Rack",
+"Hero's Hachimaki",
+"Honcho's Headgear",
+"Brain Bucket",
+"Jumper's Jeepcap",
+"Fancy Dress Uniform",
+"Armored Authority",
+"Team Captain",
+"Furious Fukaamigasa",
+"Pocket Medic",
+"Lord Cockswain's Novelty Mutton Chops and Pipe",
+"Lord Cockswain's Pith Helmet",
+"Stahlhelm",
+"Hat With No Name",
+"Idiot Box",
+"Infernal Impaler",
+"Shoestring Budget",
+"Steel Pipes",
+"Kringle Collection",
+"All-Father",
+"Ornament Armament",
+"Lucky Shot",
+"Battle Bob",
+"Conquistador",
+"Teufort Tooth Kicker",
+"Cross-Comm Crash Helmet",
+"Professor's Pineapple",
+"Captain's Cocktails",
+"Helmet Without a Home",
+"Soldier's Stogie",
+"Tin Pot",
+"Crafty Hair",
+"War Pig",
+"Menpo",
+"Voodoo-Cursed Soldier Soul",
+"Bonedolier",
+"Exorcizor",
+"Zipperface",
+"Chief Constable",
+"Full Metal Drill Hat",
+"Doe-Boy",
+"Mutton Mann",
+"Soldier's Slope Scopers",
+"Deadliest Duckling",
+"Soldier's Sparkplug",
+"Steel Shako",
+"Tyrantium Helmet",
+"Cloud Crasher",
+"Powdered Practitioner",
+"Brawling Buccaneer",
+"Caribbean Conqueror",
+"Colonial Clogs",
+"Compatriot",
+"Founding Father",
+"Hornblower",
+"Lieutenant Bites",
+"Rebel Rouser",
+"Shogun's Shoulder Guard",
+"Valley Forge",
+"Whirly Warrior",
+"Macho Mann",
+"Cuban Bristle Crisis",
+"Viking Braider",
+"Cadaver's Capper",
+"Faux Manchu",
+"Freedom Feathers",
+"Grub Grenades",
+"Hardium Helm",
+"Hidden Dragon",
+"Jupiter Jumpers",
+"Larval Lid",
+"Lieutenant Bites the Dust",
+"Shaolin Sash",
+"Space Bracers",
+"Spellbinder's Bonnet",
+"Candleer",
+"Pin Pals",
+"War on Smissmas Battle Hood",
+"War on Smissmas Battle Socks",
+"Antarctic Parka",
+"Marshall's Mutton Chops",
+"Slo-Poke",
+"Toy Soldier",
+"Ground Control",
+"Killer's Kit",
+"Big Daddy",
+"First American",
+"Gilded Guard",
+"Classified Coif",
+"Man in Slacks",
+"Spook Specs",
+"Lone Survivor",
+"Battle Bird",
+"Ghoul Gibbin' Gear",
+"Hellhunter's Headpiece",
+"Supernatural Stalker",
+"Coldfront Curbstompers",
+"Condor Cap",
+"Mistaken Movember",
+"Screamin' Eagle",
+"Cold Snap Coat",
+"Skullcap",
+"Hellmet",
+"Buttler",
+"Patriot's Pouches",
+"Gift Bringer",
+"Diplomat",
+"Teufort Knight",
+"Caped Crusader",
+"Pestering Jester",
+"Handy Canes",
+"Socked and Loaded",
+"Flakcatcher",
+"Attack Packs",
+"Bananades",
+"Crit Cloak",
+"Nuke",
+"Sharp Chest Pain",
+"Shellmet",
+"War Eagle",
+"Brass Bucket",
+"Head Hedge",
+"Private Maggot Muncher",
+"Sky High Fly Guy",
+"Veteran's Attire",
+"Tank Top",
+"Dancing Doe",
+"Public Speaker",
+"Bazaar Bauble",
+"Semi-tame Trapper's Hat",
+"Calamitous Cauldron",
+"Peacebreaker",
+"Dumb Bell",
+"Crack Pot",
+"El Zapateador",
+"Hawk Warrior",
+"Party Poncho",
+"Bobby Bonnet",
+"Racc Mann",
+"Pyro's Beanie",
+"Brigade Helm",
+"Respectless Rubber Glove",
+"Triboniophorus Tyrannus",
+"Vintage Merryweather",
+"Old Guadalajara",
+"Napper's Respite",
+"Handyman's Handle",
+"Attendant",
+"Whiskered Gentleman",
+"Foster's Facade",
+"Stockbroker's Scarf",
+"Prancer's Pride",
+"Madame Dixie",
+"Pyromancer's Mask",
+"Sight for Sore Eyes",
+"Dead Cone",
+"Connoisseur's Cap",
+"Hottie's Hoodie",
+"Stately Steel Toe",
+"Apparition's Aspect",
+"Little Buddy",
+"Flamboyant Flamenco",
+"Cremator's Conscience",
+"Birdcage",
+"Blazing Bull",
+"Fallen Angel",
+"Last Breath",
+"Tail From the Crypt",
+"Bubble Pipe",
+"Head Warmer",
+"Jingle Belt",
+"Moonman Backpack",
+"Ornament Armament",
+"Waxy Wayfinder",
+"HazMat Headcase",
+"Burning Bongos",
+"Professor's Pineapple",
+"Triclops",
+"Scrap Pack",
+"Infernal Orchestrina",
+"Russian Rocketeer",
+"Tribal Bones",
+"Pyrobotics Pack",
+"Area 451",
+"Pyrotechnic Tote",
+"Coffin Kit",
+"Exorcizor",
+"Plutonidome",
+"Voodoo-Cursed Pyro Soul",
+"Nose Candy",
+"DethKapp",
+"Deadliest Duckling",
+"Wraith Wrap",
+"Rail Spikes",
+"Winter Wonderland Wrap",
+"Person in the Iron Mask",
+"Necronomicrown",
+"Bolted Birdcage",
+"Metal Slug",
+"Googol Glass Eyes",
+"Firewall Helmet",
+"Filamental",
+"Electric Escorter",
+"Plumber's Pipe",
+"Pyro's Boron Beanie",
+"Respectless Robo-Glove",
+"Rusty Reaper",
+"Scrap Sack",
+"Backpack Broiler",
+"Steel Sixpack",
+"Centurion",
+"Mair Mask",
+"Breather Bag",
+"Burning Bandana",
+"El Muchacho",
+"Hive Minder",
+"Pampered Pyro",
+"Soot Suit",
+"Special Eyes",
+"Pop-eyes",
+"Bone Dome",
+"Air Raider",
+"Trickster's Turnout Gear",
+"Abhorrent Appendages",
+"Beast from Below",
+"Bozo's Bouffant",
+"Burny's Boney Bonnet",
+"Crispy Golden Locks",
+"Creature From The Heap",
+"Corpsemopolitan",
+"External Organ",
+"Glob",
+"Grisly Gumbo",
+"Death Support Pack",
+"Handhunter",
+"Hard-Headed Hardware",
+"Hollowhead",
+"Macabre Mask",
+"Maniac's Manacles",
+"Rugged Respirator",
+"Raven's Visage",
+"PY-40 Incinibot",
+"Mucous Membrain",
+"Scorched Skirt",
+"Vicious Visage",
+"Sub Zero Suit",
+"Blizzard Breather",
+"Portable Smissmas Spirit Dispenser",
+"Snaggletoothed Stetson",
+"Tiny Timber",
+"Toy Tailor",
+"Trail-Blazer",
+"Cute Suit",
+"Sole Mate",
+"Lunatic's Leathers",
+"Gas Guzzler",
+"Frymaster",
+"Employee of the Mmmph",
+"Combustible Kabuto",
+"Sengoku Scorcher",
+"Smoking Skid Lid",
+"Mishap Mercenary",
+"Arsonist Apparatus",
+"Creature's Grin",
+"Lollichop Licker",
+"Moccasin Machinery",
+"Mr. Juice",
+"Vampyro",
+"Nabler",
+"North Polar Fleece",
+"Wartime Warmth",
+"Black Knight's Bascinet",
+"Charred Chainmail",
+"Pyromancer's Hood",
+"Phobos Filter",
+"Jupiter Jetpack",
+"A Head Full of Hot Air",
+"Torcher's Tabard",
+"Pyromancer's Raiments",
+"Space Diver",
+"Arthropod's Aspect",
+"Crusader's Getup",
+"Face of Mercy",
+"Neptune's Nightmare",
+"Buttler",
+"Fear Monger",
+"Firefly",
+"Combustible Cutie",
+"Cranial Carcharodon",
+"Hovering Hotshot",
+"Pestering Jester",
+"Flammable Favor",
+"Socked and Loaded",
+"Handy Canes",
+"Pyro the Flamedeer",
+"Sweet Smissmas Sweater",
+"Airtight Arsonist",
+"Deity's Dress",
+"D-eye-monds",
+"Feathered Fiend",
+"Fireman's Essentials",
+"Hot Huaraches",
+"Sacrificial Stone",
+"Burning Beanie",
+"Cat's Pajamas",
+"Burning Question",
+"Hot Case",
+"Arachno-Arsonist",
+"Mr. Quackers",
+"Pocket Pardner",
+"Melted Mop",
+"Spawn Camper",
+"Wanderer's Wear",
+"Candy Cranium",
+"Head of the Dead",
+"Pyr'o Lantern",
+"Pyro Shark",
+"Skullbrero",
+"Trick Stabber",
+"Discovision",
+"Fire Fighter",
+"Winter Wrap Up",
+"Seared Sorcerer",
+"Flavorful Baggies",
+"Demoman's Fro",
+"Glengarry Bonnet",
+"Scotsman's Stove Pipe",
+"Hustler's Hallmark",
+"Tippler's Tricorne",
+"Prince Tavish's Crown",
+"Scotch Bonnet",
+"Samur-Eye",
+"Reggaelator",
+"Private Eye",
+"Conjurer's Cowl",
+"Sultan's Ceremonial",
+"Tam O' Shanter",
+"Mask of the Shaman",
+"A Whiff of the Old Brimstone",
+"Buccaneer's Bicorne",
+"Hat With No Name",
+"Tavish DeGroot Experience",
+"Hair of the Dog",
+"Pickled Paws",
+"Scottish Snarl",
+"Snapped Pupil",
+"Aladdin's Private Reserve",
+"Bolgan",
+"Ornament Armament",
+"All-Father",
+"Liquor Locker",
+"Grenadier Helm",
+"Menpo",
+"King of Scotland Cape",
+"K-9 Mane",
+"Bearded Bombardier",
+"Battery Bandolier",
+"Spooky Sleeves",
+"Voodoo-Cursed Demoman Soul",
+"Blind Justice",
+"Buck Turner All-Stars",
+"Wilson Weave",
+"Mutton Mann",
+"Cool Breeze",
+"Bolted Bicorne",
+"Bolted Bombardier",
+"Broadband Bonnet",
+"Cyborg Stunt Helmet",
+"FR-0",
+"Dark Age Defender",
+"Strontium Stove Pipe",
+"Scrumpy Strongbox",
+"HDMI Patch",
+"Glasgow Great Helm",
+"Tartan Shade",
+"Tartan Spartan",
+"Pirate Bandana",
+"Hurt Locher",
+"Cap'n Calamari",
+"Headtaker's Hood",
+"Horsemann's Hand-Me-Down",
+"Parasight",
+"Transylvania Top",
+"Mann-Bird of Aberdeen",
+"Highland High Heels",
+"Tartan Tyrolean",
+"Sub Zero Suit",
+"Bushi-Dou",
+"Juggernaut Jacket",
+"Sangu Sleeves",
+"Sole Saviors",
+"Stylish DeGroot",
+"Allbrero",
+"Toowoomba Tunic",
+"Six Pack Abs",
+"Razor Cut",
+"Mann of the Seven Sees",
+"Frontier Djustice",
+"Eyeborg",
+"Mannhattan Project",
+"Bomber's Bucket Hat",
+"Forgotten King's Restless Head",
+"Double Dynamite",
+"Scot Bonnet",
+"Storm Stompers",
+"Snow Sleeves",
+"Valhalla Helm",
+"Bruce's Bonnet",
+"Outta' Sight",
+"Teufort Knight",
+"Dayjogger",
+"Bomb Beanie",
+"Bomber Knight",
+"Elf Esteem",
+"Bobby Bonnet",
+"Dynamite Abs",
+"Unforgiven Glory",
+"Frag Proof Fragger",
+"Hungover Hero",
+"Backbreaker's Guards",
+"Football Helmet",
+"Officer's Ushanka",
+"Tough Guy's Toque",
+"Hound Dog",
+"Heavy Duty Rag",
+"Big Chief",
+"Dealer's Visor",
+"Cadaver's Cranium",
+"Pugilist's Protector",
+"Hard Counter",
+"Team Captain",
+"Large Luchadore",
+"Dread Knot",
+"Magnificent Mongolian",
+"Capo's Capper",
+"Big Steel Jaw of Summer Fun",
+"Copper's Hard Top",
+"Security Shades",
+"Gym Rat",
+"Storm Spirit's Jolly Hat",
+"Dragonborn Helmet",
+"Pilotka",
+"One-Man Army",
+"Outdoorsman",
+"Can Opener",
+"Soviet Stitch-Up",
+"Steel-Toed Stompers",
+"Toss-Proof Towel",
+"Sandvich Safe",
+"War Head",
+"Voodoo-Cursed Heavy Soul",
+"U-clank-a",
+"Triad Trinket",
+"Apparatchik's Apparel",
+"Apparatchik's Apparel",
+"Grand Duchess Fairy Wings",
+"Soviet Gentleman",
+"Grand Duchess Tiara",
+"Grand Duchess Tutu",
+"Mutton Mann",
+"Hunger Force",
+"Heavy's Hockey Hair",
+"Carl",
+"Samson Skewer",
+"Bunsen Brave",
+"Wilson Weave",
+"Titanium Towel",
+"Tungsten Toque",
+"Borscht Belt",
+"Red Army Robin",
+"Tsarboosh",
+"Macho Mann",
+"Cuban Bristle Crisis",
+"Weight Room Warmer",
+"Viking Braider",
+"Monstrous Mandible",
+"Last Bite",
+"Ivan the Inedible",
+"Horned Honcho",
+"Chicken Kiev",
+"Mann of the House",
+"Minnesota Slick",
+"Combat Slacks",
+"Sammy Cap",
+"Leftover Trap",
+"Heavy Lifter",
+"Trash Man",
+"Die Regime-Panzerung",
+"Minsk Beef",
+"Hunter Heavy",
+"Old Man Frost",
+"Mad Mask",
+"Gift Bringer",
+"Siberian Sweater",
+"White Russian",
+"El Duderino",
+"Airborne Attire",
+"Sinner's Shade",
+"Mann-O-War",
+"Starboard Crusader",
+"Polar Bear",
+"Nuke",
+"Kathman-Hairdo",
+"Commando Elite",
+"Pestering Jester",
+"Convict Cap",
+"Mannvich",
+"Sophisticated Smoker",
+"Cool Capuchon",
+"SandMann's Brush",
+"Bear Walker",
+"Mining Light",
+"Engineer's Cap",
+"Texas Ten Gallon",
+"Hotrod",
+"Big Country",
+"Industrial Festivizer",
+"Buckaroo's Hat",
+"Safe'n'Sound",
+"Western Wear",
+"Ol' Geezer",
+"Pip-Boy",
+"Builder's Blueprints",
+"Frontier Flyboy",
+"Buzz Killer",
+"Virtual Reality Headset",
+"Pencil Pusher",
+"Idea Tube",
+"Pocket Purrer",
+"Master Mind",
+"Itsy Bitsy Spyer",
+"Western Wear",
+"Tin-1000",
+"Barnstormer",
+"Voodoo-Cursed Engineer Soul",
+"Grizzled Growth",
+"Data Mining Light",
+"Texas Tin-Gallon",
+"Gold Digger",
+"Pardner's Pompadour",
+"Trencher's Topper",
+"Danger",
+"Tiny Texan",
+"Sheriff's Stetson",
+"Conagher's Combover",
+"Smokey Sombrero",
+"Winter Backup",
+"Wide-Brimmed Bandito",
+"Plumber's Cap",
+"Packable Provisions",
+"Aim Assistant",
+"Dell in the Shell",
+"Puggyback",
+"El Mostacho",
+"Eingineer",
+"Texas Toast",
+"Brain Interface",
+"Telefragger Toque",
+"Head of Defense",
+"Goblineer",
+"Ghoul Box",
+"Sophisticated Smoker",
+"Provisions Cap",
+"Wavefinder",
+"Prussian Pickelhaube",
+"Otolaryngologist's Mirror",
+"Vintage Tyrolean",
+"Physician's Procedure Mask",
+"Gentleman's Gatsby",
+"Ze Goggles",
+"Berliner's Bucket Helm",
+"Blighted Beak",
+"German Gonzila",
+"Geisha Boy",
+"Doctor's Sack",
+"Private Eye",
+"Medic's Mountain Cap",
+"Grimm Hatte",
+"Planeswalker Helm",
+"Surgeon's Stethoscope",
+"Nine-Pipe Problem",
+"Dr. Whoa",
+"Einstein",
+"Gentleman's Ushanka",
+"Archimedes",
+"Foppish Physician",
+"Medi-Mask",
+"Voodoo-Cursed Medic Soul",
+"Byte'd Beak",
+"Halogen Head Lamp",
+"Mecha-Medes",
+"Virus Doctor",
+"Baron von Havenaplane",
+"Das Ubersternmann",
+"Macho Mann",
+"Medimedes",
+"Shaman's Skull",
+"Nunhood",
+"Angel of Death",
+"Vicar's Vestments",
+"Das Blutliebhaber",
+"Slick Cut",
+"Das Naggenvatcher",
+"Mann of Reason",
+"Ruffled Ruprecht",
+"Heer's Helmet",
+"Teutonic Toque",
+"Chronoscarf",
+"Medicine Manpurse",
+"Hundkopf",
+"Herzensbrecher",
+"Kriegsmaschine-9000",
+"Pocket Heavy",
+"Ze Übermensch",
+"Vampire Makeover",
+"Wings of Purity",
+"Surgeon's Shako",
+"Teufort Knight",
+"Vascular Vestment",
+"Physician's Protector",
+"Unknown Mann",
+"Berlin Brain Bowl",
+"Bunnyhopper's Ballistics Vest",
+"Medical Monarch",
+"Gauzed Gaze",
+"Field Practice",
+"Santarchimedes",
+"Surgeon's Sidearms",
+"Colossal Cranium",
+"Burly Beast",
+"Battle Boonie",
+"Vitals Vest",
+"Coldfront Commander",
+"Snowcapped",
+"Miser's Muttonchops",
+"Mighty Mitre",
+"Harry",
+"Rolfe Copter",
+"Self-Care",
+"Flatliner",
+"Pocket-Medes",
+"Madmann's Muzzle",
+"Elf Care Provider",
+"Trophy Belt",
+"Master's Yellow Belt",
+"Professional's Panama",
+"Ritzy Rick's Hair Fixative",
+"Shooter's Sola Topi",
+"Villain's Veil",
+"Crocleather Slouch",
+"Larrikin Robin",
+"Ol' Snaggletooth",
+"Bloke's Bucket Hat",
+"Desert Marauder",
+"Anger",
+"Sniper's Snipin' Glass",
+"Crocodile Smile",
+"Silver Bullets",
+"Holy Hunter",
+"Your Worst Nightmare",
+"Swagman's Swatter",
+"Bushman's Boonie",
+"Liquidator's Lid",
+"HazMat Headcase",
+"Doublecross-Comm",
+"Flamingo Kid",
+"Fruit Shoot",
+"Lone Star",
+"Champ Stamp",
+"Triad Trinket",
+"Bolted Bushman",
+"Koala Compact",
+"Stovepipe Sniper Shako",
+"Sir Hootsalot",
+"Voodoo-Cursed Sniper Soul",
+"Bloodhound",
+"Sydney Straw Boat",
+"Mutton Mann",
+"Cold Killer",
+"Shooter's Tin Topi",
+"Letch's LED",
+"Soldered Sensei",
+"Brim-Full of Bullets",
+"Wet Works",
+"Li'l Snaggletooth",
+"Chronomancer",
+"Hallowed Headcase",
+"Sir Shootsalot",
+"Five-Month Shadow",
+"Extra Layer",
+"Smissmas Caribou",
+"Snaggletoothed Stetson",
+"Golden Garment",
+"Snow Scoper",
+"Toy Soldier",
+"Scoper's Smoke",
+"Dread Hiding Hood",
+"Deep Cover Operator",
+"Hillbilly Speed-Bump",
+"Cranial Conspiracy",
+"Marsupial Man",
+"Marsupial Muzzle",
+"Bushman's Bristles",
+"Professional's Ushanka",
+"Wally Pocket",
+"Starduster",
+"Corona Australis",
+"Archer's Sterling",
+"Hawk-Eyed Hunter",
+"Classy Capper",
+"Puffy Polar Cap",
+"Handsome Hitman",
+"Most Dangerous Mane",
+"Antarctic Eyewear",
+"Head Hedge",
+"Crocodile Mun-Dee",
+"Highway Star",
+"Bare Necessities",
+"Missing Piece",
+"Killing Tree",
+"Glow from Below",
+"Fancy Fedora",
+"Backbiter's Billycock",
+"Camera Beard",
+"Magistrate's Mullet",
+"Frenchman's Beret",
+"Charmer's Chapeau",
+"Noh Mercy",
+"Le Party Phantom",
+"Detective Noir",
+"Familiar Fez",
+"Private Eye",
+"Janissary Ketche",
+"Cosa Nostra Cap",
+"Made Man",
+"Rogue's Col Roule",
+"Spectre's Spectacles",
+"L'Inspecteur",
+"Counterfeit Billycock",
+"Nanobalaclava",
+"Intangible Ascot",
+"Under Cover",
+"Doublecross-Comm",
+"Stealth Steeler",
+"Ninja Cowl",
+"Business Casual",
+"Hat of Cards",
+"Lacking Moral Fiber Mask",
+"Scarecrow",
+"Base Metal Billycock",
+"Bloodhound",
+"Dapper Disguise",
+"Cut Throat Concierge",
+"Voodoo-Cursed Spy Soul",
+"Bootleg Base Metal Billycock",
+"Megapixel Beard",
+"Pom-Pommed Provocateur",
+"Powdered Practitioner",
+"After Dark",
+"Harmburg",
+"Rogue's Brogues",
+"Blood Banker",
+"Belgian Detective",
+"Escapist",
+"Frenchman's Formals",
+"L'homme Burglerre",
+"Bountiful Bow",
+"Bozo's Brogues",
+"Backstabber's Boomslang",
+"Ethereal Hood",
+"Hyperbaric Bowler",
+"Candyman's Cap",
+"Napoleon Complex",
+"Au Courant Assassin",
+"Aviator Assassin",
+"Rogue's Robe",
+"Nightmare Hunter",
+"Facepeeler",
+"Lady Killer",
+"Spycrab",
+"Sky Captain",
+"Rogue's Rabbit",
+"Shadowman's Shade",
+"Pocket Momma",
+"Puffy Provocateur",
+"Stealthy Scarf",
+"A Hat to Kill For",
+"Buttler",
+"Graylien",
+"Lurker's Leathers",
+"Showstopper",
+"Big Topper",
+"Dead Head",
+"Lurking Legionnaire",
+"Chicago Overcoat",
+"Brain-Warming Wear",
+"Upgrade",
+"Aloha Apparel",
+"Aristotle",
+"Murderer's Motif",
+"Dressperado",
+"Bandit's Boots",
+"Assassin's Attire",
+"Shutterbug",
+"Avian Amante",
+"Voodoo Vizier",
+"Bird's Eye Viewer",
+"Crabe de Chapeau",
+"Smoking Jacket"
+]
+
+unusualList = [
+"Burning Flames",
+"Circling Heart",
+"Circling Peace Sign",
+"Circling TF Logo",
+"Green Confetti",
+"Green Energy",
+"Haunted Ghosts",
+"Massed Flies",
+"Purple Confetti",
+"Purple Energy",
+"Scorching Flames",
+"Searing Plasma",
+"Sunbeams",
+"Vivid Plasma",
+"Blizzardy Storm",
+"Bubbling",
+"Nuts n' Bolts",
+"Orbiting Fire",
+"Orbiting Planets",
+"Smoking",
+"Steaming",
+"Stormy Storm",
+"Aces High",
+"Cloud 9",
+"Dead Presidents",
+"Disco Beat Down",
+"Kill-a-Watt",
+"Miami Nights",
+"Terror-Watt",
+"Aromatica",
+"Bee Swarm",
+"Chromatica",
+"Frisky Fireflies",
+"Kaleidoscope",
+"Prismatica",
+"Smoldering Spirits",
+"Verdatica",
+"Wandering Wisps",
+"Anti-Freeze",
+"Electrostatic",
+"Green Black Hole",
+"Memory Leak",
+"Overclocked",
+"Phosphorous",
+"Power Surge",
+"Roboactive",
+"Sulphurous",
+"Time Warp",
+"Death at Dusk",
+"Frostbite",
+"Molten Mallard",
+"Morning Glory",
+"Abduction",
+"Ancient Codex",
+"Atomic",
+"Electric Hat Protector",
+"Galactic Codex",
+"Magnetic Hat Protector",
+"Nebula",
+"Subatomic",
+"Voltaic Hat Protector"
+]
+
+halloweenList = [
+"Cauldron Bubbles",
+"Cloudy Moon",
+"Eerie Orbiting Fire",
+"Flaming Lantern",
+"Harvest Moon",
+"It's A Secret To Everybody",
+"Knifestorm",
+"Misty Skull",
+"Stormy 13th Hour"
+"Arcana",
+"Chiroptera Venenata",
+"Darkblaze",
+"Demonflame",
+"Hellfire",
+"Poisoned Shadows",
+"Something Burning This Way Comes"
+"Spellbound"
+"Amaranthine",
+"Bonzo The All-Gnawing",
+"Ghastly Ghosts Jr",
+"Haunted Phantasm Jr",
+"Stare From Beyond",
+"The Ooze",
+"Ancient Eldritch",
+"Death by Disco",
+"Eldritch Flame",
+"Ether Trail",
+"It's a mystery to everyone",
+"It's a puzzle to me",
+"Nether Trail",
+"Neutron Star",
+"Starstorm Insomnia",
+"Starstorm Slumber",
+"Tesla Coil",
+"Brain Drain",
+"Clairvoyance",
+"Galactic Gateway",
+"Head of Steam",
+"Omniscient Orb"
+"Open Mind",
+"Ring of Fire",
+"The Dark Doorway",
+"The Eldritch Opening",
+"Vicious Circle",
+"White Lightning",
+"Abyssal Aura",
+"Ethereal Essence",
+"Fifth Dimension",
+"Ghastly Grove",
+"Menacing Miasma",
+"Mystical Medley",
+"Twisted Radiance",
+"Valiant Vortex",
+"Verdant Vortex",
+"Vicious Vortex",
+"Violet Vortex",
+"Wicked Wood",
+"Gourdian Angel",
+"Gravelly Ghoul",
+"Green Giggler",
+"Laugh-O-Lantern",
+"Plum Prankster",
+"Pumpkin Party",
+"Pyroland Nightmare",
+"Vexed Volcanics"
+]
+
+smissmassList = [
+ "Defragmenting Reality",
+ "Fragmented Gluons",
+ "Fragmented Photons",
+ "Fragmented Quarks",
+ "Fragmenting Reality",
+ "Frozen Icefall",
+ "Pyroland Daydream",
+ "Refragmenting Reality",
+ "Snowblinded",
+ "Snowfallen",
+ "Sparkling Lights",
+ "Blighted Snowstorm",
+ "Distant Dream",
+ "Divine Desire",
+ "Frozen Fractals",
+ "Genus Plasmos",
+ "Lavender Landfall",
+ "Mirthful Mistletoe",
+ "Pale Nimbus",
+ "Serenus Lumen",
+ "Special Snowfall",
+ "Ventum Maris",
+ "Violent Wintertide"
+]
diff --git a/trader.py b/trader.py
new file mode 100644
index 0000000..dc276b9
--- /dev/null
+++ b/trader.py
@@ -0,0 +1,589 @@
+"""
+Copyright (C) 2021 Lexzach
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+"""
+
+import sys
+import time
+import asyncio
+import discord
+from discord.ext import commands
+import os.path
+import random
+from random import randint
+import re
+from items import itemList, unusualList
+import numpy
+import sqlite3
+from datetime import datetime
+client = commands.Bot(command_prefix='tf.')
+conn = sqlite3.connect("itemServ.db")
+itemSrv = conn.cursor()
+client.remove_command('help')
+# itemSrv.execute("CREATE TABLE users(user_id integer PRIMARY KEY, items list, crates_unboxed integer)")
+# conn.commit()
+items = itemList
+@client.event
+async def on_ready():
+ print("Bot has successfully connected.")
+ print("")
+ print("Bot made by:")
+ print(" _ _ ")
+ print("| | _____ __ _____ _ __| |_ ")
+ print("| |__/ -_) \ /|_ / _` / _| ' \ ")
+ print("|____\___/_\_\/__\__,_\__|_||_|")
+ print("Ver 1.3")
+ await client.change_presence(status=discord.Status.online, activity=discord.Game("tf.help"))
+def unboxCalc():
+ final = ""
+ itemUnboxed = items[randint(0,int(len(items))-1)]
+ quality = ""
+ unusual = False
+ if randint(0,100) > 98:
+ quality = "Elite Grade "
+ elif randint(0, 100) <= 8:
+ quality = "Commando Grade "
+ elif randint(0,100) <= 16:
+ quality = "Mercenary Grade "
+ if randint(1,100) == 100:
+ effect = unusualList[randint(0,int(len(unusualList))-1)]
+ quality = "Unusual "+quality
+ unusual = True
+ if randint(0,10) == 10:
+ quality = "Strange "+quality
+ if randint(0,10000) == 10000:
+ quality = "Community "
+ if quality == "":
+ final = itemUnboxed
+ else:
+ if unusual == False:
+ final = quality + itemUnboxed
+ else:
+ final = quality + itemUnboxed + " (★ Unusual Effect: "+effect+")"
+ print("Generated new item: "+final)
+ return final
+
+@client.command()
+async def help(ctx):
+ print("Command: help")
+ embedHelp = discord.Embed(title = "", color = discord.Colour.green())
+ embedHelp.add_field(name = 'TF2 Virtual Trading', value = "Bot Prefix: tf.\n\n Commands:\n tf.help - Show this menu\n tf.unbox - Unbox a new item\n tf.inventory (@user) - View your inventory or someone elses\n tf.trade (@user) - Trade with someone\n tf.collectors - Combine 10 copies of an item into one collectors copy")
+ embedHelp.set_footer(text="Direct any bugs to Lexzach#3215")
+ await ctx.send(embed=embedHelp)
+
+@client.command()
+@commands.cooldown(1, 1800, commands.BucketType.user)
+async def unbox(ctx):
+ bonus = False
+ bonusItem = ""
+ await ctx.message.delete(delay=60)
+ print("\nUser ID #"+str(ctx.author.id)+" started an unbox")
+ new = False
+ itemSrv.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='"+str(ctx.author.id)+"'")
+ conn.commit()
+ if int(itemSrv.fetchone()[0]) == 0:
+ itemSrv.execute("create table if not exists '"+str(ctx.author.id)+"'(items list)")
+ now = datetime.now()
+ now = now.strftime('%d/%m/%Y %H:%M:%S')
+ new = True
+ itemSrv.execute("INSERT INTO '"+str(ctx.author.id)+"'(items) VALUES('[Untradable] Tester Badge ( "+now+" )')")
+ conn.commit()
+ embedUnbox = discord.Embed(title = "", color = discord.Colour.green())
+ embedUnbox.add_field(name = '**Unboxing your loot.\n5**', value = "<@" + str(ctx.author.id)+">")
+ embedUnbox4 = discord.Embed(title = "", color = discord.Colour.green())
+ embedUnbox4.add_field(name = '**Unboxing your loot..\n4**', value = "<@" + str(ctx.author.id)+">")
+ embedUnbox3 = discord.Embed(title = "", color = discord.Colour.green())
+ embedUnbox3.add_field(name = '**Unboxing your loot...\n3**', value = "<@" + str(ctx.author.id)+">")
+ embedUnbox2 = discord.Embed(title = "", color = discord.Colour.green())
+ embedUnbox2.add_field(name = '**Unboxing your loot.\n2**', value = "<@" + str(ctx.author.id)+">")
+ embedUnbox1 = discord.Embed(title = "", color = discord.Colour.green())
+ embedUnbox1.add_field(name = '**Unboxing your loot..\n1**', value = "<@" + str(ctx.author.id)+">")
+ item = unboxCalc()
+ if random.randint(1,5) == 5:
+ bonus = True
+ bonusItem = "Mann Co. Supply Crate Key"
+ print("Generated new item: "+bonusItem)
+ if "Unusual" in item: #----------------------------------------------------------------------------Add effects
+ embedFound = discord.Embed(title = "", color = 0x8650AC)
+ elif "Elite Grade" in item:
+ embedFound = discord.Embed(title = "", color = 0xEB4B4B)
+ elif "Commando Grade" in item:
+ embedFound = discord.Embed(title = "", color = 0x8847FF)
+ elif "Commando Grade" in item:
+ embedFound = discord.Embed(title = "", color = 0x4B69FF)
+ elif "Strange" in item:
+ embedFound = discord.Embed(title = "", color = 0xCF6A32)
+ elif "Community" in item:
+ embedFound = discord.Embed(title = "", color = 0x70B04A)
+ elif "Mercenary Grade" in item:
+ embedFound = discord.Embed(title = "", color = 0x4B69FF)
+ else:
+ embedFound = discord.Embed(title = "", color = 0xFFD700)
+ if new == True:
+ embedFound.add_field(name = '**You unboxed:\n||'+item + "||\n||First unbox: [Untradable] Tester Badge ( "+now+" )"+'||**', value = "<@" + str(ctx.author.id)+">")
+ else:
+ if bonus == False:
+ embedFound.add_field(name = '**You unboxed:\n||'+item+'||**', value = "<@" + str(ctx.author.id)+">")
+ else:
+ embedFound.add_field(name = '**You unboxed:\n||'+item+"||\n||"+bonusItem+'||**', value = "<@" + str(ctx.author.id)+">")
+ item = item.replace("'", "")
+ item = item.replace('"', "")
+ itemSrv.execute("INSERT INTO '"+str(ctx.author.id)+"'(items) VALUES('"+item+"')")
+ if bonus == True:
+ itemSrv.execute("INSERT INTO '"+str(ctx.author.id)+"'(items) VALUES('"+bonusItem+"')")
+ conn.commit()
+ msg = await ctx.send(embed=embedUnbox)
+ await asyncio.sleep(1)
+ await msg.edit(embed=embedUnbox4)
+ await asyncio.sleep(1)
+ await msg.edit(embed=embedUnbox3)
+ await asyncio.sleep(1)
+ await msg.edit(embed=embedUnbox2)
+ await asyncio.sleep(1)
+ await msg.edit(embed=embedUnbox1)
+ await asyncio.sleep(1)
+ await msg.edit(embed=embedFound)
+
+
+@unbox.error
+async def unbox_error(ctx, error):
+ await ctx.message.delete(delay=10)
+ embedTooLong = discord.Embed(title = "", color = discord.Colour.red())
+ embedTooLong.add_field(name = "**You must wait "+str(round(error.retry_after/60)) +" minutes before your next unbox**".format(error.retry_after), value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=embedTooLong, delete_after=10)
+
+@client.command()
+async def inventory(ctx, *args):
+ await ctx.message.delete(delay=60)
+ someoneElse = False
+ error = False
+ if str(args) == "()":
+ inventory = discord.Embed(title = "", color = discord.Colour.blue())
+ itemSrv.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='"+str(ctx.author.id)+"'")
+ if int(itemSrv.fetchone()[0]) != 0:
+ itemSrv.execute("SELECT * FROM '"+ str(ctx.author.id)+"'")
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see their inventory")
+ else:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see their inventory, but they don't have any items")
+ error = True
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**You don't have an inventory yet!\nDo `tf.unbox` to get started!**", value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=userNotFound, delete_after=10)
+ else:
+ if True == (str(args)[5:-4].isdecimal()):
+ itemSrv.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='"+str(args)[5:-4]+"'")
+ if int(itemSrv.fetchone()[0]) == 0:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see the inventory of user ID#"+str(args)[5:-4]+" but they have no items")
+ error = True
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = '**User not found!**', value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=userNotFound, delete_after=10)
+ else:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see the inventory of user ID#"+str(args)[5:-4])
+ someoneElse = True
+ inventory = discord.Embed(title = "", color = discord.Colour.blue())
+ itemSrv.execute("SELECT * FROM '"+ str(args)[5:-4]+"'")
+ else:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see the inventory of user ID#"+str(args)[5:-4]+" but they have no items")
+ error = True
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = '**User not found!**', value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=userNotFound, delete_after=10)
+ # except:
+ # error = True
+ items = ""
+ if error == False:
+ if someoneElse == True:
+ itemSrv.execute("SELECT * FROM '"+str(str(args)[5:-4])+"' ORDER BY items")
+ else:
+ itemSrv.execute("SELECT * FROM '"+str(ctx.author.id)+"' ORDER BY items")
+ for x in itemSrv.fetchall():
+ items = items + str(x)[2:-3] + "\n"
+ if someoneElse == False:
+ inventory.add_field(name = '**Your inventory:**', value = "<@" + str(ctx.author.id)+">\n\n"+items)
+ else:
+ inventory.add_field(name = '**Other inventory:**', value = "<@" + str(args)[5:-4]+">'s Inventory\n\n"+items)
+ await ctx.send(embed=inventory, delete_after=120)
+
+@inventory.error
+async def inventory_error(ctx, error):
+ embedTooLong = discord.Embed(title = "", color = discord.Colour.red())
+ embedTooLong.add_field(name = '**An error has occured while checking inventory**', value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=embedTooLong, delete_after=10)
+
+@client.command()
+async def trade(ctx, *args):
+ try:
+ if str(args) == "()":
+ testing = discord.Embed(title = "", color = discord.Colour.green())
+ testing.add_field(name = '**Instructions have been sent to you**', value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=testing, delete_after=5)
+
+ user= client.get_user(ctx.author.id)
+ testing = discord.Embed(title = "", color = discord.Colour.green())
+ testing.add_field(name = '**Trading**', value = "Please enter the users discord ID (NOT their username)\n\nAlternatively, you can tag them in the trade message inside of a server.")
+ testingEmbed = await user.send(embed=testing)
+ error = False
+ await asyncio.sleep(0.5)
+ msg = await client.wait_for("message")
+ await testingEmbed.delete()
+ player = msg.content
+ else:
+ if True == (str(args)[5:-4].isdecimal()):
+ player = int(str(args)[5:-4])
+ error = False
+ user= client.get_user(ctx.author.id)
+ else:
+ failedTag = discord.Embed(title = "", color = discord.Colour.red())
+ failedTag.add_field(name = '**Please tag someone to trade.**', value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=failedTag, delete_after=10)
+ error = True
+ if str(player) != str(ctx.author.id):
+ itemSrv.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='"+str(player)+"'")
+ if int(itemSrv.fetchone()[0]) == 0:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see the inventory of user ID#"+str(player)+" but they have no items")
+ error = True
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = '**User not found!**', value = "<@" + str(ctx.author.id)+">")
+ await user.send(embed=userNotFound, delete_after=10)
+ else:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see the inventory of user ID#"+str(player))
+ someoneElse = True
+ inventory = discord.Embed(title = "", color = discord.Colour.blue())
+ itemSrv.execute("SELECT * FROM '"+ str(player)+"'")
+ items = ""
+ itemsList = []
+ if error == False:
+ itemSrv.execute("SELECT * FROM '"+str(player)+"' ORDER BY items")
+ for x in itemSrv.fetchall():
+ if "[Untradeable]" and "[Untradable]" not in str(x)[2:-3]:
+ items = items + str(x)[2:-3] + "\n"
+ itemsList.append(str(x)[2:-3])
+ inventory.add_field(name = '**Other inventory:**', value = "<@" + str(player)+">'s Inventory\n\n"+items)
+ # await ctx.send(embed=inventory)
+ # inventory = discord.Embed(title = "", color = discord.Colour.blue())
+ itemSrv.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='"+str(ctx.author.id)+"'")
+ if int(itemSrv.fetchone()[0]) != 0:
+ itemSrv.execute("SELECT * FROM '"+ str(ctx.author.id)+"'")
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see their inventory")
+ else:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see their inventory, but they don't have any items")
+ error = True
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**You don't have an inventory yet!\nDo `tf.unbox` to get started!**", value = "<@" + str(ctx.author.id)+">")
+ await user.send(embed=userNotFound, delete_after=10)
+ uitems = ""
+ uitemsList = []
+ itemSrv.execute("SELECT * FROM '"+str(ctx.author.id)+"' ORDER BY items")
+ for x in itemSrv.fetchall():
+ if "[Untradeable]" and "[Untradable]" not in str(x)[2:-3]:
+ uitems = uitems + str(x)[2:-3] + "\n"
+ uitemsList.append(str(x)[2:-3])
+ howto = discord.Embed(title = "", color = discord.Colour.green())
+ howto.add_field(name = '**How to trade:**', value = "1. Type the items you want to receive out of their inventory\n2. Type `next` to confirm\n3. Type the items you want send to them from your inventory\n4. Type `send` to send the trade\n\n**You can triple-click the text to highlight and copy it**")
+ how2Trade = await user.send(embed=howto)
+ inventory.add_field(name = '**Your inventory:**', value = "<@" + str(ctx.author.id)+">\n\n"+uitems)
+ inventoryEmbed = await user.send(embed=inventory)
+ send = discord.Embed(title = "", color = discord.Colour.green())
+ send.add_field(name = '**Send**', value = "None")
+ receive = discord.Embed(title = "", color = discord.Colour.green())
+ receive.add_field(name = '**Receive**', value = "None")
+ await asyncio.sleep(0.5)
+ receiveEmbed = await user.send(embed=receive)
+ await asyncio.sleep(0.5)
+ sendEmbed = await user.send(embed=send)
+ currentSend = []
+ currentReceive = []
+ currentSendText = ""
+ currentReceiveText = ""
+ await asyncio.sleep(1)
+ msg = await client.wait_for("message")
+ if msg.content in itemsList:
+ currentReceive.append(msg.content)
+ currentReceiveText = currentReceiveText + str(msg.content) + "\n"
+ receive.clear_fields()
+ receive.add_field(name = '**Receive**', value = currentReceiveText)
+ await receiveEmbed.edit(embed=receive)
+ while msg.content != "next":
+ msg = await client.wait_for("message", check=lambda message: message.author == ctx.author and isinstance(message.channel, discord.DMChannel))
+ if msg.content in itemsList and currentReceive.count(msg.content) < itemsList.count(msg.content):
+ currentReceive.append(msg.content)
+ currentReceiveText = currentReceiveText + str(msg.content) + "\n"
+ receive.clear_fields()
+ receive.add_field(name = '**Receive**', value = currentReceiveText)
+ await receiveEmbed.edit(embed=receive)
+ while msg.content != "send":
+ msg = await client.wait_for("message", check=lambda message: message.author == ctx.author and isinstance(message.channel, discord.DMChannel))
+ if msg.content in uitemsList and currentSend.count(msg.content) < uitemsList.count(msg.content):
+ currentSend.append(msg.content)
+ currentSendText = currentSendText + msg.content + "\n"
+ send.clear_fields()
+ send.add_field(name = '**Send**', value = currentSendText)
+ await sendEmbed.edit(embed=send)
+
+ await inventoryEmbed.delete()
+ await receiveEmbed.delete()
+ await sendEmbed.delete()
+ await how2Trade.delete()
+ confirmSend = discord.Embed(title = "", color = discord.Colour.purple())
+ if currentSendText != "" or currentReceiveText != "":
+ if currentSendText == "":
+ currentSendText = "Nothing"
+ if currentReceiveText == "":
+ currentReceiveText = "Nothing"
+ def check(reaction, user):
+ return reaction.message.id == confirm.id
+ confirmSend.add_field(name = '**Please confirm the trade.**', value = "\n**You will get:**\n`"+currentReceiveText+"`\n**You will lose:**\n`"+currentSendText+"`\n\n**All trades are final!\nOffer cannot be cancelled once sent.**")
+ confirm = await user.send(embed=confirmSend)
+ await confirm.add_reaction("✅")
+ await confirm.add_reaction("❌")
+ await asyncio.sleep(1)
+ reaction = await client.wait_for("reaction_add",check=check)
+ if str(reaction[0]) == "✅":
+ print("User ID #"+str(ctx.author.id)+" sent a trade to User ID #"+str(player)+"\n"+currentSendText+"\nfor\n"+currentReceiveText)
+ confirmSend = discord.Embed(title = "", color = discord.Colour.green())
+ confirmSend.add_field(name = '**Trade sent!**', value = "Your trade to <@" + str(player)+"> has been sent.")
+ confirm = await user.send(embed=confirmSend)
+ userDm = await client.fetch_user(int(player))
+ confirmSend = discord.Embed(title = "", color = discord.Colour.green())
+ confirmSend.add_field(name = '**User wants to trade:**', value = "<@" + str(ctx.author.id)+">"+" wants to trade with you.\n\n**You will lose:**\n`"+currentReceiveText+"`\n**You will get:**\n`"+currentSendText+"`\n\n**All trades are final!**")
+ confirm = await userDm.send(embed=confirmSend)
+ await confirm.add_reaction("✅")
+ await confirm.add_reaction("❌")
+ await asyncio.sleep(1)
+ reaction = await client.wait_for("reaction_add",check=check)
+ if str(reaction[0]) == "✅":
+ itemsList = []
+ itemSrv.execute("SELECT * FROM '"+str(player)+"' ORDER BY items")
+ for x in itemSrv.fetchall():
+ if "[Untradeable]" and "[Untradable]" not in str(x)[2:-3]:
+ items = items + str(x)[2:-3] + "\n"
+ itemsList.append(str(x)[2:-3])
+ uitemsList = []
+ itemSrv.execute("SELECT * FROM '"+str(ctx.author.id)+"' ORDER BY items")
+ for x in itemSrv.fetchall():
+ if "[Untradeable]" and "[Untradable]" not in str(x)[2:-3]:
+ uitems = uitems + str(x)[2:-3] + "\n"
+ uitemsList.append(str(x)[2:-3])
+
+
+ receiveChecksOut = False
+ sendChecksOut = False
+ if currentSendText == "Nothing":
+ sendChecksOut = True
+ if currentReceiveText == "Nothing":
+ receiveChecksOut = True
+ for x in currentReceive:
+ count=0
+ for y in itemsList:
+ if x == y:
+ count+=1
+ if count >= currentReceive.count(x):
+ receiveChecksOut = True
+ else:
+ receiveChecksOut = False
+
+ for x in currentSend:
+ count=0
+ for y in uitemsList:
+ if x == y:
+ count+=1
+ if count >= currentReceive.count(x):
+ sendChecksOut = True
+ else:
+ sendChecksOut = False
+
+ if sendChecksOut and receiveChecksOut:
+ print("User ID #"+str(player)+" accepted User ID #"+str(ctx.author.id)+"'s trade request")
+ now = datetime.now()
+ now = now.strftime('%d/%m/%Y %H:%M:%S')
+ if currentSendText != "Nothing":
+ for x in currentSend:
+ itemSrv.execute("INSERT INTO '"+str(player)+"'(items) VALUES('"+x+"')")
+ itemSrv.execute("DELETE FROM '"+str(ctx.author.id)+"' WHERE items='"+x+"' AND rowid = (SELECT MIN(rowid) FROM '"+str(ctx.author.id)+"' WHERE items='"+x+"')")
+ if currentReceiveText != "Nothing":
+ for x in currentReceive:
+ itemSrv.execute("INSERT INTO '"+str(ctx.author.id)+"'(items) VALUES('"+x+"')")
+ itemSrv.execute("DELETE FROM '"+str(player)+"' WHERE items='"+x+"' AND rowid = (SELECT MIN(rowid) FROM '"+str(player)+"' WHERE items='"+x+"')")
+ conn.commit()
+ tradeID = random.randint(1111111111111111111111,9999999999999999999999)
+ tradeDocument = open("trades.txt","a")
+ tradeDocument.write("Trade ID #"+str(tradeID)+"\n"+str(ctx.author.id)+" sent a trade to "+str(player)+", who accepted on "+now+"\nPlayer sent:\n"+currentSendText+"\nPlayer received:\n"+currentReceiveText+"\n")
+ tradeDocument.close()
+ userNotFound = discord.Embed(title = "", color = discord.Colour.green())
+ userNotFound.add_field(name = '**Trade accepted!**', value = "New items:\n`"+currentReceiveText+"`\n("+now+")")
+ userNotFound.set_footer(text="Trade ID #"+str(tradeID))
+ await user.send(embed=userNotFound)
+
+ userNotFound = discord.Embed(title = "", color = discord.Colour.green())
+ userNotFound.add_field(name = '**You accepted the trade.**', value = "New items:\n`"+currentSendText+"`\n("+now+")")
+ userNotFound.set_footer(text="Trade ID #"+str(tradeID))
+ await userDm.send(embed=userNotFound)
+ else:
+ await confirm.delete()
+ confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+ confirmSend.add_field(name = '**Trade failed.**', value = "Items in the trade are no longer available.")
+ confirm = await user.send(embed=confirmSend, delete_after=10)
+ await confirm.delete()
+ confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+ confirmSend.add_field(name = '**Trade failed.**', value = "Items in the trade are no longer available.")
+ confirm = await userDm.send(embed=confirmSend, delete_after=10)
+
+ else:
+ print("User ID #"+str(player)+" declined User ID #"+str(ctx.author.id)+"'s trade request")
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ now = datetime.now()
+ now = now.strftime('%d/%m/%Y %H:%M:%S')
+ userNotFound.add_field(name = '**Trade declined.**', value = "You declined "+"<@" + str(ctx.author.id)+">"+"'s trade\n("+now+")")
+ await userDm.send(embed=userNotFound)
+
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = '**Trade declined.**', value = "<@" + str(player)+"> declined your trade.\n("+now+")")
+ await user.send(embed=userNotFound)
+ else:
+ await confirm.delete()
+ confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+ confirmSend.add_field(name = '**Trade cancelled.**', value = "Your trade did not get sent.")
+ confirm = await user.send(embed=confirmSend, delete_after=10)
+ else:
+ confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+ confirmSend.add_field(name = '**Trade is empty.**', value = "You didn't enter an item to trade\nso there is no point in sending the offer.")
+ confirm = await user.send(embed=confirmSend, delete_after=10)
+ else:
+ confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+ confirmSend.add_field(name = '**You cannot trade with yourself.**', value = "The ID you requested to trade with is your ID.")
+ confirm = await user.send(embed=confirmSend, delete_after=10)
+ except asyncio.TimeoutError:
+ confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+ confirmSend.add_field(name = '**Timed out**', value = "You took too long to respond.")
+ confirm = await user.send(embed=confirmSend, delete_after=10)
+
+# @trade.error
+# async def trade_error(ctx,error):
+# confirmSend = discord.Embed(title = "", color = discord.Colour.red())
+# confirmSend.add_field(name = '**Something went wrong.**', value = "An unknown error occured while trading.\nPlease try again.")
+# confirm = await ctx.send(embed=confirmSend, delete_after=5)
+
+@client.command()
+async def collectors(ctx):
+ testing = discord.Embed(title = "", color = discord.Colour.green())
+ testing.add_field(name = '**Instructions have been sent to you**', value = "<@" + str(ctx.author.id)+">")
+ await ctx.send(embed=testing, delete_after=5)
+ error = False
+ user= client.get_user(ctx.author.id)
+ itemSrv.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='"+str(ctx.author.id)+"'")
+ if int(itemSrv.fetchone()[0]) != 0:
+ itemSrv.execute("SELECT * FROM '"+str(ctx.author.id)+"' ORDER BY items")
+ uitems = ""
+ uitemsList = []
+ for x in itemSrv.fetchall():
+ uitems = uitems + str(x)[2:-3] + "\n"
+ uitemsList.append(str(x)[2:-3])
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see their inventory")
+ else:
+ print("\nUser ID #"+str(ctx.author.id)+" requested to see their inventory, but they don't have any items")
+ error = True
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**You don't have an inventory yet!\nDo `tf.unbox` to get started!**", value = "<@" + str(ctx.author.id)+">")
+ await user.send(embed=userNotFound, delete_after=10)
+ if error == False:
+ inventory = discord.Embed(title = "", color = discord.Colour.blue())
+ inventory.add_field(name = '**Your inventory:**', value = "<@" + str(ctx.author.id)+">\n\n"+uitems)
+ inventoryEmbed = await user.send(embed=inventory)
+ testing = discord.Embed(title = "", color = discord.Colour.green())
+ testing.add_field(name = '**Collectors**', value = "Please enter items to make into a collectors item.\n(You need 10 unique copies [but not necessarily unique quality])")
+ testingEmbed = await user.send(embed=testing)
+ await asyncio.sleep(0.5)
+ msg = await client.wait_for("message", check=lambda message: message.author == ctx.author and isinstance(message.channel, discord.DMChannel))
+ await testingEmbed.delete()
+ await inventoryEmbed.delete()
+ itemToCollectors = msg.content
+ if msg.content in uitemsList:
+ if uitemsList.count(msg.content) >= 10:
+ count=0
+ textStuff = ""
+ while count != 10:
+ textStuff = textStuff+itemToCollectors+"\n"
+ count+=1
+ print(textStuff)
+ def check(reaction, user):
+ return reaction.message.id == confirm.id
+ confirmSend = discord.Embed(title = "", color = 0xAA0000)
+ confirmSend.add_field(name = '**Please confirm collectors process**', value = "\n**You will get:**\n`Collectors "+itemToCollectors+"`\n**You will lose:**\n`"+textStuff+"`\n\n**This process is irreversible**")
+ confirm = await user.send(embed=confirmSend)
+ await confirm.add_reaction("✅")
+ await confirm.add_reaction("❌")
+ await asyncio.sleep(1)
+ reaction = await client.wait_for("reaction_add",check=check)
+ if str(reaction[0]) == "✅":
+ await confirm.delete()
+ count = 0
+ while count != 10:
+ itemSrv.execute("DELETE FROM '"+str(ctx.author.id)+"' WHERE items='"+itemToCollectors+"' AND rowid = (SELECT MIN(rowid) FROM '"+str(ctx.author.id)+"' WHERE items='"+itemToCollectors+"')")
+ count+=1
+ itemToCollectors = "Collectors "+itemToCollectors
+ itemSrv.execute("INSERT INTO '"+str(ctx.author.id)+"'(items) VALUES('"+itemToCollectors+"')")
+ conn.commit()
+ collectors = discord.Embed(title = "", color = 0xAA0000)
+ collectors.add_field(name = '**Collectors Succeeded**', value = "New item:\n`"+itemToCollectors+"`")
+ await user.send(embed=collectors)
+ else:
+ await confirm.delete()
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**Collectors item failed**", value = "You cancelled the process")
+ await user.send(embed=userNotFound, delete_after=5)
+ else:
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**Collectors item failed**", value = "You don't have 10 unique copies of that item")
+ await user.send(embed=userNotFound, delete_after=5)
+ else:
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**Collectors item failed**", value = "That item isn't in your inventory")
+ await user.send(embed=userNotFound, delete_after=5)
+
+@client.command()
+async def give(ctx, args):
+ if int(ctx.author.id) == 495976318274502676 or int(ctx.author.id) == 123968463453552644:
+ player = args
+ userDm = await client.fetch_user(int(player))
+ user= client.get_user(ctx.author.id)
+ userNotFound = discord.Embed(title = "", color = discord.Colour.green())
+ userNotFound.add_field(name = "**Enter item**", value = "Enter item to give")
+ embed = await user.send(embed=userNotFound)
+ await asyncio.sleep(1)
+ msg = await client.wait_for("message", check=lambda message: message.author == ctx.author and isinstance(message.channel, discord.DMChannel))
+ def check(reaction, user):
+ return reaction.message.id == confirm.id
+ confirm = discord.Embed(title = "", color = discord.Colour.green())
+ confirm.add_field(name = '**Please confirm action**', value = "\n**Player to give item to:**\n`"+str(player)+"`\n**Item to give:**\n`"+msg.content+"`")
+ confirm = await user.send(embed=confirm)
+ await embed.delete()
+ await confirm.add_reaction("✅")
+ await confirm.add_reaction("❌")
+ await asyncio.sleep(1)
+ reaction = await client.wait_for("reaction_add",check=check)
+ if str(reaction[0]) == "✅":
+ await confirm.delete()
+ userNotFound = discord.Embed(title = "", color = discord.Colour.teal())
+ userNotFound.add_field(name = '**Support granted you:\n||'+msg.content+'||**', value = "<@" + str(player)+">")
+ embed = await userDm.send(embed=userNotFound)
+ itemSrv.execute("INSERT INTO '"+str(player)+"'(items) VALUES('"+msg.content+"')")
+ conn.commit()
+ else:
+ userNotFound = discord.Embed(title = "", color = discord.Colour.red())
+ userNotFound.add_field(name = "**Cancelled**", value = "Item didnt send.")
+ await user.send(embed=userNotFound, delete_after=5)
+
+client.run('replaceme')
diff --git a/trades.txt b/trades.txt
new file mode 100644
index 0000000..3726c40
--- /dev/null
+++ b/trades.txt
@@ -0,0 +1,23 @@
+Trade ID #8564013651357799077430
+495976318274502676 sent a trade to 782985934156988417, who accepted on 11/04/2021 00:34:09
+Player sent:
+Mercenary Grade Digit Divulger
+
+Player received:
+Nothing
+Trade ID #8453221216368250595051
+495976318274502676 sent a trade to 497768496403316736, who accepted on 11/04/2021 01:20:16
+Player sent:
+Mercenary Grade Horrific Head of Hare
+Runners Warm-Up
+Cheet Sheet
+
+Player received:
+Nothing
+Trade ID #9328924067207430370094
+495976318274502676 sent a trade to 782985934156988417, who accepted on 11/04/2021 01:28:54
+Player sent:
+Fowl Fists
+
+Player received:
+Nothing