diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 6fd0a37..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,41 +0,0 @@
-# Compiled Lua sources
-luac.out
-
-# luarocks build files
-*.src.rock
-*.zip
-*.tar.gz
-
-# Object files
-*.o
-*.os
-*.ko
-*.obj
-*.elf
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-*.def
-*.exp
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index ff3ebb6..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "tg"]
- path = tg
- url = https://github.com/SEEDTEAM/tg
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 8cdb845..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) 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
-this service 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 make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. 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.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the 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 a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE 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.
-
- 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
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- {description}
- Copyright (C) {year} {fullname}
-
- 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 2 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, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision 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, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- {signature of Ty Coon}, 1 April 1989
- Ty Coon, President of Vice
-
-This 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.
-
diff --git a/README.md b/README.md
index b8945da..11c3dce 100644
--- a/README.md
+++ b/README.md
@@ -1,506 +1,6 @@
-# [TeleSeed](https://telegram.me/TeleSeed)
-[](https://gitter.im/SEEDTEAM/TeleSeed?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+### BlackPlus > [GitHub](https://GitHub.com/Mehdi-HS/BlackPlus) | [Site](BlackPlus.ir) | [Channel](https://telegram.me/black_ch) | [Bot ID](https;//telegram.me/blackplus)
-**An advanced and powerful administration bot based on [yagop/telegram-bot](https://github.com/yagop/telegram-bot) licensed under the [GNU General Public License](https://github.com/SEEDTEAM/TeleSeed/blob/master/LICENSE)**.
-# Features
-* **A powerful antispam system with custom sensitivity for each group**
-* **Multiple realms (admin groups)**
-* **Recalcitrant to any kind of spamming (X/Y bots, name/photo changers, etc.)**
-* **Global banning**
-* **Broadcast to all groups**
-* **Group links**
-* **Kick, ban and unban by reply**
-* **Groups, ban and global ban list**
-* **Logging anything that happens in a group**
-* **Invitation by username**
-* **Group administration via private messages**
-* **Only mods, owner and admin can add bots**
-* **Arabic lock**
-* **And more!**
-**Table of Contents**
-- [TeleSeed](#teleseed)
-- [Features](#features)
-- [Commands](#commands)
- - [Admins commands](#admins-commands)
- - [Realm creation](#realm-creation)
- - [Group creation](#group-creation)
- - [Adding and removing realms](#add-or-remove-realms)
- - [Adding and removing groups](#add-or-remove-groups)
- - [Leaving groups](#leaving)
- - [Everything about groups](#everything-about-groups)
- - [Setting descriptions in realm](#setting-description-in-realm)
- - [Setting group names in realm](#setting-group-name-in-realm)
- - [Setting rules in realm](#setting-rules-in-realm)
- - [Locking group names/photos/flood/members in realm](#lock-groups-namefloodphotomember-in-realm)
- - [Unlocking group names/photos/flood/members](#unlock-groups-namefloodphotomember)
- - [Group settings in realm](#group-setting-in-realm)
- - [Adding admins](#add-admin)
- - [Removing admins](#remove-admin)
- - [Admin/group listing in realm](#adminsgroup-list-in-realm)
- - [Broadcasting](#broadcast)
- - [Realm help](#realm-help)
- - [Global ban commands](#global-ban-commands)
- - [Set group owner](#set-group-owner)
- - [Bot stats](#bot-stats)
- - [Owner and mod commands](#owners-and-mods-commands)
- - [Hammer](#hammer)
- - [Locking a group's name/members/bots/arabic/flood](#group-namememberarabicfloodbots-lock)
- - [Unlocking a group's name/members/bots/arabic/flood](#group-namememberarabicfloodbots-unlock)
- - [Cleaning a group's modlist/rules/about/members](#group-modlistrulesaboutmember-clean)
- - [Seting a group's rules/about](#set-groups-rulesabout)
- - [Setting or changing a group's owner](#setting-or-changing-group-photo)
- - [Setting or changing a group's photo](#setting-or-changing-group-photo)
- - [Changing a group's name](#changing-group-name)
- - [Group links](#group-link)
- - [Promoting and demoting mods](#promote-and-demote-mods)
- - [Resolving usernames](#resolve-username)
- - [Flood sensitivity](#flood-sensitivity)
- - [Group rules and about](#group-rules-and-about)
- - [Group settings](#group-settings)
- - [Modlist](#modlist)
- - [Help](#help)
- - [Owner](#owner)
- - [Save and Get](#save-and-get)
- - [Id](#id)
- - [Group stats](#group-stats)
- - [Member list](#member-list)
- - [Group help](#group-help)
- - [In private commands](#in-private-commands)
- - [Hammer](#hammer)
- - [Cleaning](#cleaning)
- - [Setting flood sensitivity](#setting-flood-sensitivity)
- - [Locking a group's members/name](#lock-groups-membername)
- - [Unlocking a group's members/name](#unlock-groups-membername)
- - [Group link](#group-link)
- - [Changing name/rules](#change-namerulesname)
- - [Group log](#group-log)
- - [Join](#join)
-- [Installation](#installation)
- - [One command](#one-command)
- - [Realm configuration](#realm-configuration)
-- [Support and development](#support-and-development)
-- [Special thanks to:](#special-thanks-to)
-- [Our team!](#our-team)
-
-# Commands
-## Admins commands
-**Only admins and sudo users can run these commands.**
-### Group creation
->[!/]creategroup [group name]
->
->>[!/]creategroup SEED
->>>will create a group
->>>
->>>_Only works in realms for admins but, sudo users can use it everywhere_
-
-### Realm creation
->[!/]createrealm [realm name]
->
->>[!/]createrealm SEED
->>>will create a realm
->>>
->>>_Only works in realms for admins but, sudo users can use it everywhere_
-
-###Add or remove realms
->[!/]add realm
->>This command will add that group
->
->[!/]rem realm
->>This command will remove that group
-
-
-###Add or remove groups
->[!/]add
->>This command will add that group
->
->[!/]rem
->>This command will remove that group
-
-###Leaving
->[!/]leave
->>Bot will leave that group
-
-###Everything about groups
->[!/]all
->>This command will return everything about that group
->
->[!/]all [group_id]
->>_Only onwer, admin and sudo users can use this command_
-
-
-### Setting description in realm
-> [!/]setabout [group_id] [text]
->>[!/]setabout 123456789 about
->>>This command will set [text] as description of [group_id]
-
-
-### Setting group name in realm
-> [!/]setname [group_id] [text]
->>[!/]setname 123456789 SEED
->>>This command will set [text] as name of [group_id]
-
-### Setting rules in realm
-> [!/]setrules [group_id] [text]
->>[!/]setrules 123456789 rules !
->>>This command will set [text] as rules of [group_id]
-
-
-### Lock groups name|flood|photo|member in realm
-> [!/]lock [group_id] [name|flood|photo|member]
->>[!/]lock 123456789 name
->>>This command will lock name|flood|photo|member of [group_id]
-
-
-### Unlock groups name|flood|photo|member
-> [!/]unlock [group_id] [name|flood|photo|member]
->>[!/]unlock 123456789 name
->>>This command will unlock name|flood|photo|member of [group_id]
-
-## Group setting in realm
->[!/]setting [group_id]
->>[!/]setting 12345678
->>>This command will return settings of [group_id]
-
-### Add admin
->[!/]addadmin [username]
->>[!/]addadmin @username
->>>This command will add username as admin
->>>
->>>_Only works in realms_
-
-### Remove admin
->[!/]removeadmin [username]
->
->>[!/]removeadmin @username
->>>This command will add username as admin
->>>
->>>_Only works in realms_ [username]
-
-### Admins|group list in realm
->[!/]list [admins|groups]
->>[!/]list groups
->>>This command will return admins|groups list
-
-### Broadcast
->[!/]broadcast [text]
->>[!/]broadcast Hello !
->>>This command will send text to all groups
->>>
->>>_Only sudo users can run this command_
->
->[!/]bc [group_id] [text]
->>[!/]bc 123456789 Hello !
->>>This command will send text to [group_id]
-
-##Global ban commands
->[!/]banall [id]
->>[!/]banall 123456789
->>>This commands will globally ban [id]
->
->/sync_gbans
->>Sync your global bans with teleseed
->
->[!/]unbanall [id]
->>[!/]unbanall 123456789
->>>This commands will remove [id] from global bans
->
->[!/]gbanlist
->>This command will return global bans ids
->
->[!/]banlist [group_id]
->>[!/]banlist 123456789
->>>This command will return banned user of [group_id]
-
-### Set group owner
->[!/]setgpowner [group_id] [User_id]
->>[!/]setgpowner 123456789 987654321
->>>This command will set [User_id] as the owner of [group_id]
-
-### Bot stats
->[!/]stats teleseed
->>This command will return bot stats
-
-# Realm Help
->[!/]help
->>Get realm commands list
-
-
-
-
-## owners and mods commands
-
-_Sudo users and admins can also use this commands in all groups_
-
-### Hammer
-
->[!/]kick [username|id]
->>[!/]kick @useranme
->>[!/]kick 123456789
->>>This command will remove that user
->
->[!/]ban [username|id]
->>[!/]ban @username
->>[!/]ban 123456789
->>>this command will ban and remove that user
->
->[!/]unban [id]
->>[!/]unban 12345678
->>>This command will unban that user
->
->[!/]banlist
->>This command will return bans list
-
-### group name|member|arabic|flood|bots lock
->[!/]lock [name|member|arabic|flood|bots]
->>[!/]lock flood
->>>This command will lock name|member|arabic|flood|bots of groups
-
-### group name|member|arabic|flood|bots unlock
->[!/]unlock [name|member|arabic|flood|bots]
->>[!/]unlock flood
->>>This command will unlock name|member|arabic|flood|bots of groups
-
-### Group modlist|rules|about|member clean
->[!/]clean [modlist|rules|about|member]
->>[!/]clean modlist
->>>This command will clean modlist|rules|about|member
->>>_/clean member will kick all users except owner,admins and bot and it's for owners only_
-
-### Set groups rules|about
->[!/]set [rules|about] [text]
->>[!/]set rules don't spam!
->>
->>No NSFW
->>> This command will set [text] as the rules|about of groups
-
-### Setting or changing group owner
->[!/]setowner [id]
->>[!/]setowner 123456789
->>>This command will set id as owner of that group
-
-### Setting or changing group photo
->[!/]setphoto
->> This command will change or set group photo
->>_also locks photo_
-
-### Changing Group name
->[!/]setname [name]
->>[!/]setname SEED
->>>This command will set [name] as name of groups
-
-### Group link
->[!/]newlink
->>This command will revoke group link
->
->[!/]link
->>This command will return group link
-
-### Promote and demote mods
->[!/]promote [username]
->>[!/]promote @username
->>>This command will promote @username as moderator
->
->[!/]demote [username]
->>[!/]demote @username
->>> This command will demote @username
-
-### Resolve username
->[!/]res [username]
->>[!/]res @username
->>>This command will return info about that username
-
-### Flood sensitivity
->[!/]setflood [value]
->>[!/]setflood 15
->>> will set flood sensitivity to [value]
-
-### Group rules and about
->[!/]about
->>This command will return group description
->
->[!/]rules
->>This command will return group rules
->>>_normal users can use it too_
-
-### Group settings
->[!/]setting
->>This command will return group settings
-
-### modlist
->[!/]modlist
->>This command will return group moderators
->>>_normal users can use it too_
-
-###Help
->[!/]help
-
-### Owner
->[!/]owner
->>This command will return owners id
-
-### Save and get
->[!/]save [title] [text]
->>[!/]save spam Don't spam !
->>>This command will save text as that title
->
->[!/]get [title]
->>[!/]get spam
->>>This command will return text of that title
-
-### Id
->[!/]id
->>This command will return user or group id
->>_can be triggered by reply_
->>
->>_Normal users can use it_
-
-### group stats
->[!/]stats
->>This command will return group message statistic in a .txt file
->
->[!/]statslist
->>This command will return group message statistic
-
-### member list
->[!/]who
->>This command will return member list in a .txt file
->
->[!/]wholist
->>This command will return member list
-
-# Group Help
->[!/]help
->>Get commands list
-
-
-
-## in private commands
-
-**These commands only works in bots private**
-
-### Hammer
->[!/]owners group_id [kick|ban|unban] user_id
->>[!/]owners 1234567 kick 1234567
-
-### cleaning
->[!/]owners group_id clean [modlist|rules|about]
->>[!/]owners 1234567 clean modlist
-
-### setting flood sensitivity
->[!/]owners group_id setflood value
->>[!/]owners 1234567 setflood 17
-
-### lock groups member|name
->[!/]owners group_id lock [member|name]
->>[!/]owners 1234567 lock member
-
-#### unlock groups member|name
->[!/]owner group_id unlock [member|name]
->>[!/]owners 1234567 unlock name
-
-### Group link
->[!/]owners group_id get link
->>[!/]owners 1234567 get link
->
->[!/]owners group_id new link
->>[!/]owners 1234567 new link
-
-### change name|rules|name
->[!/]changename [group_id] [name]
->>[!/]changename 123456789 SEED
->
->[!/]changrules [group_id] [rules]
->>[!/]changrules 123456789 rules !
->
->[!/]changeabout [group_id] [about]
->>[!/]changeabout 123456789 about !
-
-### Group log
->[!/]loggroup [group_id]
->>[!/]loggroup 123456789
-
-### Join
->[!/]oin [group_id]
->> This command will add user in [group_id]
-
-
-**U can use both "/" and "!"**
-
-# Installation
-
-```sh
-# Install dependencies.
-# Tested on Ubuntu 14.04. For other OSs, check out https://github.com/yagop/telegram-bot/wiki/Installation
-sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev make unzip git redis-server g++ libjansson-dev libpython-dev expat libexpat1-dev
-
-# Let's install the bot.
-cd $HOME
-git clone https://github.com/SEEDTEAM/TeleSeed.git
-cd TeleSeed
-chmod +x launch.sh
-./launch.sh install
-./launch.sh # Enter a phone number & confirmation code.
-```
-### One command
-To install everything in one command (useful for VPS deployment) on Debian-based distros, use:
-```sh
-#https://github.com/yagop/telegram-bot/wiki/Installation
-sudo apt-get update; sudo apt-get upgrade -y --force-yes; sudo apt-get dist-upgrade -y --force-yes; sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson* libpython-dev make unzip git redis-server g++ -y --force-yes && git clone https://github.com/SEEDTEAM/TeleSeed.git && cd TeleSeed && chmod +x launch.sh && ./launch.sh install && ./launch.sh
-```
-### Realm configuration
-
-After you run the bot for first time, send it `!id`. Get your ID and stop the bot.
-
-Open ./data/config.lua and add your ID to the "sudo_users" section in the following format:
-```
- sudo_users = {
- 110626080,
- 103649648,
- 111020322,
- 0,
- YourID
- }
-```
-Then restart the bot.
-
-Create a realm using the `!createrealm` command.
-
-# Support and development
-
-Check out this [tutorial by Telegram Geeks](http://telegramgeeks.com/2016/01/teleseed-tutorial/) for further assistance with setup and installation.
-
-**Do not contact us** in private for support.
-Join our bot development group by sending `/join 56670147` to [@TeleSeed](https://telegram.me/TeleSeed)
-
-# Special thanks to
-[@seyedan25](https://telegram.me/seyedan25)
-
-For managing [@teleseed](https://telegram.me/TeleSeed) on Telegram.
-
-[@Vamptacus](https://telegram.me/Vamptacus)
-
-For graphic designs.
-
-[topkecleon](https://github.com/topkecleon)
-
-[Juan Potato](https://github.com/JuanPotato)
-
-# Our team!
-
-[Alphonse](https://github.com/hmon) ([Telegram](https://telegram.me/iwals))
-
-[I M /-\ N](https://github.com/imandaneshi) ([Telegram](https://telegram.me/imandaneshi))
-
-[Siyanew](https://github.com/Siyanew) ([Telegram](https://telegram.me/Siyanew))
-
-[Rondoozle](https://github.com/Rondoozle) ([Telegram](https://telegram.me/POTUS))
-
-###Our Telegram channels:
-
-English: [@TeleSeedCH](https://telegram.me/teleseedch)
-
-Persian: [@IranSeed](https://telegram.me/iranseed)
diff --git a/bot/seedbot.lua b/bot/seedbot.lua
deleted file mode 100644
index 8dc5ac4..0000000
--- a/bot/seedbot.lua
+++ /dev/null
@@ -1,520 +0,0 @@
-package.path = package.path .. ';.luarocks/share/lua/5.2/?.lua'
- ..';.luarocks/share/lua/5.2/?/init.lua'
-package.cpath = package.cpath .. ';.luarocks/lib/lua/5.2/?.so'
-
-require("./bot/utils")
-
-VERSION = '2'
-
--- This function is called when tg receive a msg
-function on_msg_receive (msg)
- if not started then
- return
- end
-
- local receiver = get_receiver(msg)
- print (receiver)
-
- --vardump(msg)
- msg = pre_process_service_msg(msg)
- if msg_valid(msg) then
- msg = pre_process_msg(msg)
- if msg then
- match_plugins(msg)
- if redis:get("bot:markread") then
- if redis:get("bot:markread") == "on" then
- mark_read(receiver, ok_cb, false)
- end
- end
- end
- end
-end
-
-function ok_cb(extra, success, result)
-end
-
-function on_binlog_replay_end()
- started = true
- postpone (cron_plugins, false, 60*5.0)
-
- _config = load_config()
-
- -- load plugins
- plugins = {}
- load_plugins()
-end
-
-function msg_valid(msg)
- -- Don't process outgoing messages
- if msg.out then
- print('\27[36mNot valid: msg from us\27[39m')
- return false
- end
-
- -- Before bot was started
- if msg.date < now then
- print('\27[36mNot valid: old msg\27[39m')
- return false
- end
-
- if msg.unread == 0 then
- print('\27[36mNot valid: readed\27[39m')
- return false
- end
-
- if not msg.to.id then
- print('\27[36mNot valid: To id not provided\27[39m')
- return false
- end
-
- if not msg.from.id then
- print('\27[36mNot valid: From id not provided\27[39m')
- return false
- end
-
- if msg.from.id == our_id then
- print('\27[36mNot valid: Msg from our id\27[39m')
- return false
- end
-
- if msg.to.type == 'encr_chat' then
- print('\27[36mNot valid: Encrypted chat\27[39m')
- return false
- end
-
- if msg.from.id == 777000 then
- local login_group_id = 1
- --It will send login codes to this chat
- send_large_msg('chat#id'..login_group_id, msg.text)
- end
-
- return true
-end
-
---
-function pre_process_service_msg(msg)
- if msg.service then
- local action = msg.action or {type=""}
- -- Double ! to discriminate of normal actions
- msg.text = "!!tgservice " .. action.type
-
- -- wipe the data to allow the bot to read service messages
- if msg.out then
- msg.out = false
- end
- if msg.from.id == our_id then
- msg.from.id = 0
- end
- end
- return msg
-end
-
--- Apply plugin.pre_process function
-function pre_process_msg(msg)
- for name,plugin in pairs(plugins) do
- if plugin.pre_process and msg then
- print('Preprocess', name)
- msg = plugin.pre_process(msg)
- end
- end
-
- return msg
-end
-
--- Go over enabled plugins patterns.
-function match_plugins(msg)
- for name, plugin in pairs(plugins) do
- match_plugin(plugin, name, msg)
- end
-end
-
--- Check if plugin is on _config.disabled_plugin_on_chat table
-local function is_plugin_disabled_on_chat(plugin_name, receiver)
- local disabled_chats = _config.disabled_plugin_on_chat
- -- Table exists and chat has disabled plugins
- if disabled_chats and disabled_chats[receiver] then
- -- Checks if plugin is disabled on this chat
- for disabled_plugin,disabled in pairs(disabled_chats[receiver]) do
- if disabled_plugin == plugin_name and disabled then
- local warning = 'Plugin '..disabled_plugin..' is disabled on this chat'
- print(warning)
- send_msg(receiver, warning, ok_cb, false)
- return true
- end
- end
- end
- return false
-end
-
-function match_plugin(plugin, plugin_name, msg)
- local receiver = get_receiver(msg)
-
- -- Go over patterns. If one matches it's enough.
- for k, pattern in pairs(plugin.patterns) do
- local matches = match_pattern(pattern, msg.text)
- if matches then
- print("msg matches: ", pattern)
-
- if is_plugin_disabled_on_chat(plugin_name, receiver) then
- return nil
- end
- -- Function exists
- if plugin.run then
- -- If plugin is for privileged users only
- if not warns_user_not_allowed(plugin, msg) then
- local result = plugin.run(msg, matches)
- if result then
- send_large_msg(receiver, result)
- end
- end
- end
- -- One patterns matches
- return
- end
- end
-end
-
--- DEPRECATED, use send_large_msg(destination, text)
-function _send_msg(destination, text)
- send_large_msg(destination, text)
-end
-
--- Save the content of _config to config.lua
-function save_config( )
- serialize_to_file(_config, './data/config.lua')
- print ('saved config into ./data/config.lua')
-end
-
--- Returns the config from config.lua file.
--- If file doesn't exist, create it.
-function load_config( )
- local f = io.open('./data/config.lua', "r")
- -- If config.lua doesn't exist
- if not f then
- print ("Created new config file: data/config.lua")
- create_config()
- else
- f:close()
- end
- local config = loadfile ("./data/config.lua")()
- for v,user in pairs(config.sudo_users) do
- print("Allowed user: " .. user)
- end
- return config
-end
-
--- Create a basic config.json file and saves it.
-function create_config( )
- -- A simple config with basic plugins and ourselves as privileged user
- config = {
- enabled_plugins = {
- "onservice",
- "inrealm",
- "ingroup",
- "inpm",
- "banhammer",
- "stats",
- "anti_spam",
- "owners",
- "arabic_lock",
- "set",
- "get",
- "broadcast",
- "download_media",
- "invite",
- "all",
- "leave_ban",
- "admin"
- },
- sudo_users = {110626080,103649648,143723991,111020322,0,tonumber(our_id)},--Sudo users
- disabled_channels = {},
- moderation = {data = 'data/moderation.json'},
- about_text = [[Teleseed v2 - Open Source
-An advance Administration bot based on yagop/telegram-bot
-
-https://github.com/SEEDTEAM/TeleSeed
-
-Admins
-@iwals [Founder]
-@imandaneshi [Developer]
-@Rondoozle [Developer]
-@seyedan25 [Manager]
-
-Special thanks to
-awkward_potato
-Siyanew
-topkecleon
-Vamptacus
-
-Our channels
-@teleseedch [English]
-@iranseed [persian]
-]],
- help_text_realm = [[
-Realm Commands:
-
-!creategroup [Name]
-Create a group
-
-!createrealm [Name]
-Create a realm
-
-!setname [Name]
-Set realm name
-
-!setabout [GroupID] [Text]
-Set a group's about text
-
-!setrules [GroupID] [Text]
-Set a group's rules
-
-!lock [GroupID] [setting]
-Lock a group's setting
-
-!unlock [GroupID] [setting]
-Unock a group's setting
-
-!wholist
-Get a list of members in group/realm
-
-!who
-Get a file of members in group/realm
-
-!type
-Get group type
-
-!kill chat [GroupID]
-Kick all memebers and delete group
-
-!kill realm [RealmID]
-Kick all members and delete realm
-
-!addadmin [id|username]
-Promote an admin by id OR username *Sudo only
-
-!removeadmin [id|username]
-Demote an admin by id OR username *Sudo only
-
-!list groups
-Get a list of all groups
-
-!list realms
-Get a list of all realms
-
-!log
-Grt a logfile of current group or realm
-
-!broadcast [text]
-!broadcast Hello !
-Send text to all groups
-Only sudo users can run this command
-
-!bc [group_id] [text]
-!bc 123456789 Hello !
-This command will send text to [group_id]
-
-
-**U can use both "/" and "!"
-
-
-*Only admins and sudo can add bots in group
-
-
-*Only admins and sudo can use kick,ban,unban,newlink,setphoto,setname,lock,unlock,set rules,set about and settings commands
-
-*Only admins and sudo can use res, setowner, commands
-]],
- help_text = [[
-Commands list :
-
-!kick [username|id]
-You can also do it by reply
-
-!ban [ username|id]
-You can also do it by reply
-
-!unban [id]
-You can also do it by reply
-
-!who
-Members list
-
-!modlist
-Moderators list
-
-!promote [username]
-Promote someone
-
-!demote [username]
-Demote someone
-
-!kickme
-Will kick user
-
-!about
-Group description
-
-!setphoto
-Set and locks group photo
-
-!setname [name]
-Set group name
-
-!rules
-Group rules
-
-!id
-return group id or user id
-
-!help
-
-!lock [member|name|bots|leave]
-Locks [member|name|bots|leaveing]
-
-!unlock [member|name|bots|leave]
-Unlocks [member|name|bots|leaving]
-
-!set rules
-Set as rules
-
-!set about
-Set as about
-
-!settings
-Returns group settings
-
-!newlink
-create/revoke your group link
-
-!link
-returns group link
-
-!owner
-returns group owner id
-
-!setowner [id]
-Will set id as owner
-
-!setflood [value]
-Set [value] as flood sensitivity
-
-!stats
-Simple message statistics
-
-!save [value]
-Save as [value]
-
-!get [value]
-Returns text of [value]
-
-!clean [modlist|rules|about]
-Will clear [modlist|rules|about] and set it to nil
-
-!res [username]
-returns user id
-"!res @username"
-
-!log
-will return group logs
-
-!banlist
-will return group ban list
-
-**U can use both "/" and "!"
-
-
-*Only owner and mods can add bots in group
-
-
-*Only moderators and owner can use kick,ban,unban,newlink,link,setphoto,setname,lock,unlock,set rules,set about and settings commands
-
-*Only owner can use res,setowner,promote,demote and log commands
-
-]]
- }
- serialize_to_file(config, './data/config.lua')
- print('saved config into ./data/config.lua')
-end
-
-function on_our_id (id)
- our_id = id
-end
-
-function on_user_update (user, what)
- --vardump (user)
-end
-
-function on_chat_update (chat, what)
-
-end
-
-function on_secret_chat_update (schat, what)
- --vardump (schat)
-end
-
-function on_get_difference_end ()
-end
-
--- Enable plugins in config.json
-function load_plugins()
- for k, v in pairs(_config.enabled_plugins) do
- print("Loading plugin", v)
-
- local ok, err = pcall(function()
- local t = loadfile("plugins/"..v..'.lua')()
- plugins[v] = t
- end)
-
- if not ok then
- print('\27[31mError loading plugin '..v..'\27[39m')
- print(tostring(io.popen("lua plugins/"..v..".lua"):read('*all')))
- print('\27[31m'..err..'\27[39m')
- end
-
- end
-end
-
-
--- custom add
-function load_data(filename)
-
- local f = io.open(filename)
- if not f then
- return {}
- end
- local s = f:read('*all')
- f:close()
- local data = JSON.decode(s)
-
- return data
-
-end
-
-function save_data(filename, data)
-
- local s = JSON.encode(data)
- local f = io.open(filename, 'w')
- f:write(s)
- f:close()
-
-end
-
--- Call and postpone execution for cron plugins
-function cron_plugins()
-
- for name, plugin in pairs(plugins) do
- -- Only plugins with cron function
- if plugin.cron ~= nil then
- plugin.cron()
- end
- end
-
- -- Called again in 2 mins
- postpone (cron_plugins, false, 120)
-end
-
--- Start and load values
-our_id = 0
-now = os.time()
-math.randomseed(now)
-started = false
diff --git a/bot/utils.lua b/bot/utils.lua
deleted file mode 100644
index 2c2498e..0000000
--- a/bot/utils.lua
+++ /dev/null
@@ -1,958 +0,0 @@
-URL = require "socket.url"
-http = require "socket.http"
-https = require "ssl.https"
-ltn12 = require "ltn12"
-serpent = require "serpent"
-feedparser = require "feedparser"
-
-json = (loadfile "./libs/JSON.lua")()
-mimetype = (loadfile "./libs/mimetype.lua")()
-redis = (loadfile "./libs/redis.lua")()
-JSON = (loadfile "./libs/dkjson.lua")()
-
-http.TIMEOUT = 10
-
-
-function get_receiver(msg)
- if msg.to.type == 'user' then
- return 'user#id'..msg.from.id
- end
- if msg.to.type == 'chat' then
- return 'chat#id'..msg.to.id
- end
- if msg.to.type == 'encr_chat' then
- return msg.to.print_name
- end
-end
-
-function is_chat_msg( msg )
- if msg.to.type == 'chat' then
- return true
- end
- return false
-end
-
-function string.random(length)
- local str = "";
- for i = 1, length do
- math.random(97, 122)
- str = str..string.char(math.random(97, 122));
- end
- return str;
-end
-
-function string:split(sep)
- local sep, fields = sep or ":", {}
- local pattern = string.format("([^%s]+)", sep)
- self:gsub(pattern, function(c) fields[#fields+1] = c end)
- return fields
-end
-
--- DEPRECATED
-function string.trim(s)
- print("string.trim(s) is DEPRECATED use string:trim() instead")
- return s:gsub("^%s*(.-)%s*$", "%1")
-end
-
--- Removes spaces
-function string:trim()
- return self:gsub("^%s*(.-)%s*$", "%1")
-end
-
-function get_http_file_name(url, headers)
- -- Eg: foo.var
- local file_name = url:match("[^%w]+([%.%w]+)$")
- -- Any delimited alphanumeric on the url
- file_name = file_name or url:match("[^%w]+(%w+)[^%w]+$")
- -- Random name, hope content-type works
- file_name = file_name or str:random(5)
-
- local content_type = headers["content-type"]
-
- local extension = nil
- if content_type then
- extension = mimetype.get_mime_extension(content_type)
- end
- if extension then
- file_name = file_name.."."..extension
- end
-
- local disposition = headers["content-disposition"]
- if disposition then
- -- attachment; filename=CodeCogsEqn.png
- file_name = disposition:match('filename=([^;]+)') or file_name
- end
-
- return file_name
-end
-
--- Saves file to /tmp/. If file_name isn't provided,
--- will get the text after the last "/" for filename
--- and content-type for extension
-function download_to_file(url, file_name)
- print("url to download: "..url)
-
- local respbody = {}
- local options = {
- url = url,
- sink = ltn12.sink.table(respbody),
- redirect = true
- }
-
- -- nil, code, headers, status
- local response = nil
-
- if url:starts('https') then
- options.redirect = false
- response = {https.request(options)}
- else
- response = {http.request(options)}
- end
-
- local code = response[2]
- local headers = response[3]
- local status = response[4]
-
- if code ~= 200 then return nil end
-
- file_name = file_name or get_http_file_name(url, headers)
-
- local file_path = "/tmp/"..file_name
- print("Saved to: "..file_path)
-
- file = io.open(file_path, "w+")
- file:write(table.concat(respbody))
- file:close()
-
- return file_path
-end
-
-function vardump(value)
- print(serpent.block(value, {comment=false}))
-end
-
--- taken from http://stackoverflow.com/a/11130774/3163199
-function scandir(directory)
- local i, t, popen = 0, {}, io.popen
- for filename in popen('ls -a "'..directory..'"'):lines() do
- i = i + 1
- t[i] = filename
- end
- return t
-end
-
--- http://www.lua.org/manual/5.2/manual.html#pdf-io.popen
-function run_command(str)
- local cmd = io.popen(str)
- local result = cmd:read('*all')
- cmd:close()
- return result
-end
-
--- User has privileges
-function is_sudo(msg)
- local var = false
- -- Check users id in config
- for v,user in pairs(_config.sudo_users) do
- if user == msg.from.id then
- var = true
- end
- end
- return var
-end
-
--- Returns the name of the sender
-function get_name(msg)
- local name = msg.from.first_name
- if name == nil then
- name = msg.from.id
- end
- return name
-end
-
--- Returns at table of lua files inside plugins
-function plugins_names( )
- local files = {}
- for k, v in pairs(scandir("plugins")) do
- -- Ends with .lua
- if (v:match(".lua$")) then
- table.insert(files, v)
- end
- end
- return files
-end
-
--- Function name explains what it does.
-function file_exists(name)
- local f = io.open(name,"r")
- if f ~= nil then
- io.close(f)
- return true
- else
- return false
- end
-end
-
--- Save into file the data serialized for lua.
--- Set uglify true to minify the file.
-function serialize_to_file(data, file, uglify)
- file = io.open(file, 'w+')
- local serialized
- if not uglify then
- serialized = serpent.block(data, {
- comment = false,
- name = '_'
- })
- else
- serialized = serpent.dump(data)
- end
- file:write(serialized)
- file:close()
-end
-
--- Returns true if the string is empty
-function string:isempty()
- return self == nil or self == ''
-end
-
--- Returns true if the string is blank
-function string:isblank()
- self = self:trim()
- return self:isempty()
-end
-
--- DEPRECATED!!!!!
-function string.starts(String, Start)
- print("string.starts(String, Start) is DEPRECATED use string:starts(text) instead")
- return Start == string.sub(String,1,string.len(Start))
-end
-
--- Returns true if String starts with Start
-function string:starts(text)
- return text == string.sub(self,1,string.len(text))
-end
-
--- Send image to user and delete it when finished.
--- cb_function and cb_extra are optionals callback
-function _send_photo(receiver, file_path, cb_function, cb_extra)
- local cb_extra = {
- file_path = file_path,
- cb_function = cb_function,
- cb_extra = cb_extra
- }
- -- Call to remove with optional callback
- send_photo(receiver, file_path, cb_function, cb_extra)
-end
-
--- Download the image and send to receiver, it will be deleted.
--- cb_function and cb_extra are optionals callback
-function send_photo_from_url(receiver, url, cb_function, cb_extra)
- -- If callback not provided
- cb_function = cb_function or ok_cb
- cb_extra = cb_extra or false
-
- local file_path = download_to_file(url, false)
- if not file_path then -- Error
- local text = 'Error downloading the image'
- send_msg(receiver, text, cb_function, cb_extra)
- else
- print("File path: "..file_path)
- _send_photo(receiver, file_path, cb_function, cb_extra)
- end
-end
-
--- Same as send_photo_from_url but as callback function
-function send_photo_from_url_callback(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local url = cb_extra.url
-
- local file_path = download_to_file(url, false)
- if not file_path then -- Error
- local text = 'Error downloading the image'
- send_msg(receiver, text, ok_cb, false)
- else
- print("File path: "..file_path)
- _send_photo(receiver, file_path, ok_cb, false)
- end
-end
-
--- Send multiple images asynchronous.
--- param urls must be a table.
-function send_photos_from_url(receiver, urls)
- local cb_extra = {
- receiver = receiver,
- urls = urls,
- remove_path = nil
- }
- send_photos_from_url_callback(cb_extra)
-end
-
--- Use send_photos_from_url.
--- This function might be difficult to understand.
-function send_photos_from_url_callback(cb_extra, success, result)
- -- cb_extra is a table containing receiver, urls and remove_path
- local receiver = cb_extra.receiver
- local urls = cb_extra.urls
- local remove_path = cb_extra.remove_path
-
- -- The previously image to remove
- if remove_path ~= nil then
- os.remove(remove_path)
- print("Deleted: "..remove_path)
- end
-
- -- Nil or empty, exit case (no more urls)
- if urls == nil or #urls == 0 then
- return false
- end
-
- -- Take the head and remove from urls table
- local head = table.remove(urls, 1)
-
- local file_path = download_to_file(head, false)
- local cb_extra = {
- receiver = receiver,
- urls = urls,
- remove_path = file_path
- }
-
- -- Send first and postpone the others as callback
- send_photo(receiver, file_path, send_photos_from_url_callback, cb_extra)
-end
-
--- Callback to remove a file
-function rmtmp_cb(cb_extra, success, result)
- local file_path = cb_extra.file_path
- local cb_function = cb_extra.cb_function or ok_cb
- local cb_extra = cb_extra.cb_extra
-
- if file_path ~= nil then
- os.remove(file_path)
- print("Deleted: "..file_path)
- end
- -- Finally call the callback
- cb_function(cb_extra, success, result)
-end
-
--- Send document to user and delete it when finished.
--- cb_function and cb_extra are optionals callback
-function _send_document(receiver, file_path, cb_function, cb_extra)
- local cb_extra = {
- file_path = file_path,
- cb_function = cb_function or ok_cb,
- cb_extra = cb_extra or false
- }
- -- Call to remove with optional callback
- send_document(receiver, file_path, rmtmp_cb, cb_extra)
-end
-
--- Download the image and send to receiver, it will be deleted.
--- cb_function and cb_extra are optionals callback
-function send_document_from_url(receiver, url, cb_function, cb_extra)
- local file_path = download_to_file(url, false)
- print("File path: "..file_path)
- _send_document(receiver, file_path, cb_function, cb_extra)
-end
-
--- Parameters in ?a=1&b=2 style
-function format_http_params(params, is_get)
- local str = ''
- -- If is get add ? to the beginning
- if is_get then str = '?' end
- local first = true -- Frist param
- for k,v in pairs (params) do
- if v then -- nil value
- if first then
- first = false
- str = str..k.. "="..v
- else
- str = str.."&"..k.. "="..v
- end
- end
- end
- return str
-end
-
--- Check if user can use the plugin and warns user
--- Returns true if user was warned and false if not warned (is allowed)
-function warns_user_not_allowed(plugin, msg)
- if not user_allowed(plugin, msg) then
- local text = 'This plugin requires privileged user'
- local receiver = get_receiver(msg)
- send_msg(receiver, text, ok_cb, false)
- return true
- else
- return false
- end
-end
-
--- Check if user can use the plugin
-function user_allowed(plugin, msg)
- if plugin.privileged and not is_sudo(msg) then
- return false
- end
- return true
-end
-
-
-function send_order_msg(destination, msgs)
- local cb_extra = {
- destination = destination,
- msgs = msgs
- }
- send_order_msg_callback(cb_extra, true)
-end
-
-function send_order_msg_callback(cb_extra, success, result)
- local destination = cb_extra.destination
- local msgs = cb_extra.msgs
- local file_path = cb_extra.file_path
- if file_path ~= nil then
- os.remove(file_path)
- print("Deleted: " .. file_path)
- end
- if type(msgs) == 'string' then
- send_large_msg(destination, msgs)
- elseif type(msgs) ~= 'table' then
- return
- end
- if #msgs < 1 then
- return
- end
- local msg = table.remove(msgs, 1)
- local new_cb_extra = {
- destination = destination,
- msgs = msgs
- }
- if type(msg) == 'string' then
- send_msg(destination, msg, send_order_msg_callback, new_cb_extra)
- elseif type(msg) == 'table' then
- local typ = msg[1]
- local nmsg = msg[2]
- new_cb_extra.file_path = nmsg
- if typ == 'document' then
- send_document(destination, nmsg, send_order_msg_callback, new_cb_extra)
- elseif typ == 'image' or typ == 'photo' then
- send_photo(destination, nmsg, send_order_msg_callback, new_cb_extra)
- elseif typ == 'audio' then
- send_audio(destination, nmsg, send_order_msg_callback, new_cb_extra)
- elseif typ == 'video' then
- send_video(destination, nmsg, send_order_msg_callback, new_cb_extra)
- else
- send_file(destination, nmsg, send_order_msg_callback, new_cb_extra)
- end
- end
-end
-
--- Same as send_large_msg_callback but friendly params
-function send_large_msg(destination, text)
- local cb_extra = {
- destination = destination,
- text = text
- }
- send_large_msg_callback(cb_extra, true)
-end
-
--- If text is longer than 4096 chars, send multiple msg.
--- https://core.telegram.org/method/messages.sendMessage
-function send_large_msg_callback(cb_extra, success, result)
- local text_max = 4096
-
- local destination = cb_extra.destination
- local text = cb_extra.text
- local text_len = string.len(text)
- local num_msg = math.ceil(text_len / text_max)
-
- if num_msg <= 1 then
- send_msg(destination, text, ok_cb, false)
- else
-
- local my_text = string.sub(text, 1, 4096)
- local rest = string.sub(text, 4096, text_len)
-
- local cb_extra = {
- destination = destination,
- text = rest
- }
-
- send_msg(destination, my_text, send_large_msg_callback, cb_extra)
- end
-end
-
--- Returns a table with matches or nil
-function match_pattern(pattern, text, lower_case)
- if text then
- local matches = {}
- if lower_case then
- matches = { string.match(text:lower(), pattern) }
- else
- matches = { string.match(text, pattern) }
- end
- if next(matches) then
- return matches
- end
- end
- -- nil
-end
-
--- Function to read data from files
-function load_from_file(file, default_data)
- local f = io.open(file, "r+")
- -- If file doesn't exists
- if f == nil then
- -- Create a new empty table
- default_data = default_data or {}
- serialize_to_file(default_data, file)
- print ('Created file', file)
- else
- print ('Data loaded from file', file)
- f:close()
- end
- return loadfile (file)()
-end
-
--- See http://stackoverflow.com/a/14899740
-function unescape_html(str)
- local map = {
- ["lt"] = "<",
- ["gt"] = ">",
- ["amp"] = "&",
- ["quot"] = '"',
- ["apos"] = "'"
- }
- new = string.gsub(str, '(&(#?x?)([%d%a]+);)', function(orig, n, s)
- var = map[s] or n == "#" and string.char(s)
- var = var or n == "#x" and string.char(tonumber(s,16))
- var = var or orig
- return var
- end)
- return new
-end
-
-
-
---Check if this chat is realm or not
-function is_realm(msg)
- local var = false
- local realms = 'realms'
- local data = load_data(_config.moderation.data)
- local chat = msg.to.id
- if data[tostring(realms)] then
- if data[tostring(realms)][tostring(msg.to.id)] then
- var = true
- end
- return var
- end
-end
---Check if this chat is a group or not
-function is_group(msg)
- local var = false
- local groups = 'groups'
- local data = load_data(_config.moderation.data)
- local chat = msg.to.id
- if data[tostring(groups)] then
- if data[tostring(groups)][tostring(msg.to.id)] then
- var = true
- end
- return var
- end
-end
-
-
-function savelog(group, logtxt)
-
-local text = (os.date("[ %c ]=> "..logtxt.."\n \n"))
-local file = io.open("./groups/logs/"..group.."log.txt", "a")
-
-file:write(text)
-
-file:close()
-
-end
-
-function user_print_name(user)
- if user.print_name then
- return user.print_name
- end
- local text = ''
- if user.first_name then
- text = user.last_name..' '
- end
- if user.lastname then
- text = text..user.last_name
- end
- return text
-end
-
---Check if user is the owner of that group or not
-function is_owner(msg)
- local var = false
- local data = load_data(_config.moderation.data)
- local user = msg.from.id
-
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['set_owner'] then
- if data[tostring(msg.to.id)]['set_owner'] == tostring(user) then
- var = true
- end
- end
- end
-
- if data['admins'] then
- if data['admins'][tostring(user)] then
- var = true
- end
- end
- for v,user in pairs(_config.sudo_users) do
- if user == msg.from.id then
- var = true
- end
- end
- return var
-end
-
-function is_owner2(user_id, group_id)
- local var = false
- local data = load_data(_config.moderation.data)
-
- if data[tostring(group_id)] then
- if data[tostring(group_id)]['set_owner'] then
- if data[tostring(group_id)]['set_owner'] == tostring(user_id) then
- var = true
- end
- end
- end
-
- if data['admins'] then
- if data['admins'][tostring(user_id)] then
- var = true
- end
- end
- for v,user in pairs(_config.sudo_users) do
- if user == user_id then
- var = true
- end
- end
- return var
-end
-
---Check if user is admin or not
-function is_admin(msg)
- local var = false
- local data = load_data(_config.moderation.data)
- local user = msg.from.id
- local admins = 'admins'
- if data[tostring(admins)] then
- if data[tostring(admins)][tostring(user)] then
- var = true
- end
- end
- for v,user in pairs(_config.sudo_users) do
- if user == msg.from.id then
- var = true
- end
- end
- return var
-end
-
-function is_admin2(user_id)
- local var = false
- local data = load_data(_config.moderation.data)
- local user = user_id
- local admins = 'admins'
- if data[tostring(admins)] then
- if data[tostring(admins)][tostring(user)] then
- var = true
- end
- end
- for v,user in pairs(_config.sudo_users) do
- if user == user_id then
- var = true
- end
- end
- return var
-end
-
-
-
---Check if user is the mod of that group or not
-function is_momod(msg)
- local var = false
- local data = load_data(_config.moderation.data)
- local user = msg.from.id
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['moderators'] then
- if data[tostring(msg.to.id)]['moderators'][tostring(user)] then
- var = true
- end
- end
- end
-
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['set_owner'] then
- if data[tostring(msg.to.id)]['set_owner'] == tostring(user) then
- var = true
- end
- end
- end
-
- if data['admins'] then
- if data['admins'][tostring(user)] then
- var = true
- end
- end
- for v,user in pairs(_config.sudo_users) do
- if user == msg.from.id then
- var = true
- end
- end
- return var
-end
-
-function is_momod2(user_id, group_id)
- local var = false
- local data = load_data(_config.moderation.data)
- local usert = user_id
- if data[tostring(group_id)] then
- if data[tostring(group_id)]['moderators'] then
- if data[tostring(group_id)]['moderators'][tostring(usert)] then
- var = true
- end
- end
- end
-
- if data[tostring(group_id)] then
- if data[tostring(group_id)]['set_owner'] then
- if data[tostring(group_id)]['set_owner'] == tostring(user_id) then
- var = true
- end
- end
- end
-
- if data['admins'] then
- if data['admins'][tostring(user_id)] then
- var = true
- end
- end
- for v,user in pairs(_config.sudo_users) do
- if user == usert then
- var = true
- end
- end
- return var
-end
-
--- Returns the name of the sender
-function kick_user(user_id, chat_id)
- if tonumber(user_id) == tonumber(our_id) then -- Ignore bot
- return
- end
- if is_owner2(user_id, chat_id) then -- Ignore admins
- return
- end
- local chat = 'chat#id'..chat_id
- local user = 'user#id'..user_id
- chat_del_user(chat, user, ok_cb, true)
-end
-
--- Ban
-function ban_user(user_id, chat_id)
- if tonumber(user_id) == tonumber(our_id) then -- Ignore bot
- return
- end
- if is_admin2(user_id) then -- Ignore admins
- return
- end
- -- Save to redis
- local hash = 'banned:'..chat_id
- redis:sadd(hash, user_id)
- -- Kick from chat
- kick_user(user_id, chat_id)
-end
--- Global ban
-function banall_user(user_id)
- if tonumber(user_id) == tonumber(our_id) then -- Ignore bot
- return
- end
- if is_admin2(user_id) then -- Ignore admins
- return
- end
- -- Save to redis
- local hash = 'gbanned'
- redis:sadd(hash, user_id)
-end
--- Global unban
-function unbanall_user(user_id)
- --Save on redis
- local hash = 'gbanned'
- redis:srem(hash, user_id)
-end
-
--- Check if user_id is banned in chat_id or not
-function is_banned(user_id, chat_id)
- --Save on redis
- local hash = 'banned:'..chat_id
- local banned = redis:sismember(hash, user_id)
- return banned or false
-end
-
--- Check if user_id is globally banned or not
-function is_gbanned(user_id)
- --Save on redis
- local hash = 'gbanned'
- local banned = redis:sismember(hash, user_id)
- return banned or false
-end
-
--- Returns chat_id ban list
-function ban_list(chat_id)
- local hash = 'banned:'..chat_id
- local list = redis:smembers(hash)
- local text = "Ban list !\n\n"
- for k,v in pairs(list) do
- local user_info = redis:hgetall('user:'..v)
--- vardump(user_info)
- if user_info then
- if user_info.username then
- user = '@'..user_info.username
- elseif user_info.print_name and not user_info.username then
- user = string.gsub(user_info.print_name, "_", " ")
- else
- user = ''
- end
- text = text..k.." - "..user.." ["..v.."]\n"
- end
- end
- return text
-end
-
--- Returns globally ban list
-function banall_list()
- local hash = 'gbanned'
- local list = redis:smembers(hash)
- local text = "global bans !\n\n"
- for k,v in pairs(list) do
- local user_info = redis:hgetall('user:'..v)
--- vardump(user_info)
- if user_info then
- if user_info.username then
- user = '@'..user_info.username
- elseif user_info.print_name and not user_info.username then
- user = string.gsub(user_info.print_name, "_", " ")
- else
- user = ''
- end
- text = text..k.." - "..user.." ["..v.."]\n"
- end
- end
- return text
-end
-
--- /id by reply
-function get_message_callback_id(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- send_large_msg(chat, result.from.id)
- else
- return 'Use This in Your Groups'
- end
-end
-
--- kick by reply for mods and owner
-function Kick_by_reply(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- if tonumber(result.from.id) == tonumber(our_id) then -- Ignore bot
- return "I won't kick myself"
- end
- if is_momod2(result.from.id, result.to.id) then -- Ignore mods,owner,admin
- return "you can't kick mods,owner and admins"
- end
- chat_del_user(chat, 'user#id'..result.from.id, ok_cb, false)
- else
- return 'Use This in Your Groups'
- end
-end
-
--- Kick by reply for admins
-function Kick_by_reply_admins(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- if tonumber(result.from.id) == tonumber(our_id) then -- Ignore bot
- return "I won't kick myself"
- end
- if is_admin2(result.from.id) then -- Ignore admins
- return
- end
- chat_del_user(chat, 'user#id'..result.from.id, ok_cb, false)
- else
- return 'Use This in Your Groups'
- end
-end
-
---Ban by reply for admins
-function ban_by_reply(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- if tonumber(result.from.id) == tonumber(our_id) then -- Ignore bot
- return "I won't ban myself"
- end
- if is_momod2(result.from.id, result.to.id) then -- Ignore mods,owner,admin
- return "you can't kick mods,owner and admins"
- end
- ban_user(result.from.id, result.to.id)
- send_large_msg(chat, "User "..result.from.id.." Banned")
- else
- return 'Use This in Your Groups'
- end
-end
-
--- Ban by reply for admins
-function ban_by_reply_admins(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- if tonumber(result.from.id) == tonumber(our_id) then -- Ignore bot
- return "I won't ban myself"
- end
- if is_admin2(result.from.id) then -- Ignore admins
- return
- end
- ban_user(result.from.id, result.to.id)
- send_large_msg(chat, "User "..result.from.id.." Banned")
- else
- return 'Use This in Your Groups'
- end
-end
-
--- Unban by reply
-function unban_by_reply(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- if tonumber(result.from.id) == tonumber(our_id) then -- Ignore bot
- return "I won't unban myself"
- end
- send_large_msg(chat, "User "..result.from.id.." Unbanned")
- -- Save on redis
- local hash = 'banned:'..result.to.id
- redis:srem(hash, result.from.id)
- else
- return 'Use This in Your Groups'
- end
-end
-function banall_by_reply(extra, success, result)
- if result.to.type == 'chat' then
- local chat = 'chat#id'..result.to.id
- if tonumber(result.from.id) == tonumber(our_id) then -- Ignore bot
- return "I won't banall myself"
- end
- if is_admin2(result.from.id) then -- Ignore admins
- return
- end
- local name = user_print_name(result.from)
- banall_user(result.from.id)
- chat_del_user(chat, 'user#id'..result.from.id, ok_cb, false)
- send_large_msg(chat, "User "..name.."["..result.from.id.."] hammered")
- else
- return 'Use This in Your Groups'
- end
-end
diff --git a/data/.gitkeep b/data/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/data/photos/.gitkeep b/data/photos/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/groups/all/[group_id]all.txt b/groups/all/[group_id]all.txt
deleted file mode 100644
index f5531c1..0000000
--- a/groups/all/[group_id]all.txt
+++ /dev/null
@@ -1 +0,0 @@
-[group_id] logs !
diff --git a/groups/lists/[group_id]memberlist.txt b/groups/lists/[group_id]memberlist.txt
deleted file mode 100644
index a13454d..0000000
--- a/groups/lists/[group_id]memberlist.txt
+++ /dev/null
@@ -1 +0,0 @@
-[group_id] memeberlist !
diff --git a/groups/logs/[group_id]log.txt b/groups/logs/[group_id]log.txt
deleted file mode 100644
index f5531c1..0000000
--- a/groups/logs/[group_id]log.txt
+++ /dev/null
@@ -1 +0,0 @@
-[group_id] logs !
diff --git a/groups/logs/[group_id]stats.txt b/groups/logs/[group_id]stats.txt
deleted file mode 100644
index 56448df..0000000
--- a/groups/logs/[group_id]stats.txt
+++ /dev/null
@@ -1 +0,0 @@
-[group_id] stats !
diff --git a/launch.sh b/launch.sh
deleted file mode 100755
index b5b74dd..0000000
--- a/launch.sh
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env bash
-
-THIS_DIR=$(cd $(dirname $0); pwd)
-cd $THIS_DIR
-
-update() {
- git pull
- git submodule update --init --recursive
- install_rocks
-}
-
-# Will install luarocks on THIS_DIR/.luarocks
-install_luarocks() {
- git clone https://github.com/keplerproject/luarocks.git
- cd luarocks
- git checkout tags/v2.2.1 # Current stable
-
- PREFIX="$THIS_DIR/.luarocks"
-
- ./configure --prefix=$PREFIX --sysconfdir=$PREFIX/luarocks --force-config
-
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- make build && make install
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting.";exit $RET;
- fi
-
- cd ..
- rm -rf luarocks
-}
-
-install_rocks() {
- ./.luarocks/bin/luarocks install luasocket
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install oauth
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install redis-lua
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install lua-cjson
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install fakeredis
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install xml
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install feedparser
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-
- ./.luarocks/bin/luarocks install serpent
- RET=$?; if [ $RET -ne 0 ];
- then echo "Error. Exiting."; exit $RET;
- fi
-}
-
-install() {
- git pull
- git submodule update --init --recursive
- patch -i "patches/disable-python-and-libjansson.patch" -p 0 --batch --forward
- RET=$?;
-
- cd tg
- if [ $RET -ne 0 ]; then
- autoconf -i
- fi
- ./configure && make
-
- RET=$?; if [ $RET -ne 0 ]; then
- echo "Error. Exiting."; exit $RET;
- fi
- cd ..
- install_luarocks
- install_rocks
-}
-
-if [ "$1" = "install" ]; then
- install
-elif [ "$1" = "update" ]; then
- update
-else
- if [ ! -f ./tg/telegram.h ]; then
- echo "tg not found"
- echo "Run $0 install"
- exit 1
- fi
-
- if [ ! -f ./tg/bin/telegram-cli ]; then
- echo "tg binary not found"
- echo "Run $0 install"
- exit 1
- fi
-
- ./tg/bin/telegram-cli -k ./tg/tg-server.pub -s ./bot/seedbot.lua -l 1 -E $@
-fi
\ No newline at end of file
diff --git a/libs/JSON.lua b/libs/JSON.lua
deleted file mode 100644
index 5f11425..0000000
--- a/libs/JSON.lua
+++ /dev/null
@@ -1,1053 +0,0 @@
--- -*- coding: utf-8 -*-
---
--- Simple JSON encoding and decoding in pure Lua.
---
--- Copyright 2010-2014 Jeffrey Friedl
--- http://regex.info/blog/
---
--- Latest version: http://regex.info/blog/lua/json
---
--- This code is released under a Creative Commons CC-BY "Attribution" License:
--- http://creativecommons.org/licenses/by/3.0/deed.en_US
---
--- It can be used for any purpose so long as the copyright notice above,
--- the web-page links above, and the 'AUTHOR_NOTE' string below are
--- maintained. Enjoy.
---
-local VERSION = 20141223.14 -- version history at end of file
-local AUTHOR_NOTE = "-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json) version 20141223.14 ]-"
-
---
--- The 'AUTHOR_NOTE' variable exists so that information about the source
--- of the package is maintained even in compiled versions. It's also
--- included in OBJDEF below mostly to quiet warnings about unused variables.
---
-local OBJDEF = {
- VERSION = VERSION,
- AUTHOR_NOTE = AUTHOR_NOTE,
-}
-
-
---
--- Simple JSON encoding and decoding in pure Lua.
--- http://www.json.org/
---
---
--- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines
---
--- local lua_value = JSON:decode(raw_json_text)
---
--- local raw_json_text = JSON:encode(lua_table_or_value)
--- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability
---
---
---
--- DECODING (from a JSON string to a Lua table)
---
---
--- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines
---
--- local lua_value = JSON:decode(raw_json_text)
---
--- If the JSON text is for an object or an array, e.g.
--- { "what": "books", "count": 3 }
--- or
--- [ "Larry", "Curly", "Moe" ]
---
--- the result is a Lua table, e.g.
--- { what = "books", count = 3 }
--- or
--- { "Larry", "Curly", "Moe" }
---
---
--- The encode and decode routines accept an optional second argument,
--- "etc", which is not used during encoding or decoding, but upon error
--- is passed along to error handlers. It can be of any type (including nil).
---
---
---
--- ERROR HANDLING
---
--- With most errors during decoding, this code calls
---
--- JSON:onDecodeError(message, text, location, etc)
---
--- with a message about the error, and if known, the JSON text being
--- parsed and the byte count where the problem was discovered. You can
--- replace the default JSON:onDecodeError() with your own function.
---
--- The default onDecodeError() merely augments the message with data
--- about the text and the location if known (and if a second 'etc'
--- argument had been provided to decode(), its value is tacked onto the
--- message as well), and then calls JSON.assert(), which itself defaults
--- to Lua's built-in assert(), and can also be overridden.
---
--- For example, in an Adobe Lightroom plugin, you might use something like
---
--- function JSON:onDecodeError(message, text, location, etc)
--- LrErrors.throwUserError("Internal Error: invalid JSON data")
--- end
---
--- or even just
---
--- function JSON.assert(message)
--- LrErrors.throwUserError("Internal Error: " .. message)
--- end
---
--- If JSON:decode() is passed a nil, this is called instead:
---
--- JSON:onDecodeOfNilError(message, nil, nil, etc)
---
--- and if JSON:decode() is passed HTML instead of JSON, this is called:
---
--- JSON:onDecodeOfHTMLError(message, text, nil, etc)
---
--- The use of the fourth 'etc' argument allows stronger coordination
--- between decoding and error reporting, especially when you provide your
--- own error-handling routines. Continuing with the the Adobe Lightroom
--- plugin example:
---
--- function JSON:onDecodeError(message, text, location, etc)
--- local note = "Internal Error: invalid JSON data"
--- if type(etc) = 'table' and etc.photo then
--- note = note .. " while processing for " .. etc.photo:getFormattedMetadata('fileName')
--- end
--- LrErrors.throwUserError(note)
--- end
---
--- :
--- :
---
--- for i, photo in ipairs(photosToProcess) do
--- :
--- :
--- local data = JSON:decode(someJsonText, { photo = photo })
--- :
--- :
--- end
---
---
---
---
---
--- DECODING AND STRICT TYPES
---
--- Because both JSON objects and JSON arrays are converted to Lua tables,
--- it's not normally possible to tell which original JSON type a
--- particular Lua table was derived from, or guarantee decode-encode
--- round-trip equivalency.
---
--- However, if you enable strictTypes, e.g.
---
--- JSON = assert(loadfile "JSON.lua")() --load the routines
--- JSON.strictTypes = true
---
--- then the Lua table resulting from the decoding of a JSON object or
--- JSON array is marked via Lua metatable, so that when re-encoded with
--- JSON:encode() it ends up as the appropriate JSON type.
---
--- (This is not the default because other routines may not work well with
--- tables that have a metatable set, for example, Lightroom API calls.)
---
---
--- ENCODING (from a lua table to a JSON string)
---
--- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines
---
--- local raw_json_text = JSON:encode(lua_table_or_value)
--- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability
--- local custom_pretty = JSON:encode(lua_table_or_value, etc, { pretty = true, indent = "| ", align_keys = false })
---
--- On error during encoding, this code calls:
---
--- JSON:onEncodeError(message, etc)
---
--- which you can override in your local JSON object.
---
--- The 'etc' in the error call is the second argument to encode()
--- and encode_pretty(), or nil if it wasn't provided.
---
---
--- PRETTY-PRINTING
---
--- An optional third argument, a table of options, allows a bit of
--- configuration about how the encoding takes place:
---
--- pretty = JSON:encode(val, etc, {
--- pretty = true, -- if false, no other options matter
--- indent = " ", -- this provides for a three-space indent per nesting level
--- align_keys = false, -- see below
--- })
---
--- encode() and encode_pretty() are identical except that encode_pretty()
--- provides a default options table if none given in the call:
---
--- { pretty = true, align_keys = false, indent = " " }
---
--- For example, if
---
--- JSON:encode(data)
---
--- produces:
---
--- {"city":"Kyoto","climate":{"avg_temp":16,"humidity":"high","snowfall":"minimal"},"country":"Japan","wards":11}
---
--- then
---
--- JSON:encode_pretty(data)
---
--- produces:
---
--- {
--- "city": "Kyoto",
--- "climate": {
--- "avg_temp": 16,
--- "humidity": "high",
--- "snowfall": "minimal"
--- },
--- "country": "Japan",
--- "wards": 11
--- }
---
--- The following three lines return identical results:
--- JSON:encode_pretty(data)
--- JSON:encode_pretty(data, nil, { pretty = true, align_keys = false, indent = " " })
--- JSON:encode (data, nil, { pretty = true, align_keys = false, indent = " " })
---
--- An example of setting your own indent string:
---
--- JSON:encode_pretty(data, nil, { pretty = true, indent = "| " })
---
--- produces:
---
--- {
--- | "city": "Kyoto",
--- | "climate": {
--- | | "avg_temp": 16,
--- | | "humidity": "high",
--- | | "snowfall": "minimal"
--- | },
--- | "country": "Japan",
--- | "wards": 11
--- }
---
--- An example of setting align_keys to true:
---
--- JSON:encode_pretty(data, nil, { pretty = true, indent = " ", align_keys = true })
---
--- produces:
---
--- {
--- "city": "Kyoto",
--- "climate": {
--- "avg_temp": 16,
--- "humidity": "high",
--- "snowfall": "minimal"
--- },
--- "country": "Japan",
--- "wards": 11
--- }
---
--- which I must admit is kinda ugly, sorry. This was the default for
--- encode_pretty() prior to version 20141223.14.
---
---
--- AMBIGUOUS SITUATIONS DURING THE ENCODING
---
--- During the encode, if a Lua table being encoded contains both string
--- and numeric keys, it fits neither JSON's idea of an object, nor its
--- idea of an array. To get around this, when any string key exists (or
--- when non-positive numeric keys exist), numeric keys are converted to
--- strings.
---
--- For example,
--- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" }))
--- produces the JSON object
--- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"}
---
--- To prohibit this conversion and instead make it an error condition, set
--- JSON.noKeyConversion = true
---
-
-
-
-
---
--- SUMMARY OF METHODS YOU CAN OVERRIDE IN YOUR LOCAL LUA JSON OBJECT
---
--- assert
--- onDecodeError
--- onDecodeOfNilError
--- onDecodeOfHTMLError
--- onEncodeError
---
--- If you want to create a separate Lua JSON object with its own error handlers,
--- you can reload JSON.lua or use the :new() method.
---
----------------------------------------------------------------------------
-
-local default_pretty_indent = " "
-local default_pretty_options = { pretty = true, align_keys = false, indent = default_pretty_indent }
-
-local isArray = { __tostring = function() return "JSON array" end } isArray.__index = isArray
-local isObject = { __tostring = function() return "JSON object" end } isObject.__index = isObject
-
-
-function OBJDEF:newArray(tbl)
- return setmetatable(tbl or {}, isArray)
-end
-
-function OBJDEF:newObject(tbl)
- return setmetatable(tbl or {}, isObject)
-end
-
-local function unicode_codepoint_as_utf8(codepoint)
- --
- -- codepoint is a number
- --
- if codepoint <= 127 then
- return string.char(codepoint)
-
- elseif codepoint <= 2047 then
- --
- -- 110yyyxx 10xxxxxx <-- useful notation from http://en.wikipedia.org/wiki/Utf8
- --
- local highpart = math.floor(codepoint / 0x40)
- local lowpart = codepoint - (0x40 * highpart)
- return string.char(0xC0 + highpart,
- 0x80 + lowpart)
-
- elseif codepoint <= 65535 then
- --
- -- 1110yyyy 10yyyyxx 10xxxxxx
- --
- local highpart = math.floor(codepoint / 0x1000)
- local remainder = codepoint - 0x1000 * highpart
- local midpart = math.floor(remainder / 0x40)
- local lowpart = remainder - 0x40 * midpart
-
- highpart = 0xE0 + highpart
- midpart = 0x80 + midpart
- lowpart = 0x80 + lowpart
-
- --
- -- Check for an invalid character (thanks Andy R. at Adobe).
- -- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070
- --
- if ( highpart == 0xE0 and midpart < 0xA0 ) or
- ( highpart == 0xED and midpart > 0x9F ) or
- ( highpart == 0xF0 and midpart < 0x90 ) or
- ( highpart == 0xF4 and midpart > 0x8F )
- then
- return "?"
- else
- return string.char(highpart,
- midpart,
- lowpart)
- end
-
- else
- --
- -- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
- --
- local highpart = math.floor(codepoint / 0x40000)
- local remainder = codepoint - 0x40000 * highpart
- local midA = math.floor(remainder / 0x1000)
- remainder = remainder - 0x1000 * midA
- local midB = math.floor(remainder / 0x40)
- local lowpart = remainder - 0x40 * midB
-
- return string.char(0xF0 + highpart,
- 0x80 + midA,
- 0x80 + midB,
- 0x80 + lowpart)
- end
-end
-
-function OBJDEF:onDecodeError(message, text, location, etc)
- if text then
- if location then
- message = string.format("%s at char %d of: %s", message, location, text)
- else
- message = string.format("%s: %s", message, text)
- end
- end
-
- if etc ~= nil then
- message = message .. " (" .. OBJDEF:encode(etc) .. ")"
- end
-
- if self.assert then
- self.assert(false, message)
- else
- assert(false, message)
- end
-end
-
-OBJDEF.onDecodeOfNilError = OBJDEF.onDecodeError
-OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError
-
-function OBJDEF:onEncodeError(message, etc)
- if etc ~= nil then
- message = message .. " (" .. OBJDEF:encode(etc) .. ")"
- end
-
- if self.assert then
- self.assert(false, message)
- else
- assert(false, message)
- end
-end
-
-local function grok_number(self, text, start, etc)
- --
- -- Grab the integer part
- --
- local integer_part = text:match('^-?[1-9]%d*', start)
- or text:match("^-?0", start)
-
- if not integer_part then
- self:onDecodeError("expected number", text, start, etc)
- end
-
- local i = start + integer_part:len()
-
- --
- -- Grab an optional decimal part
- --
- local decimal_part = text:match('^%.%d+', i) or ""
-
- i = i + decimal_part:len()
-
- --
- -- Grab an optional exponential part
- --
- local exponent_part = text:match('^[eE][-+]?%d+', i) or ""
-
- i = i + exponent_part:len()
-
- local full_number_text = integer_part .. decimal_part .. exponent_part
- local as_number = tonumber(full_number_text)
-
- if not as_number then
- self:onDecodeError("bad number", text, start, etc)
- end
-
- return as_number, i
-end
-
-
-local function grok_string(self, text, start, etc)
-
- if text:sub(start,start) ~= '"' then
- self:onDecodeError("expected string's opening quote", text, start, etc)
- end
-
- local i = start + 1 -- +1 to bypass the initial quote
- local text_len = text:len()
- local VALUE = ""
- while i <= text_len do
- local c = text:sub(i,i)
- if c == '"' then
- return VALUE, i + 1
- end
- if c ~= '\\' then
- VALUE = VALUE .. c
- i = i + 1
- elseif text:match('^\\b', i) then
- VALUE = VALUE .. "\b"
- i = i + 2
- elseif text:match('^\\f', i) then
- VALUE = VALUE .. "\f"
- i = i + 2
- elseif text:match('^\\n', i) then
- VALUE = VALUE .. "\n"
- i = i + 2
- elseif text:match('^\\r', i) then
- VALUE = VALUE .. "\r"
- i = i + 2
- elseif text:match('^\\t', i) then
- VALUE = VALUE .. "\t"
- i = i + 2
- else
- local hex = text:match('^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
- if hex then
- i = i + 6 -- bypass what we just read
-
- -- We have a Unicode codepoint. It could be standalone, or if in the proper range and
- -- followed by another in a specific range, it'll be a two-code surrogate pair.
- local codepoint = tonumber(hex, 16)
- if codepoint >= 0xD800 and codepoint <= 0xDBFF then
- -- it's a hi surrogate... see whether we have a following low
- local lo_surrogate = text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i)
- if lo_surrogate then
- i = i + 6 -- bypass the low surrogate we just read
- codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16)
- else
- -- not a proper low, so we'll just leave the first codepoint as is and spit it out.
- end
- end
- VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint)
-
- else
-
- -- just pass through what's escaped
- VALUE = VALUE .. text:match('^\\(.)', i)
- i = i + 2
- end
- end
- end
-
- self:onDecodeError("unclosed string", text, start, etc)
-end
-
-local function skip_whitespace(text, start)
-
- local _, match_end = text:find("^[ \n\r\t]+", start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2
- if match_end then
- return match_end + 1
- else
- return start
- end
-end
-
-local grok_one -- assigned later
-
-local function grok_object(self, text, start, etc)
- if text:sub(start,start) ~= '{' then
- self:onDecodeError("expected '{'", text, start, etc)
- end
-
- local i = skip_whitespace(text, start + 1) -- +1 to skip the '{'
-
- local VALUE = self.strictTypes and self:newObject { } or { }
-
- if text:sub(i,i) == '}' then
- return VALUE, i + 1
- end
- local text_len = text:len()
- while i <= text_len do
- local key, new_i = grok_string(self, text, i, etc)
-
- i = skip_whitespace(text, new_i)
-
- if text:sub(i, i) ~= ':' then
- self:onDecodeError("expected colon", text, i, etc)
- end
-
- i = skip_whitespace(text, i + 1)
-
- local new_val, new_i = grok_one(self, text, i)
-
- VALUE[key] = new_val
-
- --
- -- Expect now either '}' to end things, or a ',' to allow us to continue.
- --
- i = skip_whitespace(text, new_i)
-
- local c = text:sub(i,i)
-
- if c == '}' then
- return VALUE, i + 1
- end
-
- if text:sub(i, i) ~= ',' then
- self:onDecodeError("expected comma or '}'", text, i, etc)
- end
-
- i = skip_whitespace(text, i + 1)
- end
-
- self:onDecodeError("unclosed '{'", text, start, etc)
-end
-
-local function grok_array(self, text, start, etc)
- if text:sub(start,start) ~= '[' then
- self:onDecodeError("expected '['", text, start, etc)
- end
-
- local i = skip_whitespace(text, start + 1) -- +1 to skip the '['
- local VALUE = self.strictTypes and self:newArray { } or { }
- if text:sub(i,i) == ']' then
- return VALUE, i + 1
- end
-
- local VALUE_INDEX = 1
-
- local text_len = text:len()
- while i <= text_len do
- local val, new_i = grok_one(self, text, i)
-
- -- can't table.insert(VALUE, val) here because it's a no-op if val is nil
- VALUE[VALUE_INDEX] = val
- VALUE_INDEX = VALUE_INDEX + 1
-
- i = skip_whitespace(text, new_i)
-
- --
- -- Expect now either ']' to end things, or a ',' to allow us to continue.
- --
- local c = text:sub(i,i)
- if c == ']' then
- return VALUE, i + 1
- end
- if text:sub(i, i) ~= ',' then
- self:onDecodeError("expected comma or '['", text, i, etc)
- end
- i = skip_whitespace(text, i + 1)
- end
- self:onDecodeError("unclosed '['", text, start, etc)
-end
-
-
-grok_one = function(self, text, start, etc)
- -- Skip any whitespace
- start = skip_whitespace(text, start)
-
- if start > text:len() then
- self:onDecodeError("unexpected end of string", text, nil, etc)
- end
-
- if text:find('^"', start) then
- return grok_string(self, text, start, etc)
-
- elseif text:find('^[-0123456789 ]', start) then
- return grok_number(self, text, start, etc)
-
- elseif text:find('^%{', start) then
- return grok_object(self, text, start, etc)
-
- elseif text:find('^%[', start) then
- return grok_array(self, text, start, etc)
-
- elseif text:find('^true', start) then
- return true, start + 4
-
- elseif text:find('^false', start) then
- return false, start + 5
-
- elseif text:find('^null', start) then
- return nil, start + 4
-
- else
- self:onDecodeError("can't parse JSON", text, start, etc)
- end
-end
-
-function OBJDEF:decode(text, etc)
- if type(self) ~= 'table' or self.__index ~= OBJDEF then
- OBJDEF:onDecodeError("JSON:decode must be called in method format", nil, nil, etc)
- end
-
- if text == nil then
- self:onDecodeOfNilError(string.format("nil passed to JSON:decode()"), nil, nil, etc)
- elseif type(text) ~= 'string' then
- self:onDecodeError(string.format("expected string argument to JSON:decode(), got %s", type(text)), nil, nil, etc)
- end
-
- if text:match('^%s*$') then
- return nil
- end
-
- if text:match('^%s*<') then
- -- Can't be JSON... we'll assume it's HTML
- self:onDecodeOfHTMLError(string.format("html passed to JSON:decode()"), text, nil, etc)
- end
-
- --
- -- Ensure that it's not UTF-32 or UTF-16.
- -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3),
- -- but this package can't handle them.
- --
- if text:sub(1,1):byte() == 0 or (text:len() >= 2 and text:sub(2,2):byte() == 0) then
- self:onDecodeError("JSON package groks only UTF-8, sorry", text, nil, etc)
- end
-
- local success, value = pcall(grok_one, self, text, 1, etc)
-
- if success then
- return value
- else
- -- if JSON:onDecodeError() didn't abort out of the pcall, we'll have received the error message here as "value", so pass it along as an assert.
- if self.assert then
- self.assert(false, value)
- else
- assert(false, value)
- end
- -- and if we're still here, return a nil and throw the error message on as a second arg
- return nil, value
- end
-end
-
-local function backslash_replacement_function(c)
- if c == "\n" then
- return "\\n"
- elseif c == "\r" then
- return "\\r"
- elseif c == "\t" then
- return "\\t"
- elseif c == "\b" then
- return "\\b"
- elseif c == "\f" then
- return "\\f"
- elseif c == '"' then
- return '\\"'
- elseif c == '\\' then
- return '\\\\'
- else
- return string.format("\\u%04x", c:byte())
- end
-end
-
-local chars_to_be_escaped_in_JSON_string
- = '['
- .. '"' -- class sub-pattern to match a double quote
- .. '%\\' -- class sub-pattern to match a backslash
- .. '%z' -- class sub-pattern to match a null
- .. '\001' .. '-' .. '\031' -- class sub-pattern to match control characters
- .. ']'
-
-local function json_string_literal(value)
- local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function)
- return '"' .. newval .. '"'
-end
-
-local function object_or_array(self, T, etc)
- --
- -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON
- -- object. If there are only numbers, it's a JSON array.
- --
- -- If we'll be converting to a JSON object, we'll want to sort the keys so that the
- -- end result is deterministic.
- --
- local string_keys = { }
- local number_keys = { }
- local number_keys_must_be_strings = false
- local maximum_number_key
-
- for key in pairs(T) do
- if type(key) == 'string' then
- table.insert(string_keys, key)
- elseif type(key) == 'number' then
- table.insert(number_keys, key)
- if key <= 0 or key >= math.huge then
- number_keys_must_be_strings = true
- elseif not maximum_number_key or key > maximum_number_key then
- maximum_number_key = key
- end
- else
- self:onEncodeError("can't encode table with a key of type " .. type(key), etc)
- end
- end
-
- if #string_keys == 0 and not number_keys_must_be_strings then
- --
- -- An empty table, or a numeric-only array
- --
- if #number_keys > 0 then
- return nil, maximum_number_key -- an array
- elseif tostring(T) == "JSON array" then
- return nil
- elseif tostring(T) == "JSON object" then
- return { }
- else
- -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects
- return nil
- end
- end
-
- table.sort(string_keys)
-
- local map
- if #number_keys > 0 then
- --
- -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array
- -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object.
- --
-
- if self.noKeyConversion then
- self:onEncodeError("a table with both numeric and string keys could be an object or array; aborting", etc)
- end
-
- --
- -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings
- --
- map = { }
- for key, val in pairs(T) do
- map[key] = val
- end
-
- table.sort(number_keys)
-
- --
- -- Throw numeric keys in there as strings
- --
- for _, number_key in ipairs(number_keys) do
- local string_key = tostring(number_key)
- if map[string_key] == nil then
- table.insert(string_keys , string_key)
- map[string_key] = T[number_key]
- else
- self:onEncodeError("conflict converting table with mixed-type keys into a JSON object: key " .. number_key .. " exists both as a string and a number.", etc)
- end
- end
- end
-
- return string_keys, nil, map
-end
-
---
--- Encode
---
--- 'options' is nil, or a table with possible keys:
--- pretty -- if true, return a pretty-printed version
--- indent -- a string (usually of spaces) used to indent each nested level
--- align_keys -- if true, align all the keys when formatting a table
---
-local encode_value -- must predeclare because it calls itself
-function encode_value(self, value, parents, etc, options, indent)
-
- if value == nil then
- return 'null'
-
- elseif type(value) == 'string' then
- return json_string_literal(value)
-
- elseif type(value) == 'number' then
- if value ~= value then
- --
- -- NaN (Not a Number).
- -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option.
- --
- return "null"
- elseif value >= math.huge then
- --
- -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should
- -- really be a package option. Note: at least with some implementations, positive infinity
- -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is.
- -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">="
- -- case first.
- --
- return "1e+9999"
- elseif value <= -math.huge then
- --
- -- Negative infinity.
- -- JSON has no INF, so we have to fudge the best we can. This should really be a package option.
- --
- return "-1e+9999"
- else
- return tostring(value)
- end
-
- elseif type(value) == 'boolean' then
- return tostring(value)
-
- elseif type(value) ~= 'table' then
- self:onEncodeError("can't convert " .. type(value) .. " to JSON", etc)
-
- else
- --
- -- A table to be converted to either a JSON object or array.
- --
- local T = value
-
- if type(options) ~= 'table' then
- options = {}
- end
- if type(indent) ~= 'string' then
- indent = ""
- end
-
- if parents[T] then
- self:onEncodeError("table " .. tostring(T) .. " is a child of itself", etc)
- else
- parents[T] = true
- end
-
- local result_value
-
- local object_keys, maximum_number_key, map = object_or_array(self, T, etc)
- if maximum_number_key then
- --
- -- An array...
- --
- local ITEMS = { }
- for i = 1, maximum_number_key do
- table.insert(ITEMS, encode_value(self, T[i], parents, etc, options, indent))
- end
-
- if options.pretty then
- result_value = "[ " .. table.concat(ITEMS, ", ") .. " ]"
- else
- result_value = "[" .. table.concat(ITEMS, ",") .. "]"
- end
-
- elseif object_keys then
- --
- -- An object
- --
- local TT = map or T
-
- if options.pretty then
-
- local KEYS = { }
- local max_key_length = 0
- for _, key in ipairs(object_keys) do
- local encoded = encode_value(self, tostring(key), parents, etc, options, indent)
- if options.align_keys then
- max_key_length = math.max(max_key_length, #encoded)
- end
- table.insert(KEYS, encoded)
- end
- local key_indent = indent .. tostring(options.indent or "")
- local subtable_indent = key_indent .. string.rep(" ", max_key_length) .. (options.align_keys and " " or "")
- local FORMAT = "%s%" .. string.format("%d", max_key_length) .. "s: %s"
-
- local COMBINED_PARTS = { }
- for i, key in ipairs(object_keys) do
- local encoded_val = encode_value(self, TT[key], parents, etc, options, subtable_indent)
- table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val))
- end
- result_value = "{\n" .. table.concat(COMBINED_PARTS, ",\n") .. "\n" .. indent .. "}"
-
- else
-
- local PARTS = { }
- for _, key in ipairs(object_keys) do
- local encoded_val = encode_value(self, TT[key], parents, etc, options, indent)
- local encoded_key = encode_value(self, tostring(key), parents, etc, options, indent)
- table.insert(PARTS, string.format("%s:%s", encoded_key, encoded_val))
- end
- result_value = "{" .. table.concat(PARTS, ",") .. "}"
-
- end
- else
- --
- -- An empty array/object... we'll treat it as an array, though it should really be an option
- --
- result_value = "[]"
- end
-
- parents[T] = false
- return result_value
- end
-end
-
-
-function OBJDEF:encode(value, etc, options)
- if type(self) ~= 'table' or self.__index ~= OBJDEF then
- OBJDEF:onEncodeError("JSON:encode must be called in method format", etc)
- end
- return encode_value(self, value, {}, etc, options or nil)
-end
-
-function OBJDEF:encode_pretty(value, etc, options)
- if type(self) ~= 'table' or self.__index ~= OBJDEF then
- OBJDEF:onEncodeError("JSON:encode_pretty must be called in method format", etc)
- end
- return encode_value(self, value, {}, etc, options or default_pretty_options)
-end
-
-function OBJDEF.__tostring()
- return "JSON encode/decode package"
-end
-
-OBJDEF.__index = OBJDEF
-
-function OBJDEF:new(args)
- local new = { }
-
- if args then
- for key, val in pairs(args) do
- new[key] = val
- end
- end
-
- return setmetatable(new, OBJDEF)
-end
-
-return OBJDEF:new()
-
---
--- Version history:
---
--- 20141223.14 The encode_pretty() routine produced fine results for small datasets, but isn't really
--- appropriate for anything large, so with help from Alex Aulbach I've made the encode routines
--- more flexible, and changed the default encode_pretty() to be more generally useful.
---
--- Added a third 'options' argument to the encode() and encode_pretty() routines, to control
--- how the encoding takes place.
---
--- Updated docs to add assert() call to the loadfile() line, just as good practice so that
--- if there is a problem loading JSON.lua, the appropriate error message will percolate up.
---
--- 20140920.13 Put back (in a way that doesn't cause warnings about unused variables) the author string,
--- so that the source of the package, and its version number, are visible in compiled copies.
---
--- 20140911.12 Minor lua cleanup.
--- Fixed internal reference to 'JSON.noKeyConversion' to reference 'self' instead of 'JSON'.
--- (Thanks to SmugMug's David Parry for these.)
---
--- 20140418.11 JSON nulls embedded within an array were being ignored, such that
--- ["1",null,null,null,null,null,"seven"],
--- would return
--- {1,"seven"}
--- It's now fixed to properly return
--- {1, nil, nil, nil, nil, nil, "seven"}
--- Thanks to "haddock" for catching the error.
---
--- 20140116.10 The user's JSON.assert() wasn't always being used. Thanks to "blue" for the heads up.
---
--- 20131118.9 Update for Lua 5.3... it seems that tostring(2/1) produces "2.0" instead of "2",
--- and this caused some problems.
---
--- 20131031.8 Unified the code for encode() and encode_pretty(); they had been stupidly separate,
--- and had of course diverged (encode_pretty didn't get the fixes that encode got, so
--- sometimes produced incorrect results; thanks to Mattie for the heads up).
---
--- Handle encoding tables with non-positive numeric keys (unlikely, but possible).
---
--- If a table has both numeric and string keys, or its numeric keys are inappropriate
--- (such as being non-positive or infinite), the numeric keys are turned into
--- string keys appropriate for a JSON object. So, as before,
--- JSON:encode({ "one", "two", "three" })
--- produces the array
--- ["one","two","three"]
--- but now something with mixed key types like
--- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" }))
--- instead of throwing an error produces an object:
--- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"}
---
--- To maintain the prior throw-an-error semantics, set
--- JSON.noKeyConversion = true
---
--- 20131004.7 Release under a Creative Commons CC-BY license, which I should have done from day one, sorry.
---
--- 20130120.6 Comment update: added a link to the specific page on my blog where this code can
--- be found, so that folks who come across the code outside of my blog can find updates
--- more easily.
---
--- 20111207.5 Added support for the 'etc' arguments, for better error reporting.
---
--- 20110731.4 More feedback from David Kolf on how to make the tests for Nan/Infinity system independent.
---
--- 20110730.3 Incorporated feedback from David Kolf at http://lua-users.org/wiki/JsonModules:
---
--- * When encoding lua for JSON, Sparse numeric arrays are now handled by
--- spitting out full arrays, such that
--- JSON:encode({"one", "two", [10] = "ten"})
--- returns
--- ["one","two",null,null,null,null,null,null,null,"ten"]
---
--- In 20100810.2 and earlier, only up to the first non-null value would have been retained.
---
--- * When encoding lua for JSON, numeric value NaN gets spit out as null, and infinity as "1+e9999".
--- Version 20100810.2 and earlier created invalid JSON in both cases.
---
--- * Unicode surrogate pairs are now detected when decoding JSON.
---
--- 20100810.2 added some checking to ensure that an invalid Unicode character couldn't leak in to the UTF-8 encoding
---
--- 20100731.1 initial public release
---
diff --git a/libs/dkjson.lua b/libs/dkjson.lua
deleted file mode 100644
index 8b3f37d..0000000
--- a/libs/dkjson.lua
+++ /dev/null
@@ -1,809 +0,0 @@
- -- Module options:
- local always_try_using_lpeg = true
- local register_global_module_table = false
- local global_module_name = 'json'
-
- --[==[
-
-David Kolf's JSON module for Lua 5.1/5.2
-========================================
-*Version 2.4*
-In the default configuration this module writes no global values, not even
-the module table. Import it using
- json = require ("dkjson")
-In environments where `require` or a similiar function are not available
-and you cannot receive the return value of the module, you can set the
-option `register_global_module_table` to `true`. The module table will
-then be saved in the global variable with the name given by the option
-`global_module_name`.
-Exported functions and values:
-`json.encode (object [, state])`
---------------------------------
-Create a string representing the object. `Object` can be a table,
-a string, a number, a boolean, `nil`, `json.null` or any object with
-a function `__tojson` in its metatable. A table can only use strings
-and numbers as keys and its values have to be valid objects as
-well. It raises an error for any invalid data types or reference
-cycles.
-`state` is an optional table with the following fields:
- - `indent`
- When `indent` (a boolean) is set, the created string will contain
- newlines and indentations. Otherwise it will be one long line.
- - `keyorder`
- `keyorder` is an array to specify the ordering of keys in the
- encoded output. If an object has keys which are not in this array
- they are written after the sorted keys.
- - `level`
- This is the initial level of indentation used when `indent` is
- set. For each level two spaces are added. When absent it is set
- to 0.
- - `buffer`
- `buffer` is an array to store the strings for the result so they
- can be concatenated at once. When it isn't given, the encode
- function will create it temporary and will return the
- concatenated result.
- - `bufferlen`
- When `bufferlen` is set, it has to be the index of the last
- element of `buffer`.
- - `tables`
- `tables` is a set to detect reference cycles. It is created
- temporary when absent. Every table that is currently processed
- is used as key, the value is `true`.
-
-When `state.buffer` was set, the return value will be `true` on
-success. Without `state.buffer` the return value will be a string.
-
-`json.decode (string [, position [, null]])`
---------------------------------------------
-
-Decode `string` starting at `position` or at 1 if `position` was
-omitted.
-
-`null` is an optional value to be returned for null values. The
-default is `nil`, but you could set it to `json.null` or any other
-value.
-
-The return values are the object or `nil`, the position of the next
-character that doesn't belong to the object, and in case of errors
-an error message.
-Two metatables are created. Every array or object that is decoded gets
-a metatable with the `__jsontype` field set to either `array` or
-`object`. If you want to provide your own metatables use the syntax
- json.decode (string, position, null, objectmeta, arraymeta)
-To prevent the assigning of metatables pass `nil`:
- json.decode (string, position, null, nil)
-`.__jsonorder`
--------------------------
-`__jsonorder` can overwrite the `keyorder` for a specific table.
-`.__jsontype`
-------------------------
-`__jsontype` can be either `"array"` or `"object"`. This value is only
-checked for empty tables. (The default for empty tables is `"array"`).
-`.__tojson (self, state)`
-------------------------------------
-You can provide your own `__tojson` function in a metatable. In this
-function you can either add directly to the buffer and return true,
-or you can return a string. On errors nil and a message should be
-returned.
-`json.null`
------------
-You can use this value for setting explicit `null` values.
-`json.version`
---------------
-Set to `"dkjson 2.4"`.
-`json.quotestring (string)`
----------------------------
-Quote a UTF-8 string and escape critical characters using JSON
-escape sequences. This function is only necessary when you build
-your own `__tojson` functions.
-`json.addnewline (state)`
--------------------------
-When `state.indent` is set, add a newline to `state.buffer` and spaces
-according to `state.level`.
-LPeg support
-------------
-When the local configuration variable `always_try_using_lpeg` is set,
-this module tries to load LPeg to replace the `decode` function. The
-speed increase is significant. You can get the LPeg module at
- .
-When LPeg couldn't be loaded, the pure Lua functions stay active.
-
-In case you don't want this module to require LPeg on its own,
-disable the option `always_try_using_lpeg` in the options section at
-the top of the module.
-In this case you can later load LPeg support using
-### `json.use_lpeg ()`
-Require the LPeg module and replace the functions `quotestring` and
-and `decode` with functions that use LPeg patterns.
-This function returns the module table, so you can load the module
-using:
- json = require "dkjson".use_lpeg()
-Alternatively you can use `pcall` so the JSON module still works when
-LPeg isn't found.
-
- json = require "dkjson"
- pcall (json.use_lpeg)
-
-### `json.using_lpeg`
-
-This variable is set to `true` when LPeg was loaded successfully.
-
----------------------------------------------------------------------
-
-Contact
--------
-
-You can contact the author by sending an e-mail to 'david' at the
-domain 'dkolf.de'.
-
----------------------------------------------------------------------
-
-*Copyright (C) 2010-2013 David Heiko Kolf*
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
-
-
\ No newline at end of file
diff --git a/libs/mimetype.lua b/libs/mimetype.lua
deleted file mode 100644
index 4ff6c29..0000000
--- a/libs/mimetype.lua
+++ /dev/null
@@ -1,101 +0,0 @@
--- Thanks to https://github.com/catwell/lua-toolbox/blob/master/mime.types
-do
-
-local mimetype = {}
-
--- TODO: Add more?
-local types = {
- ["text/html"] = "html",
- ["text/css"] = "css",
- ["text/xml"] = "xml",
- ["image/gif"] = "gif",
- ["image/jpeg"] = "jpg",
- ["application/x-javascript"] = "js",
- ["application/atom+xml"] = "atom",
- ["application/rss+xml"] = "rss",
- ["text/mathml"] = "mml",
- ["text/plain"] = "txt",
- ["text/vnd.sun.j2me.app-descriptor"] = "jad",
- ["text/vnd.wap.wml"] = "wml",
- ["text/x-component"] = "htc",
- ["image/png"] = "png",
- ["image/tiff"] = "tiff",
- ["image/vnd.wap.wbmp"] = "wbmp",
- ["image/x-icon"] = "ico",
- ["image/x-jng"] = "jng",
- ["image/x-ms-bmp"] = "bmp",
- ["image/svg+xml"] = "svg",
- ["image/webp"] = "webp",
- ["application/java-archive"] = "jar",
- ["application/mac-binhex40"] = "hqx",
- ["application/msword"] = "doc",
- ["application/pdf"] = "pdf",
- ["application/postscript"] = "ps",
- ["application/rtf"] = "rtf",
- ["application/vnd.ms-excel"] = "xls",
- ["application/vnd.ms-powerpoint"] = "ppt",
- ["application/vnd.wap.wmlc"] = "wmlc",
- ["application/vnd.google-earth.kml+xml"] = "kml",
- ["application/vnd.google-earth.kmz"] = "kmz",
- ["application/x-7z-compressed"] = "7z",
- ["application/x-cocoa"] = "cco",
- ["application/x-java-archive-diff"] = "jardiff",
- ["application/x-java-jnlp-file"] = "jnlp",
- ["application/x-makeself"] = "run",
- ["application/x-perl"] = "pl",
- ["application/x-pilot"] = "prc",
- ["application/x-rar-compressed"] = "rar",
- ["application/x-redhat-package-manager"] = "rpm",
- ["application/x-sea"] = "sea",
- ["application/x-shockwave-flash"] = "swf",
- ["application/x-stuffit"] = "sit",
- ["application/x-tcl"] = "tcl",
- ["application/x-x509-ca-cert"] = "crt",
- ["application/x-xpinstall"] = "xpi",
- ["application/xhtml+xml"] = "xhtml",
- ["application/zip"] = "zip",
- ["application/octet-stream"] = "bin",
- ["audio/midi"] = "mid",
- ["audio/mpeg"] = "mp3",
- ["audio/ogg"] = "ogg",
- ["audio/x-m4a"] = "m4a",
- ["audio/x-realaudio"] = "ra",
- ["video/3gpp"] = "3gpp",
- ["video/mp4"] = "mp4",
- ["video/mpeg"] = "mpeg",
- ["video/quicktime"] = "mov",
- ["video/webm"] = "webm",
- ["video/x-flv"] = "flv",
- ["video/x-m4v"] = "m4v",
- ["video/x-mng"] = "mng",
- ["video/x-ms-asf"] = "asf",
- ["video/x-ms-wmv"] = "wmv",
- ["video/x-msvideo"] = "avi"
-}
-
--- Returns the common file extension from a content-type
-function mimetype.get_mime_extension(content_type)
- return types[content_type]
-end
-
--- Returns the mimetype and subtype
-function mimetype.get_content_type(extension)
- for k,v in pairs(types) do
- if v == extension then
- return k
- end
- end
-end
-
--- Returns the mimetype without the subtype
-function mimetype.get_content_type_no_sub(extension)
- for k,v in pairs(types) do
- if v == extension then
- -- Before /
- return k:match('([%w-]+)/')
- end
- end
-end
-
-return mimetype
-end
\ No newline at end of file
diff --git a/libs/redis.lua b/libs/redis.lua
deleted file mode 100644
index c09142b..0000000
--- a/libs/redis.lua
+++ /dev/null
@@ -1,47 +0,0 @@
-local Redis = require 'redis'
-local FakeRedis = require 'fakeredis'
-
-local params = {
- host = '127.0.0.1',
- port = 6379,
-}
-
--- Overwrite HGETALL
-Redis.commands.hgetall = Redis.command('hgetall', {
- response = function(reply, command, ...)
- local new_reply = { }
- for i = 1, #reply, 2 do new_reply[reply[i]] = reply[i + 1] end
- return new_reply
- end
-})
-
-local redis = nil
-
--- Won't launch an error if fails
-local ok = pcall(function()
- redis = Redis.connect(params)
-end)
-
-if not ok then
-
- local fake_func = function()
- print('\27[31mCan\'t connect with Redis, install/configure it!\27[39m')
- end
- fake_func()
- fake = FakeRedis.new()
-
- print('\27[31mRedis addr: '..params.host..'\27[39m')
- print('\27[31mRedis port: '..params.port..'\27[39m')
-
- redis = setmetatable({fakeredis=true}, {
- __index = function(a, b)
- if b ~= 'data' and fake[b] then
- fake_func(b)
- end
- return fake[b] or fake_func
- end })
-
-end
-
-
-return redis
\ No newline at end of file
diff --git a/patches/disable-python-and-libjansson.patch b/patches/disable-python-and-libjansson.patch
deleted file mode 100644
index 1093164..0000000
--- a/patches/disable-python-and-libjansson.patch
+++ /dev/null
@@ -1,130 +0,0 @@
---- tg/configure.ac 2015-10-24 14:23:51.964259062 +0200
-+++ tg/configure.ac 2015-10-24 14:05:10.111062758 +0200
-@@ -61,93 +61,43 @@
- ],[
- ])
-
-+# liblua is required
- AC_MSG_CHECKING([for liblua])
--AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua],
-- [
-- if test "x$enableval" = "xno" ; then
-- AC_MSG_RESULT([disabled])
-- else
-- AC_MSG_RESULT([enabled])
-- AX_PROG_LUA([],[],
-- [
-- AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Try --disable-liblua])])
-- AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Try --disable-liblua])])
-- [EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ]
-- [CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; ]
-- AC_DEFINE(USE_LUA,1,[use lua])
-- ],
-- [
-- AC_MSG_ERROR([No lua found. Try --disable-liblua])
-- ])
-- fi
-- ],[
-- AC_MSG_RESULT([enabled])
-- AX_PROG_LUA([],[],
-- [
-- AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Try --disable-liblua])])
-- AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Try --disable-liblua])])
-- [EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ]
-- [CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; ]
-- AC_DEFINE(USE_LUA,1,[use lua])
-- ],
-- [
-- AC_MSG_ERROR([No lua found. Try --disable-liblua])
-- ])
-- ])
--
--AC_MSG_CHECKING([for python])
--AC_ARG_ENABLE(python,[--enable-python/--disable-python],
-+AC_MSG_RESULT([enabled])
-+AX_PROG_LUA([],[],
- [
-- if test "x$enableval" = "xno" ; then
-- AC_MSG_RESULT([disabled])
-- else
-- AC_MSG_RESULT([enabled])
--
-- AX_PYTHON()
-- AC_SUBST([PYTHON_FOUND])
-- if test $PYTHON_FOUND = no ; then
-- AC_MSG_ERROR([No supported python lib version found. Try --disable-python])
-- else
-- AC_SUBST([PYTHON_LIBS])
-- AC_SUBST([PYTHON_CFLAGS])
-- EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}"
-- CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}"
-- AC_DEFINE(USE_PYTHON,1,[use python])
-- fi
-- fi
-- ],[
-- AC_MSG_RESULT([enabled])
--
-- AX_PYTHON()
-- AC_SUBST([PYTHON_FOUND])
-- if test $PYTHON_FOUND = no ; then
-- AC_MSG_ERROR([No supported python lib version found. Try --disable-python])
-- else
-- AC_SUBST([PYTHON_LIBS])
-- AC_SUBST([PYTHON_CFLAGS])
-- EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}"
-- CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}"
-- AC_DEFINE(USE_PYTHON,1,[use python])
-- fi
-+ AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Install them])])
-+ AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Install them])])
-+ [EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ]
-+ [CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; ]
-+ AC_DEFINE(USE_LUA,1,[use lua])
-+ ],
-+ [
-+ AC_MSG_ERROR([No lua found. Install lua])
- ])
-
-+# Optional
-+AC_MSG_CHECKING([for python])
-+AX_PYTHON()
-+AC_SUBST([PYTHON_FOUND])
-+if test $PYTHON_FOUND = no ; then
-+ AC_MSG_RESULT([disabled])
-+else
-+ AC_SUBST([PYTHON_LIBS])
-+ AC_SUBST([PYTHON_CFLAGS])
-+ EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}"
-+ CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}"
-+ AC_DEFINE(USE_PYTHON,1,[use python])
-+fi
-
--
-+# Optional
- AC_MSG_CHECKING([for libjansson])
--AC_ARG_ENABLE(json,[--enable-json/--disable-json],
-- [
-- if test "x$enableval" = "xno" ; then
-- AC_MSG_RESULT([disabled])
-- else
-- AC_MSG_RESULT([enabled])
-- AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json]))
-- AC_DEFINE(USE_JSON,1,[use json])
-- fi
-- ],[
-+AC_CHECK_LIB([jansson],[json_array_set_new],
-+ [
- AC_MSG_RESULT([enabled])
-- AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json]))
- AC_DEFINE(USE_JSON,1,[use json])
-- ])
-+ ],
-+ [AC_MSG_RESULT([disabled])])
-
- #check for custom prog name
- AC_MSG_CHECKING([progname])
-@@ -193,4 +143,3 @@
- AC_SUBST(EXTRA_LIBS)
- AC_CONFIG_FILES([Makefile])
- AC_OUTPUT
--
diff --git a/plugins/admin.lua b/plugins/admin.lua
deleted file mode 100644
index b30014a..0000000
--- a/plugins/admin.lua
+++ /dev/null
@@ -1,209 +0,0 @@
-local function set_bot_photo(msg, success, result)
- local receiver = get_receiver(msg)
- if success then
- local file = 'data/photos/bot.jpg'
- print('File downloaded to:', result)
- os.rename(result, file)
- print('File moved to:', file)
- set_profile_photo(file, ok_cb, false)
- send_large_msg(receiver, 'Photo changed!', ok_cb, false)
- redis:del("bot:photo")
- else
- print('Error downloading: '..msg.id)
- send_large_msg(receiver, 'Failed, please try again!', ok_cb, false)
- end
-end
-local function parsed_url(link)
- local parsed_link = URL.parse(link)
- local parsed_path = URL.parse_path(parsed_link.path)
- return parsed_path[2]
-end
-local function get_contact_list_callback (cb_extra, success, result)
- local text = " "
- for k,v in pairs(result) do
- if v.print_name and v.id and v.phone then
- text = text..string.gsub(v.print_name , "_" , " ").." ["..v.id.."] = "..v.phone.."\n"
- end
- end
- local file = io.open("contact_list.txt", "w")
- file:write(text)
- file:flush()
- file:close()
- send_document("user#id"..cb_extra.target,"contact_list.txt", ok_cb, false)--.txt format
- local file = io.open("contact_list.json", "w")
- file:write(json:encode_pretty(result))
- file:flush()
- file:close()
- send_document("user#id"..cb_extra.target,"contact_list.json", ok_cb, false)--json format
-end
-local function user_info_callback(cb_extra, success, result)
- result.access_hash = nil
- result.flags = nil
- result.phone = nil
- if result.username then
- result.username = '@'..result.username
- end
- result.print_name = result.print_name:gsub("_","")
- local text = serpent.block(result, {comment=false})
- text = text:gsub("[{}]", "")
- text = text:gsub('"', "")
- text = text:gsub(",","")
- if cb_extra.msg.to.type == "chat" then
- send_large_msg("chat#id"..cb_extra.msg.to.id, text)
- else
- send_large_msg("user#id"..cb_extra.msg.to.id, text)
- end
-end
-local function get_dialog_list_callback(cb_extra, success, result)
- local text = ""
- for k,v in pairs(result) do
- if v.peer then
- if v.peer.type == "chat" then
- text = text.."group{"..v.peer.title.."}["..v.peer.id.."]("..v.peer.members_num..")"
- else
- if v.peer.print_name and v.peer.id then
- text = text.."user{"..v.peer.print_name.."}["..v.peer.id.."]"
- end
- if v.peer.username then
- text = text.."("..v.peer.username..")"
- end
- if v.peer.phone then
- text = text.."'"..v.peer.phone.."'"
- end
- end
- end
- if v.message then
- text = text..'\nlast msg >\nmsg id = '..v.message.id
- if v.message.text then
- text = text .. "\n text = "..v.message.text
- end
- if v.message.action then
- text = text.."\n"..serpent.block(v.message.action, {comment=false})
- end
- if v.message.from then
- if v.message.from.print_name then
- text = text.."\n From > \n"..string.gsub(v.message.from.print_name, "_"," ").."["..v.message.from.id.."]"
- end
- if v.message.from.username then
- text = text.."( "..v.message.from.username.." )"
- end
- if v.message.from.phone then
- text = text.."' "..v.message.from.phone.." '"
- end
- end
- end
- text = text.."\n\n"
- end
- local file = io.open("dialog_list.txt", "w")
- file:write(text)
- file:flush()
- file:close()
- send_document("user#id"..cb_extra.target,"dialog_list.txt", ok_cb, false)--.txt format
- local file = io.open("dialog_list.json", "w")
- file:write(json:encode_pretty(result))
- file:flush()
- file:close()
- send_document("user#id"..cb_extra.target,"dialog_list.json", ok_cb, false)--json format
-end
-local function run(msg,matches)
- local data = load_data(_config.moderation.data)
- local receiver = get_receiver(msg)
- local group = msg.to.id
- if not is_admin(msg) then
- return
- end
- if msg.media then
- if msg.media.type == 'photo' and redis:get("bot:photo") then
- if redis:get("bot:photo") == 'waiting' then
- load_photo(msg.id, set_bot_photo, msg)
- end
- end
- end
- if matches[1] == "setbotphoto" then
- redis:set("bot:photo", "waiting")
- return 'Please send me bot photo now'
- end
- if matches[1] == "markread" then
- if matches[2] == "on" then
- redis:set("bot:markread", "on")
- return "Mark read > on"
- end
- if matches[2] == "off" then
- redis:del("bot:markread")
- return "Mark read > off"
- end
- return
- end
- if matches[1] == "pm" then
- send_large_msg("user#id"..matches[2],matches[3])
- return "Msg sent"
- end
- if matches[1] == "block" then
- if is_admin2(matches[2]) then
- return "You can't block admins"
- end
- block_user("user#id"..matches[2],ok_cb,false)
- return "User blocked"
- end
- if matches[1] == "unblock" then
- unblock_user("user#id"..matches[2],ok_cb,false)
- return "User unblocked"
- end
- if matches[1] == "import" then--join by group link
- local hash = parsed_url(matches[2])
- import_chat_link(hash,ok_cb,false)
- end
- if matches[1] == "contactlist" then
- get_contact_list(get_contact_list_callback, {target = msg.from.id})
- return "I've sent contact list with both json and text format to your private"
- end
- if matches[1] == "addcontact" and matches[2] then add_contact(matches[2],matches[3],matches[4],ok_cb,false)
- return "Number "..matches[2].." add from contact list"
- end
- if matches[1] == "delcontact" then
- del_contact("user#id"..matches[2],ok_cb,false)
- return "User "..matches[2].." removed from contact list"
- end
- if matches[1] == "dialoglist" then
- get_dialog_list(get_dialog_list_callback, {target = msg.from.id})
- return "I've sent dialog list with both json and text format to your private"
- end
- if matches[1] == "whois" then
- user_info("user#id"..matches[2],user_info_callback,{msg=msg})
- end
- if matches[1] == "sync_gbans" then
- if not is_sudo(msg) then-- Sudo only
- return
- end
- local url = "http://seedteam.org/Teleseed/Global_bans.json"
- local SEED_gbans = http.request(url)
- local jdat = json:decode(SEED_gbans)
- for k,v in pairs(jdat) do
- redis:hset('user:'..v, 'print_name', k)
- banall_user(v)
- print(k, v.." Globally banned")
- end
- end
- return
-end
-return {
- patterns = {
- "^[!/](pm) (%d+) (.*)$",
- "^[!/](import) (.*)$",
- "^[!/](unblock) (%d+)$",
- "^[!/](block) (%d+)$",
- "^[!/](markread) (on)$",
- "^[!/](markread) (off)$",
- "^[!/](setbotphoto)$",
- "%[(photo)%]",
- "^[!/](contactlist)$",
- "^[!/](dialoglist)$",
- "^[!/](delcontact) (%d+)$",
- "^[!/](addcontact) (.*) (.*) (.*)$",
- "^[!/](whois) (%d+)$",
- "^/(sync_gbans)$"--sync your global bans with seed
- },
- run = run,
-}
---By @imandaneshi :)
---https://github.com/SEEDTEAM/TeleSeed/blob/master/plugins/admin.lua
diff --git a/plugins/all.lua b/plugins/all.lua
deleted file mode 100644
index fe4751c..0000000
--- a/plugins/all.lua
+++ /dev/null
@@ -1,156 +0,0 @@
-do
-data = load_data(_config.moderation.data)
-local function get_msgs_user_chat(user_id, chat_id)
- local user_info = {}
- local uhash = 'user:'..user_id
- local user = redis:hgetall(uhash)
- local um_hash = 'msgs:'..user_id..':'..chat_id
- user_info.msgs = tonumber(redis:get(um_hash) or 0)
- user_info.name = user_print_name(user)..' ['..user_id..']'
- return user_info
-end
-local function chat_stats(chat_id)
- local hash = 'chat:'..chat_id..':users'
- local users = redis:smembers(hash)
- local users_info = {}
- for i = 1, #users do
- local user_id = users[i]
- local user_info = get_msgs_user_chat(user_id, chat_id)
- table.insert(users_info, user_info)
- end
- table.sort(users_info, function(a, b)
- if a.msgs and b.msgs then
- return a.msgs > b.msgs
- end
- end)
- local text = 'Chat stats:\n'
- for k,user in pairs(users_info) do
- text = text..user.name..' = '..user.msgs..'\n'
- end
- return text
-end
-
-local function get_group_type(target)
- local data = load_data(_config.moderation.data)
- local group_type = data[tostring(target)]['group_type']
- if not group_type or group_type == nil then
- return 'No group type available.'
- end
- return group_type
-end
-local function show_group_settings(target)
- local data = load_data(_config.moderation.data)
- if data[tostring(target)] then
- if data[tostring(target)]['settings']['flood_msg_max'] then
- NUM_MSG_MAX = tonumber(data[tostring(target)]['settings']['flood_msg_max'])
- print('custom'..NUM_MSG_MAX)
- else
- NUM_MSG_MAX = 5
- end
- end
- local settings = data[tostring(target)]['settings']
- local text = "Lock group name : "..settings.lock_name.."\nLock group photo : "..settings.lock_photo.."\nLock group member : "..settings.lock_member.."\nflood sensitivity : "..NUM_MSG_MAX
- return text
-end
-
-local function get_description(target)
- local data = load_data(_config.moderation.data)
- local data_cat = 'description'
- if not data[tostring(target)][data_cat] then
- return 'No description available.'
- end
- local about = data[tostring(target)][data_cat]
- return about
-end
-
-local function get_rules(target)
- local data = load_data(_config.moderation.data)
- local data_cat = 'rules'
- if not data[tostring(target)][data_cat] then
- return 'No rules available.'
- end
- local rules = data[tostring(target)][data_cat]
- return rules
-end
-
-
-local function modlist(target)
- local data = load_data(_config.moderation.data)
- local groups = 'groups'
- if not data[tostring(groups)] or not data[tostring(groups)][tostring(target)] then
- return 'Group is not added or is Realm.'
- end
- if next(data[tostring(target)]['moderators']) == nil then
- return 'No moderator in this group.'
- end
- local i = 1
- local message = '\nList of moderators :\n'
- for k,v in pairs(data[tostring(target)]['moderators']) do
- message = message ..i..' - @'..v..' [' ..k.. '] \n'
- i = i + 1
- end
- return message
-end
-
-local function get_link(target)
- local data = load_data(_config.moderation.data)
- local group_link = data[tostring(target)]['settings']['set_link']
- if not group_link or group_link == nil then
- return "No link"
- end
- return "Group link:\n"..group_link
-end
-
-local function all(target, receiver)
- local text = "All the things I know about this group\n\n"
- local group_type = get_group_type(target)
- text = text.."Group Type: \n"..group_type
- local settings = show_group_settings(target)
- text = text.."\n\nGroup settings: \n"..settings
- local rules = get_rules(target)
- text = text.."\n\nRules: \n"..rules
- local description = get_description(target)
- text = text.."\n\nAbout: \n"..description
- local modlist = modlist(target)
- text = text.."\n\nMods: \n"..modlist
- local link = get_link(target)
- text = text.."\n\nLink: \n"..link
- local stats = chat_stats(target)
- text = text.."\n\n"..stats
- local ban_list = ban_list(target)
- text = text.."\n\n"..ban_list
- local file = io.open("./groups/all/"..target.."all.txt", "w")
- file:write(text)
- file:flush()
- file:close()
- send_document(receiver,"./groups/all/"..target.."all.txt", ok_cb, false)
- return
-end
-
-function run(msg, matches)
- if matches[1] == "all" and matches[2] and is_owner2(msg.from.id, matches[2]) then
- local receiver = get_receiver(msg)
- local target = matches[2]
- return all(target, receiver)
- end
- if not is_owner(msg) then
- return
- end
- if matches[1] == "all" and not matches[2] then
- local receiver = get_receiver(msg)
- if not is_owner(msg) then
- return
- end
- return all(msg.to.id, receiver)
- end
-end
-
-
-return {
- patterns = {
- "^[!/](all)$",
- "^[!/](all) (%d+)$"
- },
- run = run
-}
-end
diff --git a/plugins/anti_spam.lua b/plugins/anti_spam.lua
deleted file mode 100644
index 689857c..0000000
--- a/plugins/anti_spam.lua
+++ /dev/null
@@ -1,134 +0,0 @@
-
---An empty table for solving multiple kicking problem(thanks to @topkecleon )
-kicktable = {}
-
-do
-
-local TIME_CHECK = 2 -- seconds
-local data = load_data(_config.moderation.data)
--- Save stats, ban user
-local function pre_process(msg)
- -- Ignore service msg
- if msg.service then
- return msg
- end
- if msg.from.id == our_id then
- return msg
- end
-
- -- Save user on Redis
- if msg.from.type == 'user' then
- local hash = 'user:'..msg.from.id
- print('Saving user', hash)
- if msg.from.print_name then
- redis:hset(hash, 'print_name', msg.from.print_name)
- end
- if msg.from.first_name then
- redis:hset(hash, 'first_name', msg.from.first_name)
- end
- if msg.from.last_name then
- redis:hset(hash, 'last_name', msg.from.last_name)
- end
- if msg.from.username then
- redis:hset(hash, 'username', msg.from.username)
- end
- end
-
- -- Save stats on Redis
- if msg.to.type == 'chat' then
- -- User is on chat
- local hash = 'chat:'..msg.to.id..':users'
- redis:sadd(hash, msg.from.id)
- end
-
-
-
- -- Total user msgs
- local hash = 'msgs:'..msg.from.id..':'..msg.to.id
- redis:incr(hash)
-
- --Load moderation data
- local data = load_data(_config.moderation.data)
- if data[tostring(msg.to.id)] then
- --Check if flood is one or off
- if data[tostring(msg.to.id)]['settings']['flood'] == 'no' then
- return msg
- end
- end
-
- -- Check flood
- if msg.from.type == 'user' then
- local hash = 'user:'..msg.from.id..':msgs'
- local msgs = tonumber(redis:get(hash) or 0)
- local data = load_data(_config.moderation.data)
- local NUM_MSG_MAX = 5
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['settings']['flood_msg_max'] then
- NUM_MSG_MAX = tonumber(data[tostring(msg.to.id)]['settings']['flood_msg_max'])--Obtain group flood sensitivity
- end
- end
- local max_msg = NUM_MSG_MAX * 1
- if msgs > max_msg then
- local user = msg.from.id
- -- Ignore mods,owner and admins
- if is_momod(msg) then
- return msg
- end
- local chat = msg.to.id
- local user = msg.from.id
- -- Return end if user was kicked before
- if kicktable[user] == true then
- return
- end
- kick_user(user, chat)
- if msg.to.type == "user" then
- block_user("user#id"..msg.from.id,ok_cb,false)--Block user if spammed in private
- end
- local name = user_print_name(msg.from)
- --save it to log file
- savelog(msg.to.id, name.." ["..msg.from.id.."] spammed and kicked ! ")
- -- incr it on redis
- local gbanspam = 'gban:spam'..msg.from.id
- redis:incr(gbanspam)
- local gbanspam = 'gban:spam'..msg.from.id
- local gbanspamonredis = redis:get(gbanspam)
- --Check if user has spammed is group more than 4 times
- if gbanspamonredis then
- if tonumber(gbanspamonredis) == 4 and not is_owner(msg) then
- --Global ban that user
- banall_user(msg.from.id)
- local gbanspam = 'gban:spam'..msg.from.id
- --reset the counter
- redis:set(gbanspam, 0)
- local username = " "
- if msg.from.username ~= nil then
- username = msg.from.username
- end
- local name = user_print_name(msg.from)
- --Send this to that chat
- send_large_msg("chat#id"..msg.to.id, "User [ "..name.." ]"..msg.from.id.." Globally banned (spamming)")
- local log_group = 1 --set log group caht id
- --send it to log group
- send_large_msg("chat#id"..log_group, "User [ "..name.." ] ( @"..username.." )"..msg.from.id.." Globally banned from ( "..msg.to.print_name.." ) [ "..msg.to.id.." ] (spamming)")
- end
- end
- kicktable[user] = true
- msg = nil
- end
- redis:setex(hash, TIME_CHECK, msgs+1)
- end
- return msg
-end
-
-local function cron()
- --clear that table on the top of the plugins
- kicktable = {}
-end
-
-return {
- patterns = {},
- cron = cron,
- pre_process = pre_process
-}
-
-end
diff --git a/plugins/arabic_lock.lua b/plugins/arabic_lock.lua
deleted file mode 100644
index 86e462f..0000000
--- a/plugins/arabic_lock.lua
+++ /dev/null
@@ -1,36 +0,0 @@
-
-antiarabic = {}-- An empty table for solving multiple kicking problem
-
-do
-local function run(msg, matches)
- if is_momod(msg) then -- Ignore mods,owner,admins
- return
- end
- local data = load_data(_config.moderation.data)
- if data[tostring(msg.to.id)]['settings']['lock_arabic'] then
- if data[tostring(msg.to.id)]['settings']['lock_arabic'] == 'yes' then
- if antiarabic[msg.from.id] == true then
- return
- end
- send_large_msg("chat#id".. msg.to.id , "Arabic is not allowed here")
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] kicked (arabic was locked) ")
- chat_del_user('chat#id'..msg.to.id,'user#id'..msg.from.id,ok_cb,false)
- antiarabic[msg.from.id] = true
- return
- end
- end
- return
-end
-local function cron()
- antiarabic = {} -- Clear antiarabic table
-end
-return {
- patterns = {
- "([\216-\219][\128-\191])"
- },
- run = run,
- cron = cron
-}
-
-end
diff --git a/plugins/banhammer.lua b/plugins/banhammer.lua
deleted file mode 100644
index eda9676..0000000
--- a/plugins/banhammer.lua
+++ /dev/null
@@ -1,331 +0,0 @@
-
-local function pre_process(msg)
- -- SERVICE MESSAGE
- if msg.action and msg.action.type then
- local action = msg.action.type
- -- Check if banned user joins chat by link
- if action == 'chat_add_user_link' then
- local user_id = msg.from.id
- print('Checking invited user '..user_id)
- local banned = is_banned(user_id, msg.to.id)
- if banned or is_gbanned(user_id) then -- Check it with redis
- print('User is banned!')
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] is banned and kicked ! ")-- Save to logs
- kick_user(user_id, msg.to.id)
- end
- end
- -- Check if banned user joins chat
- if action == 'chat_add_user' then
- local user_id = msg.action.user.id
- print('Checking invited user '..user_id)
- local banned = is_banned(user_id, msg.to.id)
- if banned or is_gbanned(user_id) then -- Check it with redis
- print('User is banned!')
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] added a banned user >"..msg.action.user.id)-- Save to logs
- kick_user(user_id, msg.to.id)
- local banhash = 'addedbanuser:'..msg.to.id..':'..msg.from.id
- redis:incr(banhash)
- local banhash = 'addedbanuser:'..msg.to.id..':'..msg.from.id
- local banaddredis = redis:get(banhash)
- if banaddredis then
- if tonumber(banaddredis) == 4 and not is_owner(msg) then
- kick_user(msg.from.id, msg.to.id)-- Kick user who adds ban ppl more than 3 times
- end
- if tonumber(banaddredis) == 8 and not is_owner(msg) then
- ban_user(msg.from.id, msg.to.id)-- Kick user who adds ban ppl more than 7 times
- local banhash = 'addedbanuser:'..msg.to.id..':'..msg.from.id
- redis:set(banhash, 0)-- Reset the Counter
- end
- end
- end
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['settings'] then
- if data[tostring(msg.to.id)]['settings']['lock_bots'] then
- bots_protection = data[tostring(msg.to.id)]['settings']['lock_bots']
- end
- end
- end
- if msg.action.user.username ~= nil then
- if string.sub(msg.action.user.username:lower(), -3) == 'bot' and not is_momod(msg) and bots_protection == "yes" then --- Will kick bots added by normal users
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] added a bot > @".. msg.action.user.username)-- Save to logs
- kick_user(msg.action.user.id, msg.to.id)
- end
- end
- end
- -- No further checks
- return msg
- end
- -- banned user is talking !
- if msg.to.type == 'chat' then
- local data = load_data(_config.moderation.data)
- local group = msg.to.id
- local texttext = 'groups'
- --if not data[tostring(texttext)][tostring(msg.to.id)] and not is_realm(msg) then -- Check if this group is one of my groups or not
- --chat_del_user('chat#id'..msg.to.id,'user#id'..our_id,ok_cb,false)
- --return
- --end
- local user_id = msg.from.id
- local chat_id = msg.to.id
- local banned = is_banned(user_id, chat_id)
- if banned or is_gbanned(user_id) then -- Check it with redis
- print('Banned user talking!')
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] banned user is talking !")-- Save to logs
- kick_user(user_id, chat_id)
- msg.text = ''
- end
- end
- return msg
-end
-
-local function kick_ban_res(extra, success, result)
---vardump(result)
---vardump(extra)
- local member_id = result.id
- local user_id = member_id
- local member = result.username
- local chat_id = extra.chat_id
- local from_id = extra.from_id
- local get_cmd = extra.get_cmd
- local receiver = "chat#id"..chat_id
- if get_cmd == "kick" then
- if member_id == from_id then
- return send_large_msg(receiver, "You can't kick yourself")
- end
- if is_momod2(member_id, chat_id) and not is_admin2(sender) then
- return send_large_msg(receiver, "You can't kick mods/owner/admins")
- end
- return kick_user(member_id, chat_id)
- elseif get_cmd == 'ban' then
- if is_momod2(member_id, chat_id) and not is_admin2(sender) then
- return send_large_msg(receiver, "You can't ban mods/owner/admins")
- end
- send_large_msg(receiver, 'User @'..member..' ['..member_id..'] banned')
- return ban_user(member_id, chat_id)
- elseif get_cmd == 'unban' then
- send_large_msg(receiver, 'User @'..member..' ['..member_id..'] unbanned')
- local hash = 'banned:'..chat_id
- redis:srem(hash, member_id)
- return 'User '..user_id..' unbanned'
- elseif get_cmd == 'banall' then
- send_large_msg(receiver, 'User @'..member..' ['..member_id..'] globally banned')
- return banall_user(member_id, chat_id)
- elseif get_cmd == 'unbanall' then
- send_large_msg(receiver, 'User @'..member..' ['..member_id..'] un-globally banned')
- return unbanall_user(member_id, chat_id)
- end
-end
-
-local function run(msg, matches)
- if matches[1]:lower() == 'id' then
- if msg.to.type == "user" then
- return "Bot ID: "..msg.to.id.. "\n\nYour ID: "..msg.from.id
- end
- if type(msg.reply_id) ~= "nil" then
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] used /id ")
- id = get_message(msg.reply_id,get_message_callback_id, false)
- elseif matches[1]:lower() == 'id' then
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] used /id ")
- return "Group ID for " ..string.gsub(msg.to.print_name, "_", " ").. ":\n\n"..msg.to.id
- end
- end
- if matches[1]:lower() == 'kickme' then-- /kickme
- local receiver = get_receiver(msg)
- if msg.to.type == 'chat' then
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] left using kickme ")-- Save to logs
- chat_del_user("chat#id"..msg.to.id, "user#id"..msg.from.id, ok_cb, false)
- end
- end
-
- if not is_momod(msg) then -- Ignore normal users
- return
- end
-
- if matches[1]:lower() == "banlist" then -- Ban list !
- local chat_id = msg.to.id
- if matches[2] and is_admin(msg) then
- chat_id = matches[2]
- end
- return ban_list(chat_id)
- end
- if matches[1]:lower() == 'ban' then-- /ban
- if type(msg.reply_id)~="nil" and is_momod(msg) then
- if is_admin(msg) then
- local msgr = get_message(msg.reply_id,ban_by_reply_admins, false)
- else
- msgr = get_message(msg.reply_id,ban_by_reply, false)
- end
- end
- local user_id = matches[2]
- local chat_id = msg.to.id
- if string.match(matches[2], '^%d+$') then
- if tonumber(matches[2]) == tonumber(our_id) then
- return
- end
- if not is_admin(msg) and is_momod2(matches[2], msg.to.id) then
- return "you can't ban mods/owner/admins"
- end
- if tonumber(matches[2]) == tonumber(msg.from.id) then
- return "You can't ban your self !"
- end
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] baned user ".. matches[2])
- ban_user(user_id, chat_id)
- else
- local cbres_extra = {
- chat_id = msg.to.id,
- get_cmd = 'ban',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- res_user(username, kick_ban_res, cbres_extra)
- end
- end
-
-
- if matches[1]:lower() == 'unban' then -- /unban
- if type(msg.reply_id)~="nil" and is_momod(msg) then
- local msgr = get_message(msg.reply_id,unban_by_reply, false)
- end
- local user_id = matches[2]
- local chat_id = msg.to.id
- local targetuser = matches[2]
- if string.match(targetuser, '^%d+$') then
- local user_id = targetuser
- local hash = 'banned:'..chat_id
- redis:srem(hash, user_id)
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] unbaned user ".. matches[2])
- return 'User '..user_id..' unbanned'
- else
- local cbres_extra = {
- chat_id = msg.to.id,
- get_cmd = 'unban',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- res_user(username, kick_ban_res, cbres_extra)
- end
- end
-
-if matches[1]:lower() == 'kick' then
- if type(msg.reply_id)~="nil" and is_momod(msg) then
- if is_admin(msg) then
- local msgr = get_message(msg.reply_id,Kick_by_reply_admins, false)
- else
- msgr = get_message(msg.reply_id,Kick_by_reply, false)
- end
- end
-
- if string.match(matches[2], '^%d+$') then
- if tonumber(matches[2]) == tonumber(our_id) then
- return
- end
- if not is_admin(msg) and is_momod2(matches[2], msg.to.id) then
- return "you can't kick mods/owner/admins"
- end
- if tonumber(matches[2]) == tonumber(msg.from.id) then
- return "You can't kick your self !"
- end
- local user_id = matches[2]
- local chat_id = msg.to.id
- name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] kicked user ".. matches[2])
- kick_user(user_id, chat_id)
- else
- local cbres_extra = {
- chat_id = msg.to.id,
- get_cmd = 'kick',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- res_user(username, kick_ban_res, cbres_extra)
- end
-end
-
-
- if not is_admin(msg) then
- return
- end
-
- if matches[1]:lower() == 'banall' then -- Global ban
- if type(msg.reply_id) ~="nil" and is_admin(msg) then
- return get_message(msg.reply_id,banall_by_reply, false)
- end
- local user_id = matches[2]
- local chat_id = msg.to.id
- local targetuser = matches[2]
- if string.match(targetuser, '^%d+$') then
- if tonumber(matches[2]) == tonumber(our_id) then
- return false
- end
- banall_user(targetuser)
- return 'User ['..user_id..' ] globally banned'
- else
- local cbres_extra = {
- chat_id = msg.to.id,
- get_cmd = 'banall',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- res_user(username, kick_ban_res, cbres_extra)
- end
- end
- if matches[1]:lower() == 'unbanall' then -- Global unban
- local user_id = matches[2]
- local chat_id = msg.to.id
- if string.match(matches[2], '^%d+$') then
- if tonumber(matches[2]) == tonumber(our_id) then
- return false
- end
- unbanall_user(user_id)
- return 'User ['..user_id..' ] removed from global ban list'
- else
- local cbres_extra = {
- chat_id = msg.to.id,
- get_cmd = 'unbanall',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- res_user(username, kick_ban_res, cbres_extra)
- end
- end
- if matches[1]:lower() == "gbanlist" then -- Global ban list
- return banall_list()
- end
-end
-
-return {
- patterns = {
- "^[!/]([Bb]anall) (.*)$",
- "^[!/]([Bb]anall)$",
- "^[!/]([Bb]anlist) (.*)$",
- "^[!/]([Bb]anlist)$",
- "^[!/]([Gg]banlist)$",
- "^[!/]([Bb]an) (.*)$",
- "^[!/]([Kk]ick)$",
- "^[!/]([Uu]nban) (.*)$",
- "^[!/]([Uu]nbanall) (.*)$",
- "^[!/]([Uu]nbanall)$",
- "^[!/]([Kk]ick) (.*)$",
- "^[!/]([Kk]ickme)$",
- "^[!/]([Bb]an)$",
- "^[!/]([Uu]nban)$",
- "^[!/]([Ii]d)$",
- "^!!tgservice (.+)$"
- },
- run = run,
- pre_process = pre_process
-}
-
diff --git a/plugins/broadcast.lua b/plugins/broadcast.lua
deleted file mode 100644
index eea356e..0000000
--- a/plugins/broadcast.lua
+++ /dev/null
@@ -1,25 +0,0 @@
-local function run(msg, matches)
- if matches[1] == 'bc' and is_admin(msg) then
- local response = matches[3]
- send_large_msg("chat#id"..matches[2], response)
- end
- if matches[1] == 'broadcast' then
- if is_sudo(msg) then -- Only sudo !
- local data = load_data(_config.moderation.data)
- local groups = 'groups'
- local response = matches[2]
- for k,v in pairs(data[tostring(groups)]) do
- chat_id = v
- local receiver = 'chat#id'..chat_id
- send_large_msg(receiver, response)
- end
- end
- end
-end
-return {
- patterns = {
- "^[!/](broadcast) +(.+)$",
- "^[!/](bc) (%d+) (.*)$"
- },
- run = run
-}
diff --git a/plugins/download_media.lua b/plugins/download_media.lua
deleted file mode 100644
index 37e1167..0000000
--- a/plugins/download_media.lua
+++ /dev/null
@@ -1,33 +0,0 @@
-local function callback(extra, success, result) -- Calback for load_photo in line 17
- if success then
- print('File downloaded to:', result)
- else
- print('Error downloading: '..extra)
- end
-end
-
-local function run(msg, matches)
- if not is_momod(msg) then -- Will download images only from mods,owner and admins
- return
- end
- if msg.media then
- if msg.media.type == 'photo' then
- load_photo(msg.id, callback, msg.id)
- end
- end
-end
-
-local function pre_process(msg)
- if not msg.text and msg.media then
- msg.text = '['..msg.media.type..']'
- end
- return msg
-end
-
-return {
- run = run,
- patterns = {
- '%[(photo)%]'
- },
- pre_process = pre_process
-}
diff --git a/plugins/get.lua b/plugins/get.lua
deleted file mode 100644
index 5ca47d5..0000000
--- a/plugins/get.lua
+++ /dev/null
@@ -1,37 +0,0 @@
-local function get_variables_hash(msg)
- if msg.to.type == 'chat' then
- return 'chat:'..msg.to.id..':variables'
- end
-end
-
-local function get_value(msg, var_name)
- local hash = get_variables_hash(msg)
- if hash then
- local value = redis:hget(hash, var_name)
- if not value then
- return
- else
- return var_name..' :\n'..value
- end
- end
-end
-
-local function run(msg, matches)
- if not is_momod(msg) then -- only for mods,owner and admins
- return
- end
- if matches[2] then
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] used /get ".. matches[2])-- save to logs
- return get_value(msg, matches[2])
- else
- return
- end
-end
-
-return {
- patterns = {
- "^([!/]get) (.+)$"
- },
- run = run
-}
diff --git a/plugins/ingroup.lua b/plugins/ingroup.lua
deleted file mode 100644
index 5606327..0000000
--- a/plugins/ingroup.lua
+++ /dev/null
@@ -1,1267 +0,0 @@
-do
-
--- Check Member
-local function check_member_autorealm(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local data = cb_extra.data
- local msg = cb_extra.msg
- for k,v in pairs(result.members) do
- local member_id = v.id
- if member_id ~= our_id then
- -- Group configuration
- data[tostring(msg.to.id)] = {
- group_type = 'Realm',
- settings = {
- set_name = string.gsub(msg.to.print_name, '_', ' '),
- lock_name = 'yes',
- lock_photo = 'no',
- lock_member = 'no',
- flood = 'yes'
- }
- }
- save_data(_config.moderation.data, data)
- local realms = 'realms'
- if not data[tostring(realms)] then
- data[tostring(realms)] = {}
- save_data(_config.moderation.data, data)
- end
- data[tostring(realms)][tostring(msg.to.id)] = msg.to.id
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'Welcome to your new realm !')
- end
- end
-end
-local function check_member_realm_add(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local data = cb_extra.data
- local msg = cb_extra.msg
- for k,v in pairs(result.members) do
- local member_id = v.id
- if member_id ~= our_id then
- -- Group configuration
- data[tostring(msg.to.id)] = {
- group_type = 'Realm',
- settings = {
- set_name = string.gsub(msg.to.print_name, '_', ' '),
- lock_name = 'yes',
- lock_photo = 'no',
- lock_member = 'no',
- flood = 'yes'
- }
- }
- save_data(_config.moderation.data, data)
- local realms = 'realms'
- if not data[tostring(realms)] then
- data[tostring(realms)] = {}
- save_data(_config.moderation.data, data)
- end
- data[tostring(realms)][tostring(msg.to.id)] = msg.to.id
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'Realm has been added!')
- end
- end
-end
-function check_member_group(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local data = cb_extra.data
- local msg = cb_extra.msg
- for k,v in pairs(result.members) do
- local member_id = v.id
- if member_id ~= our_id then
- -- Group configuration
- data[tostring(msg.to.id)] = {
- group_type = 'Group',
- moderators = {},
- set_owner = member_id ,
- settings = {
- set_name = string.gsub(msg.to.print_name, '_', ' '),
- lock_name = 'yes',
- lock_photo = 'no',
- lock_member = 'no',
- flood = 'yes',
- }
- }
- save_data(_config.moderation.data, data)
- local groups = 'groups'
- if not data[tostring(groups)] then
- data[tostring(groups)] = {}
- save_data(_config.moderation.data, data)
- end
- data[tostring(groups)][tostring(msg.to.id)] = msg.to.id
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'You have been promoted as the owner.')
- end
- end
-end
-local function check_member_modadd(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local data = cb_extra.data
- local msg = cb_extra.msg
- for k,v in pairs(result.members) do
- local member_id = v.id
- if member_id ~= our_id then
- -- Group configuration
- data[tostring(msg.to.id)] = {
- group_type = 'Group',
- moderators = {},
- set_owner = member_id ,
- settings = {
- set_name = string.gsub(msg.to.print_name, '_', ' '),
- lock_name = 'yes',
- lock_photo = 'no',
- lock_member = 'no',
- flood = 'yes',
- }
- }
- save_data(_config.moderation.data, data)
- local groups = 'groups'
- if not data[tostring(groups)] then
- data[tostring(groups)] = {}
- save_data(_config.moderation.data, data)
- end
- data[tostring(groups)][tostring(msg.to.id)] = msg.to.id
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'Group is added and you have been promoted as the owner ')
- end
- end
-end
-local function automodadd(msg)
- local data = load_data(_config.moderation.data)
- if msg.action.type == 'chat_created' then
- receiver = get_receiver(msg)
- chat_info(receiver, check_member_group,{receiver=receiver, data=data, msg = msg})
- end
-end
-local function autorealmadd(msg)
- local data = load_data(_config.moderation.data)
- if msg.action.type == 'chat_created' then
- receiver = get_receiver(msg)
- chat_info(receiver, check_member_autorealm,{receiver=receiver, data=data, msg = msg})
- end
-end
-local function check_member_realmrem(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local data = cb_extra.data
- local msg = cb_extra.msg
- for k,v in pairs(result.members) do
- local member_id = v.id
- if member_id ~= our_id then
- -- Realm configuration removal
- data[tostring(msg.to.id)] = nil
- save_data(_config.moderation.data, data)
- local realms = 'realms'
- if not data[tostring(realms)] then
- data[tostring(realms)] = nil
- save_data(_config.moderation.data, data)
- end
- data[tostring(realms)][tostring(msg.to.id)] = nil
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'Realm has been removed!')
- end
- end
-end
-local function check_member_modrem(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local data = cb_extra.data
- local msg = cb_extra.msg
- for k,v in pairs(result.members) do
- local member_id = v.id
- if member_id ~= our_id then
- -- Group configuration removal
- data[tostring(msg.to.id)] = nil
- save_data(_config.moderation.data, data)
- local groups = 'groups'
- if not data[tostring(groups)] then
- data[tostring(groups)] = nil
- save_data(_config.moderation.data, data)
- end
- data[tostring(groups)][tostring(msg.to.id)] = nil
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'Group has been removed')
- end
- end
-end
---End Check Member
-local function show_group_settingsmod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local data = load_data(_config.moderation.data)
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['settings']['flood_msg_max'] then
- NUM_MSG_MAX = tonumber(data[tostring(msg.to.id)]['settings']['flood_msg_max'])
- print('custom'..NUM_MSG_MAX)
- else
- NUM_MSG_MAX = 5
- end
- end
- local bots_protection = "Yes"
- if data[tostring(msg.to.id)]['settings']['lock_bots'] then
- bots_protection = data[tostring(msg.to.id)]['settings']['lock_bots']
- end
- local leave_ban = "no"
- if data[tostring(msg.to.id)]['settings']['leave_ban'] then
- leave_ban = data[tostring(msg.to.id)]['settings']['leave_ban']
- end
- local settings = data[tostring(target)]['settings']
- local text = "Group settings:\nLock group name : "..settings.lock_name.."\nLock group photo : "..settings.lock_photo.."\nLock group member : "..settings.lock_member.."\nLock group leave : "..leave_ban.."\nflood sensitivity : "..NUM_MSG_MAX.."\nBot protection : "..bots_protection--"\nPublic: "..public
- return text
-end
-
-local function set_descriptionmod(msg, data, target, about)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local data_cat = 'description'
- data[tostring(target)][data_cat] = about
- save_data(_config.moderation.data, data)
- return 'Set group description to:\n'..about
-end
-local function get_description(msg, data)
- local data_cat = 'description'
- if not data[tostring(msg.to.id)][data_cat] then
- return 'No description available.'
- end
- local about = data[tostring(msg.to.id)][data_cat]
- local about = string.gsub(msg.to.print_name, "_", " ")..':\n\n'..about
- return 'About '..about
-end
-local function lock_group_arabic(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic']
- if group_arabic_lock == 'yes' then
- return 'Arabic is already locked'
- else
- data[tostring(target)]['settings']['lock_arabic'] = 'yes'
- save_data(_config.moderation.data, data)
- return 'Arabic has been locked'
- end
-end
-
-local function unlock_group_arabic(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic']
- if group_arabic_lock == 'no' then
- return 'Arabic is already unlocked'
- else
- data[tostring(target)]['settings']['lock_arabic'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Arabic has been unlocked'
- end
-end
-
-local function lock_group_bots(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_bots_lock = data[tostring(target)]['settings']['lock_bots']
- if group_bots_lock == 'yes' then
- return 'Bots protection is already enabled'
- else
- data[tostring(target)]['settings']['lock_bots'] = 'yes'
- save_data(_config.moderation.data, data)
- return 'Bots protection has been enabled'
- end
-end
-
-local function unlock_group_bots(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_bots_lock = data[tostring(target)]['settings']['lock_bots']
- if group_bots_lock == 'no' then
- return 'Bots protection is already disabled'
- else
- data[tostring(target)]['settings']['lock_bots'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Bots protection has been disabled'
- end
-end
-
-local function lock_group_namemod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_name_set = data[tostring(target)]['settings']['set_name']
- local group_name_lock = data[tostring(target)]['settings']['lock_name']
- if group_name_lock == 'yes' then
- return 'Group name is already locked'
- else
- data[tostring(target)]['settings']['lock_name'] = 'yes'
- save_data(_config.moderation.data, data)
- rename_chat('chat#id'..target, group_name_set, ok_cb, false)
- return 'Group name has been locked'
- end
-end
-local function unlock_group_namemod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_name_set = data[tostring(target)]['settings']['set_name']
- local group_name_lock = data[tostring(target)]['settings']['lock_name']
- if group_name_lock == 'no' then
- return 'Group name is already unlocked'
- else
- data[tostring(target)]['settings']['lock_name'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group name has been unlocked'
- end
-end
-local function lock_group_floodmod(msg, data, target)
- if not is_owner(msg) then
- return "Only admins can do it for now"
- end
- local group_flood_lock = data[tostring(target)]['settings']['flood']
- if group_flood_lock == 'yes' then
- return 'Group flood is locked'
- else
- data[tostring(target)]['settings']['flood'] = 'yes'
- save_data(_config.moderation.data, data)
- return 'Group flood has been locked'
- end
-end
-
-local function unlock_group_floodmod(msg, data, target)
- if not is_owner(msg) then
- return "Only admins can do it for now"
- end
- local group_flood_lock = data[tostring(target)]['settings']['flood']
- if group_flood_lock == 'no' then
- return 'Group flood is not locked'
- else
- data[tostring(target)]['settings']['flood'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group flood has been unlocked'
- end
-end
-
-local function lock_group_membermod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_member_lock = data[tostring(target)]['settings']['lock_member']
- if group_member_lock == 'yes' then
- return 'Group members are already locked'
- else
- data[tostring(target)]['settings']['lock_member'] = 'yes'
- save_data(_config.moderation.data, data)
- end
- return 'Group members has been locked'
-end
-
-local function unlock_group_membermod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_member_lock = data[tostring(target)]['settings']['lock_member']
- if group_member_lock == 'no' then
- return 'Group members are not locked'
- else
- data[tostring(target)]['settings']['lock_member'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group members has been unlocked'
- end
-end
-
-
-local function set_public_membermod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_member_lock = data[tostring(target)]['settings']['public']
- if group_member_lock == 'yes' then
- return 'Group is already public'
- else
- data[tostring(target)]['settings']['public'] = 'yes'
- save_data(_config.moderation.data, data)
- end
- return 'Group is now: public'
-end
-
-local function unset_public_membermod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_member_lock = data[tostring(target)]['settings']['public']
- if group_member_lock == 'no' then
- return 'Group is not public'
- else
- data[tostring(target)]['settings']['public'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group is now: not public'
- end
-end
-
-local function lock_group_leave(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local leave_ban = data[tostring(msg.to.id)]['settings']['leave_ban']
- if leave_ban == 'yes' then
- return 'Leaving users will be banned'
- else
- data[tostring(msg.to.id)]['settings']['leave_ban'] = 'yes'
- save_data(_config.moderation.data, data)
- end
- return 'Leaving users will be banned'
-end
-
-local function unlock_group_leave(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local leave_ban = data[tostring(msg.to.id)]['settings']['leave_ban']
- if leave_ban == 'no' then
- return 'Leaving users will not be banned'
- else
- data[tostring(msg.to.id)]['settings']['leave_ban'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Leaving users will not be banned'
- end
-end
-
-local function unlock_group_photomod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_photo_lock = data[tostring(target)]['settings']['lock_photo']
- if group_photo_lock == 'no' then
- return 'Group photo is not locked'
- else
- data[tostring(target)]['settings']['lock_photo'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group photo has been unlocked'
- end
-end
-
-local function set_rulesmod(msg, data, target)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local data_cat = 'rules'
- data[tostring(target)][data_cat] = rules
- save_data(_config.moderation.data, data)
- return 'Set group rules to:\n'..rules
-end
-local function modadd(msg)
- -- superuser and admins only (because sudo are always has privilege)
- if not is_admin(msg) then
- return "You're not admin"
- end
- local data = load_data(_config.moderation.data)
- if is_group(msg) then
- return 'Group is already added.'
- end
- receiver = get_receiver(msg)
- chat_info(receiver, check_member_modadd,{receiver=receiver, data=data, msg = msg})
-end
-local function realmadd(msg)
- -- superuser and admins only (because sudo are always has privilege)
- if not is_admin(msg) then
- return "You're not admin"
- end
- local data = load_data(_config.moderation.data)
- if is_realm(msg) then
- return 'Realm is already added.'
- end
- receiver = get_receiver(msg)
- chat_info(receiver, check_member_realm_add,{receiver=receiver, data=data, msg = msg})
-end
--- Global functions
-function modrem(msg)
- -- superuser and admins only (because sudo are always has privilege)
- if not is_admin(msg) then
- return "You're not admin"
- end
- local data = load_data(_config.moderation.data)
- if not is_group(msg) then
- return 'Group is not added.'
- end
- receiver = get_receiver(msg)
- chat_info(receiver, check_member_modrem,{receiver=receiver, data=data, msg = msg})
-end
-
-function realmrem(msg)
- -- superuser and admins only (because sudo are always has privilege)
- if not is_admin(msg) then
- return "You're not admin"
- end
- local data = load_data(_config.moderation.data)
- if not is_realm(msg) then
- return 'Realm is not added.'
- end
- receiver = get_receiver(msg)
- chat_info(receiver, check_member_realmrem,{receiver=receiver, data=data, msg = msg})
-end
-local function get_rules(msg, data)
- local data_cat = 'rules'
- if not data[tostring(msg.to.id)][data_cat] then
- return 'No rules available.'
- end
- local rules = data[tostring(msg.to.id)][data_cat]
- local rules = 'Chat rules:\n'..rules
- return rules
-end
-
-local function set_group_photo(msg, success, result)
- local data = load_data(_config.moderation.data)
- local receiver = get_receiver(msg)
- if success then
- local file = 'data/photos/chat_photo_'..msg.to.id..'.jpg'
- print('File downloaded to:', result)
- os.rename(result, file)
- print('File moved to:', file)
- chat_set_photo (receiver, file, ok_cb, false)
- data[tostring(msg.to.id)]['settings']['set_photo'] = file
- save_data(_config.moderation.data, data)
- data[tostring(msg.to.id)]['settings']['lock_photo'] = 'yes'
- save_data(_config.moderation.data, data)
- send_large_msg(receiver, 'Photo saved!', ok_cb, false)
- else
- print('Error downloading: '..msg.id)
- send_large_msg(receiver, 'Failed, please try again!', ok_cb, false)
- end
-end
-
-local function promote(receiver, member_username, member_id)
- local data = load_data(_config.moderation.data)
- local group = string.gsub(receiver, 'chat#id', '')
- if not data[group] then
- return send_large_msg(receiver, 'Group is not added.')
- end
- if data[group]['moderators'][tostring(member_id)] then
- return send_large_msg(receiver, member_username..' is already a moderator.')
- end
- data[group]['moderators'][tostring(member_id)] = member_username
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, member_username..' has been promoted.')
-end
-
-local function promote_by_reply(extra, success, result)
- local msg = result
- local full_name = (msg.from.first_name or '')..' '..(msg.from.last_name or '')
- if msg.from.username then
- member_username = '@'.. msg.from.username
- else
- member_username = full_name
- end
- local member_id = msg.from.id
- if msg.to.type == 'chat' then
- return promote(get_receiver(msg), member_username, member_id)
- end
-end
-
-local function demote(receiver, member_username, member_id)
- local data = load_data(_config.moderation.data)
- local group = string.gsub(receiver, 'chat#id', '')
- if not data[group] then
- return send_large_msg(receiver, 'Group is not added.')
- end
- if not data[group]['moderators'][tostring(member_id)] then
- return send_large_msg(receiver, member_username..' is not a moderator.')
- end
- data[group]['moderators'][tostring(member_id)] = nil
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, member_username..' has been demoted.')
-end
-
-local function demote_by_reply(extra, success, result)
- local msg = result
- local full_name = (msg.from.first_name or '')..' '..(msg.from.last_name or '')
- if msg.from.username then
- member_username = '@'..msg.from.username
- else
- member_username = full_name
- end
- local member_id = msg.from.id
- if msg.to.type == 'chat' then
- return demote(get_receiver(msg), member_username, member_id)
- end
-end
-
-local function setowner_by_reply(extra, success, result)
- local msg = result
- local receiver = get_receiver(msg)
- local data = load_data(_config.moderation.data)
- local name_log = msg.from.print_name:gsub("_", " ")
- data[tostring(msg.to.id)]['set_owner'] = tostring(msg.from.id)
- save_data(_config.moderation.data, data)
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] setted ["..msg.from.id.."] as owner")
- local text = msg.from.print_name:gsub("_", " ").." is the owner now"
- return send_large_msg(receiver, text)
-end
-
-local function promote_demote_res(extra, success, result)
---vardump(result)
---vardump(extra)
- local member_id = result.id
- local member_username = "@"..result.username
- local chat_id = extra.chat_id
- local mod_cmd = extra.mod_cmd
- local receiver = "chat#id"..chat_id
- if mod_cmd == 'promote' then
- return promote(receiver, member_username, member_id)
- elseif mod_cmd == 'demote' then
- return demote(receiver, member_username, member_id)
- end
-end
-
-local function modlist(msg)
- local data = load_data(_config.moderation.data)
- local groups = "groups"
- if not data[tostring(groups)][tostring(msg.to.id)] then
- return 'Group is not added.'
- end
- -- determine if table is empty
- if next(data[tostring(msg.to.id)]['moderators']) == nil then --fix way
- return 'No moderator in this group.'
- end
- local i = 1
- local message = '\nList of moderators for ' .. string.gsub(msg.to.print_name, '_', ' ') .. ':\n'
- for k,v in pairs(data[tostring(msg.to.id)]['moderators']) do
- message = message ..i..' - '..v..' [' ..k.. '] \n'
- i = i + 1
- end
- return message
-end
-
-local function callbackres(extra, success, result)
---vardump(result)
- local user = result.id
- local name = string.gsub(result.print_name, "_", " ")
- local chat = 'chat#id'..extra.chatid
- send_large_msg(chat, user..'\n'..name)
- return user
-end
-
-
-local function help()
- local help_text = tostring(_config.help_text)
- return help_text
-end
-
-local function cleanmember(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- for k,v in pairs(result.members) do
- kick_user(v.id, result.id)
- end
-end
-
-local function killchat(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- for k,v in pairs(result.members) do
- kick_user_any(v.id, result.id)
- end
-end
-
-local function killrealm(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- for k,v in pairs(result.members) do
- kick_user_any(v.id, result.id)
- end
-end
-
-local function user_msgs(user_id, chat_id)
- local user_info
- local uhash = 'user:'..user_id
- local user = redis:hgetall(uhash)
- local um_hash = 'msgs:'..user_id..':'..chat_id
- user_info = tonumber(redis:get(um_hash) or 0)
- return user_info
-end
-
-local function kick_zero(cb_extra, success, result)
- local chat_id = cb_extra.chat_id
- local chat = "chat#id"..chat_id
- local ci_user
- local re_user
- for k,v in pairs(result.members) do
- local si = false
- ci_user = v.id
- local hash = 'chat:'..chat_id..':users'
- local users = redis:smembers(hash)
- for i = 1, #users do
- re_user = users[i]
- if tonumber(ci_user) == tonumber(re_user) then
- si = true
- end
- end
- if not si then
- if ci_user ~= our_id then
- if not is_momod2(ci_user, chat_id) then
- chat_del_user(chat, 'user#id'..ci_user, ok_cb, true)
- end
- end
- end
- end
-end
-
-local function kick_inactive(chat_id, num, receiver)
- local hash = 'chat:'..chat_id..':users'
- local users = redis:smembers(hash)
- -- Get user info
- for i = 1, #users do
- local user_id = users[i]
- local user_info = user_msgs(user_id, chat_id)
- local nmsg = user_info
- if tonumber(nmsg) < tonumber(num) then
- if not is_momod2(user_id, chat_id) then
- chat_del_user('chat#id'..chat_id, 'user#id'..user_id, ok_cb, true)
- end
- end
- end
- return chat_info(receiver, kick_zero, {chat_id = chat_id})
-end
-
-local function run(msg, matches)
- local data = load_data(_config.moderation.data)
- local receiver = get_receiver(msg)
- local name_log = user_print_name(msg.from)
- local group = msg.to.id
- if msg.media then
- if msg.media.type == 'photo' and data[tostring(msg.to.id)]['settings']['set_photo'] == 'waiting' and is_chat_msg(msg) and is_momod(msg) then
- load_photo(msg.id, set_group_photo, msg)
- end
- end
- if matches[1] == 'add' and not matches[2] then
- if is_realm(msg) then
- return 'Error: Already a realm.'
- end
- print("group "..msg.to.print_name.."("..msg.to.id..") added")
- return modadd(msg)
- end
- if matches[1] == 'add' and matches[2] == 'realm' then
- if is_group(msg) then
- return 'Error: Already a group.'
- end
- print("group "..msg.to.print_name.."("..msg.to.id..") added as a realm")
- return realmadd(msg)
- end
- if matches[1] == 'rem' and not matches[2] then
- print("group "..msg.to.print_name.."("..msg.to.id..") removed")
- return modrem(msg)
- end
- if matches[1] == 'rem' and matches[2] == 'realm' then
- print("group "..msg.to.print_name.."("..msg.to.id..") removed as a realm")
- return realmrem(msg)
- end
- if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "group" then
- return automodadd(msg)
- end
- if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "realm" then
- return autorealmadd(msg)
- end
-
- if msg.to.id and data[tostring(msg.to.id)] then
- local settings = data[tostring(msg.to.id)]['settings']
- if matches[1] == 'chat_add_user' then
- if not msg.service then
- return "Are you trying to troll me?"
- end
- local group_member_lock = settings.lock_member
- local user = 'user#id'..msg.action.user.id
- local chat = 'chat#id'..msg.to.id
- if group_member_lock == 'yes' and not is_owner2(msg.action.user.id, msg.to.id) then
- chat_del_user(chat, user, ok_cb, true)
- elseif group_member_lock == 'yes' and tonumber(msg.from.id) == tonumber(our_id) then
- return nil
- elseif group_member_lock == 'no' then
- return nil
- end
- end
- if matches[1] == 'chat_del_user' then
- if not msg.service then
- -- return "Are you trying to troll me?"
- end
- local user = 'user#id'..msg.action.user.id
- local chat = 'chat#id'..msg.to.id
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] deleted user "..user)
- end
- if matches[1] == 'chat_delete_photo' then
- if not msg.service then
- return "Are you trying to troll me?"
- end
- local group_photo_lock = settings.lock_photo
- if group_photo_lock == 'yes' then
- local picturehash = 'picture:changed:'..msg.to.id..':'..msg.from.id
- redis:incr(picturehash)
- ---
- local picturehash = 'picture:changed:'..msg.to.id..':'..msg.from.id
- local picprotectionredis = redis:get(picturehash)
- if picprotectionredis then
- if tonumber(picprotectionredis) == 4 and not is_owner(msg) then
- kick_user(msg.from.id, msg.to.id)
- end
- if tonumber(picprotectionredis) == 8 and not is_owner(msg) then
- ban_user(msg.from.id, msg.to.id)
- local picturehash = 'picture:changed:'..msg.to.id..':'..msg.from.id
- redis:set(picturehash, 0)
- end
- end
-
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] tried to deleted picture but failed ")
- chat_set_photo(receiver, settings.set_photo, ok_cb, false)
- elseif group_photo_lock == 'no' then
- return nil
- end
- end
- if matches[1] == 'chat_change_photo' and msg.from.id ~= 0 then
- if not msg.service then
- return "Are you trying to troll me?"
- end
- local group_photo_lock = settings.lock_photo
- if group_photo_lock == 'yes' then
- local picturehash = 'picture:changed:'..msg.to.id..':'..msg.from.id
- redis:incr(picturehash)
- ---
- local picturehash = 'picture:changed:'..msg.to.id..':'..msg.from.id
- local picprotectionredis = redis:get(picturehash)
- if picprotectionredis then
- if tonumber(picprotectionredis) == 4 and not is_owner(msg) then
- kick_user(msg.from.id, msg.to.id)
- end
- if tonumber(picprotectionredis) == 8 and not is_owner(msg) then
- ban_user(msg.from.id, msg.to.id)
- local picturehash = 'picture:changed:'..msg.to.id..':'..msg.from.id
- redis:set(picturehash, 0)
- end
- end
-
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] tried to change picture but failed ")
- chat_set_photo(receiver, settings.set_photo, ok_cb, false)
- elseif group_photo_lock == 'no' then
- return nil
- end
- end
- if matches[1] == 'chat_rename' then
- if not msg.service then
- return "Are you trying to troll me?"
- end
- local group_name_set = settings.set_name
- local group_name_lock = settings.lock_name
- local to_rename = 'chat#id'..msg.to.id
- if group_name_lock == 'yes' then
- if group_name_set ~= tostring(msg.to.print_name) then
- local namehash = 'name:changed:'..msg.to.id..':'..msg.from.id
- redis:incr(namehash)
- local namehash = 'name:changed:'..msg.to.id..':'..msg.from.id
- local nameprotectionredis = redis:get(namehash)
- if nameprotectionredis then
- if tonumber(nameprotectionredis) == 4 and not is_owner(msg) then
- kick_user(msg.from.id, msg.to.id)
- end
- if tonumber(nameprotectionredis) == 8 and not is_owner(msg) then
- ban_user(msg.from.id, msg.to.id)
- local namehash = 'name:changed:'..msg.to.id..':'..msg.from.id
- redis:set(namehash, 0)
- end
- end
-
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] tried to change name but failed ")
- rename_chat(to_rename, group_name_set, ok_cb, false)
- end
- elseif group_name_lock == 'no' then
- return nil
- end
- end
- if matches[1] == 'setname' and is_momod(msg) then
- local new_name = string.gsub(matches[2], '_', ' ')
- data[tostring(msg.to.id)]['settings']['set_name'] = new_name
- save_data(_config.moderation.data, data)
- local group_name_set = data[tostring(msg.to.id)]['settings']['set_name']
- local to_rename = 'chat#id'..msg.to.id
- rename_chat(to_rename, group_name_set, ok_cb, false)
-
- savelog(msg.to.id, "Group { "..msg.to.print_name.." } name changed to [ "..new_name.." ] by "..name_log.." ["..msg.from.id.."]")
- end
- if matches[1] == 'setphoto' and is_momod(msg) then
- data[tostring(msg.to.id)]['settings']['set_photo'] = 'waiting'
- save_data(_config.moderation.data, data)
- return 'Please send me new group photo now'
- end
- if matches[1] == 'promote' and not matches[2] then
- if not is_owner(msg) then
- return "Only the owner can prmote new moderators"
- end
- if type(msg.reply_id)~="nil" then
- msgr = get_message(msg.reply_id, promote_by_reply, false)
- end
- end
- if matches[1] == 'promote' and matches[2] then
- if not is_momod(msg) then
- return
- end
- if not is_owner(msg) then
- return "Only owner can promote"
- end
- local member = matches[2]
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted @".. member)
- local cbres_extra = {
- chat_id = msg.to.id,
- mod_cmd = 'promote',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- return res_user(username, promote_demote_res, cbres_extra)
- end
- if matches[1] == 'demote' and not matches[2] then
- if not is_owner(msg) then
- return "Only the owner can demote moderators"
- end
- if type(msg.reply_id)~="nil" then
- msgr = get_message(msg.reply_id, demote_by_reply, false)
- end
- end
- if matches[1] == 'demote' and matches[2] then
- if not is_momod(msg) then
- return
- end
- if not is_owner(msg) then
- return "Only owner can demote"
- end
- if string.gsub(matches[2], "@", "") == msg.from.username and not is_owner(msg) then
- return "You can't demote yourself"
- end
- local member = matches[2]
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted @".. member)
- local cbres_extra = {
- chat_id = msg.to.id,
- mod_cmd = 'demote',
- from_id = msg.from.id
- }
- local username = matches[2]
- local username = string.gsub(matches[2], '@', '')
- return res_user(username, promote_demote_res, cbres_extra)
- end
- if matches[1] == 'modlist' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group modlist")
- return modlist(msg)
- end
- if matches[1] == 'about' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group description")
- return get_description(msg, data)
- end
- if matches[1] == 'rules' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group rules")
- return get_rules(msg, data)
- end
- if matches[1] == 'set' then
- if matches[2] == 'rules' then
- rules = matches[3]
- local target = msg.to.id
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] has changed group rules to ["..matches[3].."]")
- return set_rulesmod(msg, data, target)
- end
- if matches[2] == 'about' then
- local data = load_data(_config.moderation.data)
- local target = msg.to.id
- local about = matches[3]
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] has changed group description to ["..matches[3].."]")
- return set_descriptionmod(msg, data, target, about)
- end
- end
- if matches[1] == 'lock' then
- local target = msg.to.id
- if matches[2] == 'name' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked name ")
- return lock_group_namemod(msg, data, target)
- end
- if matches[2] == 'member' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked member ")
- return lock_group_membermod(msg, data, target)
- end
- if matches[2] == 'flood' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked flood ")
- return lock_group_floodmod(msg, data, target)
- end
- if matches[2] == 'arabic' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked arabic ")
- return lock_group_arabic(msg, data, target)
- end
- if matches[2] == 'bots' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked bots ")
- return lock_group_bots(msg, data, target)
- end
- if matches[2] == 'leave' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked leaving ")
- return lock_group_leave(msg, data, target)
- end
- end
- if matches[1] == 'unlock' then
- local target = msg.to.id
- if matches[2] == 'name' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked name ")
- return unlock_group_namemod(msg, data, target)
- end
- if matches[2] == 'member' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked member ")
- return unlock_group_membermod(msg, data, target)
- end
- if matches[2] == 'photo' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked photo ")
- return unlock_group_photomod(msg, data, target)
- end
- if matches[2] == 'flood' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked flood ")
- return unlock_group_floodmod(msg, data, target)
- end
- if matches[2] == 'arabic' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked arabic ")
- return unlock_group_arabic(msg, data, target)
- end
- if matches[2] == 'bots' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked bots ")
- return unlock_group_bots(msg, data, target)
- end
- if matches[2] == 'leave' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked leaving ")
- return unlock_group_leave(msg, data, target)
- end
- end
- if matches[1] == 'settings' then
- local target = msg.to.id
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group settings ")
- return show_group_settingsmod(msg, data, target)
- end
-
- --[[if matches[1] == 'public' then
- local target = msg.to.id
- if matches[2] == 'yes' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: public")
- return set_public_membermod(msg, data, target)
- end
- if matches[2] == 'no' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: not public")
- return unset_public_membermod(msg, data, target)
- end
- end]]
-
- if matches[1] == 'newlink' and not is_realm(msg) then
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local function callback (extra , success, result)
- local receiver = 'chat#'..msg.to.id
- if success == 0 then
- return send_large_msg(receiver, '*Error: Invite link failed* \nReason: Not creator.')
- end
- send_large_msg(receiver, "Created a new link")
- data[tostring(msg.to.id)]['settings']['set_link'] = result
- save_data(_config.moderation.data, data)
- end
- local receiver = 'chat#'..msg.to.id
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] revoked group link ")
- return export_chat_link(receiver, callback, true)
- end
- if matches[1] == 'link' then
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local group_link = data[tostring(msg.to.id)]['settings']['set_link']
- if not group_link then
- return "Create a link using /newlink first !"
- end
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group link ["..group_link.."]")
- return "Group link:\n"..group_link
- end
- if matches[1] == 'setowner' and matches[2] then
- if not is_owner(msg) then
- return "For owner only!"
- end
- data[tostring(msg.to.id)]['set_owner'] = matches[2]
- save_data(_config.moderation.data, data)
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] set ["..matches[2].."] as owner")
- local text = matches[2].." added as owner"
- return text
- end
- if matches[1] == 'setowner' and not matches[2] then
- if not is_owner(msg) then
- return "only for the owner!"
- end
- if type(msg.reply_id)~="nil" then
- msgr = get_message(msg.reply_id, setowner_by_reply, false)
- end
- end
- if matches[1] == 'owner' then
- local group_owner = data[tostring(msg.to.id)]['set_owner']
- local user_info = redis:hgetall('user:'..group_owner)
- if not group_owner then
- return "no owner,ask admins in support groups to set owner for your group"
- end
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] used /owner")
- if user_info.username then
- return "Group onwer is @"..user_info.username.." ["..group_owner.."]"
- else
- return "Group owner is ["..group_owner..']'
- end
- end
- if matches[1] == 'setgpowner' then
- local receiver = "chat#id"..matches[2]
- if not is_admin(msg) then
- return "For admins only!"
- end
- data[tostring(matches[2])]['set_owner'] = matches[3]
- save_data(_config.moderation.data, data)
- local text = matches[3].." added as owner"
- send_large_msg(receiver, text)
- return
- end
- if matches[1] == 'setflood' then
- if not is_momod(msg) then
- return "For moderators only!"
- end
- if tonumber(matches[2]) < 5 or tonumber(matches[2]) > 20 then
- return "Wrong number,range is [5-20]"
- end
- local flood_max = matches[2]
- data[tostring(msg.to.id)]['settings']['flood_msg_max'] = flood_max
- save_data(_config.moderation.data, data)
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] set flood to ["..matches[2].."]")
- return 'Group flood has been set to '..matches[2]
- end
- if matches[1] == 'clean' then
- if not is_owner(msg) then
- return "Only owner can clean"
- end
- if matches[2] == 'member' then
- if not is_owner(msg) then
- return "Only admins can clean members"
- end
- local receiver = get_receiver(msg)
- chat_info(receiver, cleanmember, {receiver=receiver})
- end
- if matches[2] == 'modlist' then
- if next(data[tostring(msg.to.id)]['moderators']) == nil then --fix way
- return 'No moderator in this group.'
- end
- local message = '\nList of moderators for ' .. string.gsub(msg.to.print_name, '_', ' ') .. ':\n'
- for k,v in pairs(data[tostring(msg.to.id)]['moderators']) do
- data[tostring(msg.to.id)]['moderators'][tostring(k)] = nil
- save_data(_config.moderation.data, data)
- end
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] cleaned modlist")
- end
- if matches[2] == 'rules' then
- local data_cat = 'rules'
- data[tostring(msg.to.id)][data_cat] = nil
- save_data(_config.moderation.data, data)
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] cleaned rules")
- end
- if matches[2] == 'about' then
- local data_cat = 'description'
- data[tostring(msg.to.id)][data_cat] = nil
- save_data(_config.moderation.data, data)
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] cleaned about")
- end
- end
- if matches[1] == 'kill' and matches[2] == 'chat' then
- if not is_admin(msg) then
- return nil
- end
- if not is_realm(msg) then
- local receiver = get_receiver(msg)
- return modrem(msg),
- print("Closing Group..."),
- chat_info(receiver, killchat, {receiver=receiver})
- else
- return 'This is a realm'
- end
- end
- if matches[1] == 'kill' and matches[2] == 'realm' then
- if not is_admin(msg) then
- return nil
- end
- if not is_group(msg) then
- local receiver = get_receiver(msg)
- return realmrem(msg),
- print("Closing Realm..."),
- chat_info(receiver, killrealm, {receiver=receiver})
- else
- return 'This is a group'
- end
- end
- if matches[1] == 'help' then
- if not is_momod(msg) or is_realm(msg) then
- return
- end
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /help")
- return help()
- end
- if matches[1] == 'res' and is_momod(msg) then
- local cbres_extra = {
- chatid = msg.to.id
- }
- local username = matches[2]
- local username = username:gsub("@","")
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /res "..username)
- return res_user(username, callbackres, cbres_extra)
- end
- if matches[1] == 'kickinactive' then
- --send_large_msg('chat#id'..msg.to.id, 'I\'m in matches[1]')
- if not is_momod(msg) then
- return 'Only a moderator can kick inactive users'
- end
- local num = 1
- if matches[2] then
- num = matches[2]
- end
- local chat_id = msg.to.id
- local receiver = get_receiver(msg)
- return kick_inactive(chat_id, num, receiver)
- end
- end
-end
-
-return {
- patterns = {
- "^[!/](add)$",
- "^[!/](add) (realm)$",
- "^[!/](rem)$",
- "^[!/](rem) (realm)$",
- "^[!/](rules)$",
- "^[!/](about)$",
- "^[!/](setname) (.*)$",
- "^[!/](setphoto)$",
- "^[!/](promote) (.*)$",
- "^[!/](promote)",
- "^[!/](help)$",
- "^[!/](clean) (.*)$",
- "^[!/](kill) (chat)$",
- "^[!/](kill) (realm)$",
- "^[!/](demote) (.*)$",
- "^[!/](demote)",
- "^[!/](set) ([^%s]+) (.*)$",
- "^[!/](lock) (.*)$",
- "^[!/](setowner) (%d+)$",
- "^[!/](setowner)",
- "^[!/](owner)$",
- "^[!/](res) (.*)$",
- "^[!/](setgpowner) (%d+) (%d+)$",-- (group id) (owner id)
- "^[!/](unlock) (.*)$",
- "^[!/](setflood) (%d+)$",
- "^[!/](settings)$",
--- "^[!/](public) (.*)$",
- "^[!/](modlist)$",
- "^[!/](newlink)$",
- "^[!/](link)$",
- "^[!/](kickinactive)$",
- "^[!/](kickinactive) (%d+)$",
- "%[(photo)%]",
- "^!!tgservice (.+)$",
- },
- run = run
-}
-end
-
-
diff --git a/plugins/inpm.lua b/plugins/inpm.lua
deleted file mode 100644
index 5c031f6..0000000
--- a/plugins/inpm.lua
+++ /dev/null
@@ -1,90 +0,0 @@
-do
-local function pairsByKeys (t, f)
- local a = {}
- for n in pairs(t) do table.insert(a, n) end
- table.sort(a, f)
- local i = 0 -- iterator variable
- local iter = function () -- iterator function
- i = i + 1
- if a[i] == nil then return nil
- else return a[i], t[a[i]]
- end
- end
- return iter
- end
-
-local function chat_list(msg)
- local data = load_data(_config.moderation.data)
- local groups = 'groups'
- if not data[tostring(groups)] then
- return 'No groups at the moment'
- end
- local message = 'List of Groups:\n*Use /join (ID) to join*\n\n '
- for k,v in pairs(data[tostring(groups)]) do
- local settings = data[tostring(v)]['settings']
- for m,n in pairsByKeys(settings) do
- if m == 'set_name' then
- name = n
- end
- end
-
- message = message .. 'š„ '.. name .. ' (ID: ' .. v .. ')\n\n '
- end
- local file = io.open("./groups/lists/listed_groups.txt", "w")
- file:write(message)
- file:flush()
- file:close()
- return message
-end
-
-local function run(msg, matches)
- if msg.to.type ~= 'chat' or is_sudo(msg) or is_admin(msg) and is_realm(msg) then
- local data = load_data(_config.moderation.data)
- if matches[1] == 'join' and data[tostring(matches[2])] then
- if is_banned(msg.from.id, matches[2]) then
- return 'You are banned.'
- end
- if is_gbanned(msg.from.id) then
- return 'You are globally banned.'
- end
- if data[tostring(matches[2])]['settings']['lock_member'] == 'yes' and not is_owner2(msg.from.id, matches[2]) then
- return 'Group is private.'
- end
- local chat_id = "chat#id"..matches[2]
- local user_id = "user#id"..msg.from.id
- chat_add_user(chat_id, user_id, ok_cb, false)
- local group_name = data[tostring(matches[2])]['settings']['set_name']
- return "Added you to chat:\n\nš„"..group_name.." (ID:"..matches[2]..")"
- elseif matches[1] == 'join' and not data[tostring(matches[2])] then
-
- return "Chat not found."
- end
- if matches[1] == 'chats'then
- if is_admin(msg) and msg.to.type == 'chat' then
- return chat_list(msg)
- elseif msg.to.type ~= 'chat' then
- return chat_list(msg)
- end
- end
- if matches[1] == 'chatlist'then
- if is_admin(msg) and msg.to.type == 'chat' then
- send_document("chat#id"..msg.from.id, "./groups/lists/listed_groups.txt", ok_cb, false)
- elseif msg.to.type ~= 'chat' then
- send_document("user#id"..msg.from.id, "./groups/lists/listed_groups.txt", ok_cb, false)
- end
- end
-end
-end
-
-return {
- patterns = {
- "^[/!](chats)$",
- "^[/!](chatlist)$",
- "^[/!](join) (.*)$",
- "^[/!](kickme) (.*)$",
- "^!!tgservice (chat_add_user)$"
- },
- run = run,
-}
-end
-
diff --git a/plugins/inrealm.lua b/plugins/inrealm.lua
deleted file mode 100644
index 3388fa7..0000000
--- a/plugins/inrealm.lua
+++ /dev/null
@@ -1,687 +0,0 @@
--- data saved to moderation.json
--- check moderation plugin
-do
-
-local function create_group(msg)
- -- superuser and admins only (because sudo are always has privilege)
- if is_sudo(msg) or is_realm(msg) and is_admin(msg) then
- local group_creator = msg.from.print_name
- create_group_chat (group_creator, group_name, ok_cb, false)
- return 'Group [ '..string.gsub(group_name, '_', ' ')..' ] has been created.'
- end
-end
-
-local function create_realm(msg)
- -- superuser and admins only (because sudo are always has privilege)
- if is_sudo(msg) or is_realm(msg) and is_admin(msg) then
- local group_creator = msg.from.print_name
- create_group_chat (group_creator, group_name, ok_cb, false)
- return 'Realm [ '..string.gsub(group_name, '_', ' ')..' ] has been created.'
- end
-end
-
-
-local function killchat(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- for k,v in pairs(result.members) do
- kick_user_any(v.id, result.id)
- end
-end
-
-local function killrealm(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- for k,v in pairs(result.members) do
- kick_user_any(v.id, result.id)
- end
-end
-
-local function get_group_type(msg)
- local data = load_data(_config.moderation.data)
- if data[tostring(msg.to.id)] then
- if not data[tostring(msg.to.id)]['group_type'] then
- return 'No group type available.'
- end
- local group_type = data[tostring(msg.to.id)]['group_type']
- return group_type
- else
- return 'Chat type not found.'
- end
-end
-
-local function callbackres(extra, success, result)
---vardump(result)
- local user = result.id
- local name = string.gsub(result.print_name, "_", " ")
- local chat = 'chat#id'..extra.chatid
- send_large_msg(chat, user..'\n'..name)
- return user
-end
-
-local function set_description(msg, data, target, about)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local data_cat = 'description'
- data[tostring(target)][data_cat] = about
- save_data(_config.moderation.data, data)
- return 'Set group description to:\n'..about
-end
-
-local function set_rules(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local data_cat = 'rules'
- data[tostring(target)][data_cat] = rules
- save_data(_config.moderation.data, data)
- return 'Set group rules to:\n'..rules
-end
--- lock/unlock group name. bot automatically change group name when locked
-local function lock_group_name(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_name_set = data[tostring(target)]['settings']['set_name']
- local group_name_lock = data[tostring(target)]['settings']['lock_name']
- if group_name_lock == 'yes' then
- return 'Group name is already locked'
- else
- data[tostring(target)]['settings']['lock_name'] = 'yes'
- save_data(_config.moderation.data, data)
- rename_chat('chat#id'..target, group_name_set, ok_cb, false)
- return 'Group name has been locked'
- end
-end
-
-local function unlock_group_name(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_name_set = data[tostring(target)]['settings']['set_name']
- local group_name_lock = data[tostring(target)]['settings']['lock_name']
- if group_name_lock == 'no' then
- return 'Group name is already unlocked'
- else
- data[tostring(target)]['settings']['lock_name'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group name has been unlocked'
- end
-end
---lock/unlock group member. bot automatically kick new added user when locked
-local function lock_group_member(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_member_lock = data[tostring(target)]['settings']['lock_member']
- if group_member_lock == 'yes' then
- return 'Group members are already locked'
- else
- data[tostring(target)]['settings']['lock_member'] = 'yes'
- save_data(_config.moderation.data, data)
- end
- return 'Group members has been locked'
-end
-
-local function unlock_group_member(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_member_lock = data[tostring(target)]['settings']['lock_member']
- if group_member_lock == 'no' then
- return 'Group members are not locked'
- else
- data[tostring(target)]['settings']['lock_member'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group members has been unlocked'
- end
-end
-
---lock/unlock group photo. bot automatically keep group photo when locked
-local function lock_group_photo(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_photo_lock = data[tostring(target)]['settings']['lock_photo']
- if group_photo_lock == 'yes' then
- return 'Group photo is already locked'
- else
- data[tostring(target)]['settings']['set_photo'] = 'waiting'
- save_data(_config.moderation.data, data)
- end
- return 'Please send me the group photo now'
-end
-
-local function unlock_group_photo(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_photo_lock = data[tostring(target)]['settings']['lock_photo']
- if group_photo_lock == 'no' then
- return 'Group photo is not locked'
- else
- data[tostring(target)]['settings']['lock_photo'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group photo has been unlocked'
- end
-end
-
-local function lock_group_flood(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_flood_lock = data[tostring(target)]['settings']['flood']
- if group_flood_lock == 'yes' then
- return 'Group flood is locked'
- else
- data[tostring(target)]['settings']['flood'] = 'yes'
- save_data(_config.moderation.data, data)
- return 'Group flood has been locked'
- end
-end
-
-local function unlock_group_flood(msg, data, target)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local group_flood_lock = data[tostring(target)]['settings']['flood']
- if group_flood_lock == 'no' then
- return 'Group flood is not locked'
- else
- data[tostring(target)]['settings']['flood'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group flood has been unlocked'
- end
-end
--- show group settings
-local function show_group_settings(msg, data, target)
- local data = load_data(_config.moderation.data, data)
- if not is_admin(msg) then
- return "For admins only!"
- end
- local settings = data[tostring(target)]['settings']
- local text = "Group settings:\nLock group name : "..settings.lock_name.."\nLock group photo : "..settings.lock_photo.."\nLock group member : "..settings.lock_member
- return text
-end
-
-local function returnids(cb_extra, success, result)
-
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- local text = 'Users in '..string.gsub(chatname,"_"," ")..' ('..result.id..'):'..'\n'..''
- for k,v in pairs(result.members) do
- if v.print_name then
- local username = ""
- text = text .. "- " .. string.gsub(v.print_name,"_"," ") .. " (" .. v.id .. ") \n"
- end
- end
- send_large_msg(receiver, text)
- local file = io.open("./groups/lists/"..result.id.."memberlist.txt", "w")
- file:write(text)
- file:flush()
- file:close()
-end
-
-local function returnidsfile(cb_extra, success, result)
- local receiver = cb_extra.receiver
- local chat_id = "chat#id"..result.id
- local chatname = result.print_name
- local text = 'Users in '..string.gsub(chatname,"_"," ")..' ('..result.id..'):'..'\n'..''
- for k,v in pairs(result.members) do
- if v.print_name then
- local username = ""
- text = text .. "- " .. string.gsub(v.print_name,"_"," ") .. " (" .. v.id .. ") \n"
- end
- end
- local file = io.open("./groups/lists/"..result.id.."memberlist.txt", "w")
- file:write(text)
- file:flush()
- file:close()
- send_document("chat#id"..result.id,"./groups/lists/"..result.id.."memberlist.txt", ok_cb, false)
-end
-
-local function admin_promote(msg, admin_id)
- if not is_sudo(msg) then
- return "Access denied!"
- end
- local admins = 'admins'
- if not data[tostring(admins)] then
- data[tostring(admins)] = {}
- save_data(_config.moderation.data, data)
- end
- if data[tostring(admins)][tostring(admin_id)] then
- return admin_name..' is already an admin.'
- end
- data[tostring(admins)][tostring(admin_id)] = admin_id
- save_data(_config.moderation.data, data)
- return admin_id..' has been promoted as admin.'
-end
-
-local function admin_demote(msg, admin_id)
- if not is_sudo(msg) then
- return "Access denied!"
- end
- local data = load_data(_config.moderation.data)
- local admins = 'admins'
- if not data[tostring(admins)] then
- data[tostring(admins)] = {}
- save_data(_config.moderation.data, data)
- end
- if not data[tostring(admins)][tostring(admin_id)] then
- return admin_id..' is not an admin.'
- end
- data[tostring(admins)][tostring(admin_id)] = nil
- save_data(_config.moderation.data, data)
- return admin_id..' has been demoted from admin.'
-end
-
-local function admin_list(msg)
- local data = load_data(_config.moderation.data)
- local admins = 'admins'
- if not data[tostring(admins)] then
- data[tostring(admins)] = {}
- save_data(_config.moderation.data, data)
- end
- local message = 'List for Realm admins:\n'
- for k,v in pairs(data[tostring(admins)]) do
- message = message .. '- (at)' .. v .. ' [' .. k .. '] ' ..'\n'
- end
- return message
-end
-
-local function groups_list(msg)
- local data = load_data(_config.moderation.data)
- local groups = 'groups'
- if not data[tostring(groups)] then
- return 'No groups at the moment'
- end
- local message = 'List of groups:\n'
- for k,v in pairs(data[tostring(groups)]) do
- local settings = data[tostring(v)]['settings']
- for m,n in pairs(settings) do
- if m == 'set_name' then
- name = n
- end
- end
- local group_owner = "No owner"
- if data[tostring(v)]['set_owner'] then
- group_owner = tostring(data[tostring(v)]['set_owner'])
- end
- local group_link = "No link"
- if data[tostring(v)]['settings']['set_link'] then
- group_link = data[tostring(v)]['settings']['set_link']
- end
-
- message = message .. '- '.. name .. ' (' .. v .. ') ['..group_owner..'] \n {'..group_link.."}\n"
-
-
- end
- local file = io.open("./groups/lists/groups.txt", "w")
- file:write(message)
- file:flush()
- file:close()
- return message
-
-end
-local function realms_list(msg)
- local data = load_data(_config.moderation.data)
- local realms = 'realms'
- if not data[tostring(realms)] then
- return 'No Realms at the moment'
- end
- local message = 'List of Realms:\n'
- for k,v in pairs(data[tostring(realms)]) do
- local settings = data[tostring(v)]['settings']
- for m,n in pairs(settings) do
- if m == 'set_name' then
- name = n
- end
- end
- local group_owner = "No owner"
- if data[tostring(v)]['admins_in'] then
- group_owner = tostring(data[tostring(v)]['admins_in'])
- end
- local group_link = "No link"
- if data[tostring(v)]['settings']['set_link'] then
- group_link = data[tostring(v)]['settings']['set_link']
- end
- message = message .. '- '.. name .. ' (' .. v .. ') ['..group_owner..'] \n {'..group_link.."}\n"
- end
- local file = io.open("./groups/lists/realms.txt", "w")
- file:write(message)
- file:flush()
- file:close()
- return message
-end
-local function admin_user_promote(receiver, member_username, member_id)
- local data = load_data(_config.moderation.data)
- if not data['admins'] then
- data['admins'] = {}
- save_data(_config.moderation.data, data)
- end
- if data['admins'][tostring(member_id)] then
- return send_large_msg(receiver, member_username..' is already as admin.')
- end
- data['admins'][tostring(member_id)] = member_username
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, '@'..member_username..' has been promoted as admin.')
-end
-
-local function admin_user_demote(receiver, member_username, member_id)
- local data = load_data(_config.moderation.data)
- if not data['admins'] then
- data['admins'] = {}
- save_data(_config.moderation.data, data)
- end
- if not data['admins'][tostring(member_id)] then
- return send_large_msg(receiver, member_username..' is not an admin.')
- end
- data['admins'][tostring(member_id)] = nil
- save_data(_config.moderation.data, data)
- return send_large_msg(receiver, 'Admin '..member_username..' has been demoted.')
-end
-
-
-local function username_id(cb_extra, success, result)
- local mod_cmd = cb_extra.mod_cmd
- local receiver = cb_extra.receiver
- local member = cb_extra.member
- local text = 'No user @'..member..' in this group.'
- for k,v in pairs(result.members) do
- vusername = v.username
- if vusername == member then
- member_username = member
- member_id = v.id
- if mod_cmd == 'addadmin' then
- return admin_user_promote(receiver, member_username, member_id)
- elseif mod_cmd == 'removeadmin' then
- return admin_user_demote(receiver, member_username, member_id)
- end
- end
- end
- send_large_msg(receiver, text)
-end
-
-local function set_log_group(msg)
- if not is_admin(msg) then
- return
- end
- local log_group = data[tostring(groups)][tostring(msg.to.id)]['log_group']
- if log_group == 'yes' then
- return 'Log group is already set'
- else
- data[tostring(groups)][tostring(msg.to.id)]['log_group'] = 'yes'
- save_data(_config.moderation.data, data)
- return 'Log group has been set'
- end
-end
-
-local function unset_log_group(msg)
- if not is_admin(msg) then
- return
- end
- local log_group = data[tostring(groups)][tostring(msg.to.id)]['log_group']
- if log_group == 'no' then
- return 'Log group is already disabled'
- else
- data[tostring(groups)][tostring(msg.to.id)]['log_group'] = 'no'
- save_data(_config.moderation.data, data)
- return 'log group has been disabled'
- end
-end
-
-local function help()
- local help_text = tostring(_config.help_text_realm)
- return help_text
-end
-
-function run(msg, matches)
- --vardump(msg)
- local name_log = user_print_name(msg.from)
- if matches[1] == 'log' and is_owner(msg) then
- savelog(msg.to.id, "log file created by owner")
- send_document("chat#id"..msg.to.id,"./groups/"..msg.to.id.."log.txt", ok_cb, false)
- end
-
- if matches[1] == 'who' and is_momod(msg) then
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] requested member list ")
- local receiver = get_receiver(msg)
- chat_info(receiver, returnidsfile, {receiver=receiver})
- end
- if matches[1] == 'wholist' and is_momod(msg) then
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] requested member list in a file")
- local receiver = get_receiver(msg)
- chat_info(receiver, returnids, {receiver=receiver})
- end
-
- if matches[1] == 'creategroup' and matches[2] then
- group_name = matches[2]
- group_type = 'group'
- return create_group(msg)
- end
-
- if not is_sudo(msg) or not is_admin(msg) and not is_realm(msg) then
- return --Do nothing
- end
-
- if matches[1] == 'createrealm' and matches[2] then
- group_name = matches[2]
- group_type = 'realm'
- return create_realm(msg)
- end
-
- local data = load_data(_config.moderation.data)
- local receiver = get_receiver(msg)
- if matches[2] then if data[tostring(matches[2])] then
- local settings = data[tostring(matches[2])]['settings']
- if matches[1] == 'setabout' and matches[2] then
- local target = matches[2]
- local about = matches[3]
- return set_description(msg, data, target, about)
- end
- if matches[1] == 'setrules' then
- rules = matches[3]
- local target = matches[2]
- return set_rules(msg, data, target)
- end
- if matches[1] == 'lock' then --group lock *
- local target = matches[2]
- if matches[3] == 'name' then
- return lock_group_name(msg, data, target)
- end
- if matches[3] == 'member' then
- return lock_group_member(msg, data, target)
- end
- if matches[3] == 'photo' then
- return lock_group_photo(msg, data, target)
- end
- if matches[3] == 'flood' then
- return lock_group_flood(msg, data, target)
- end
- end
- if matches[1] == 'unlock' then --group unlock *
- local target = matches[2]
- if matches[3] == 'name' then
- return unlock_group_name(msg, data, target)
- end
- if matches[3] == 'member' then
- return unlock_group_member(msg, data, target)
- end
- if matches[3] == 'photo' then
- return unlock_group_photo(msg, data, target)
- end
- if matches[3] == 'flood' then
- return unlock_group_flood(msg, data, target)
- end
- end
- if matches[1] == 'settings' and data[tostring(matches[2])]['settings'] then
- local target = matches[2]
- return show_group_settings(msg, data, target)
- end
-
- if matches[1] == 'setname' and is_realm(msg) then
- local new_name = string.gsub(matches[2], '_', ' ')
- data[tostring(msg.to.id)]['settings']['set_name'] = new_name
- save_data(_config.moderation.data, data)
- local group_name_set = data[tostring(msg.to.id)]['settings']['set_name']
- local to_rename = 'chat#id'..msg.to.id
- rename_chat(to_rename, group_name_set, ok_cb, false)
- savelog(msg.to.id, "Realm { "..msg.to.print_name.." } name changed to [ "..new_name.." ] by "..name_log.." ["..msg.from.id.."]")
- end
- if matches[1] == 'setgpname' and is_admin(msg) then
- local new_name = string.gsub(matches[3], '_', ' ')
- data[tostring(matches[2])]['settings']['set_name'] = new_name
- save_data(_config.moderation.data, data)
- local group_name_set = data[tostring(matches[2])]['settings']['set_name']
- local to_rename = 'chat#id'..matches[2]
- rename_chat(to_rename, group_name_set, ok_cb, false)
- savelog(msg.to.id, "Group { "..msg.to.print_name.." } name changed to [ "..new_name.." ] by "..name_log.." ["..msg.from.id.."]")
- end
-
- end
- end
- if matches[1] == 'help' and is_realm(msg) then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /help")
- return help()
- end
- if matches[1] == 'set' then
- if matches[2] == 'loggroup' then
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] set as log group")
- return set_log_group(msg)
- end
- end
- if matches[1] == 'kill' and matches[2] == 'chat' then
- if not is_admin(msg) then
- return nil
- end
- if is_realm(msg) then
- local receiver = 'chat#id'..matches[3]
- return modrem(msg),
- print("Closing Group: "..receiver),
- chat_info(receiver, killchat, {receiver=receiver})
- else
- return 'Error: Group '..matches[3]..' not found'
- end
- end
- if matches[1] == 'kill' and matches[2] == 'realm' then
- if not is_admin(msg) then
- return nil
- end
- if is_realm(msg) then
- local receiver = 'chat#id'..matches[3]
- return realmrem(msg),
- print("Closing realm: "..receiver),
- chat_info(receiver, killrealm, {receiver=receiver})
- else
- return 'Error: Realm '..matches[3]..' not found'
- end
- end
- if matches[1] == 'chat_add_user' then
- if not msg.service then
- return "Are you trying to troll me?"
- end
- local user = 'user#id'..msg.action.user.id
- local chat = 'chat#id'..msg.to.id
- if not is_admin(msg) then
- chat_del_user(chat, user, ok_cb, true)
- end
- end
- if matches[1] == 'addadmin' then
- if string.match(matches[2], '^%d+$') then
- local admin_id = matches[2]
- print("user "..admin_id.." has been promoted as admin")
- return admin_promote(msg, admin_id)
- else
- local member = string.gsub(matches[2], "@", "")
- local mod_cmd = "addadmin"
- chat_info(receiver, username_id, {mod_cmd= mod_cmd, receiver=receiver, member=member})
- end
- end
- if matches[1] == 'removeadmin' then
- if string.match(matches[2], '^%d+$') then
- local admin_id = matches[2]
- print("user "..admin_id.." has been demoted")
- return admin_demote(msg, admin_id)
- else
- local member = string.gsub(matches[2], "@", "")
- local mod_cmd = "removeadmin"
- chat_info(receiver, username_id, {mod_cmd= mod_cmd, receiver=receiver, member=member})
- end
- end
- if matches[1] == 'type'then
- local group_type = get_group_type(msg)
- return group_type
- end
- if matches[1] == 'list' and matches[2] == 'admins' then
- return admin_list(msg)
- end
- if matches[1] == 'list' and matches[2] == 'groups' then
- if msg.to.type == 'chat' then
- groups_list(msg)
- send_document("chat#id"..msg.to.id, "./groups/lists/groups.txt", ok_cb, false)
- return "Group list created" --group_list(msg)
- elseif msg.to.type == 'user' then
- groups_list(msg)
- send_document("user#id"..msg.from.id, "./groups/lists/groups.txt", ok_cb, false)
- return "Group list created" --group_list(msg)
- end
- end
- if matches[1] == 'list' and matches[2] == 'realms' then
- if msg.to.type == 'chat' then
- realms_list(msg)
- send_document("chat#id"..msg.to.id, "./groups/lists/realms.txt", ok_cb, false)
- return "Realms list created" --realms_list(msg)
- elseif msg.to.type == 'user' then
- realms_list(msg)
- send_document("user#id"..msg.from.id, "./groups/lists/realms.txt", ok_cb, false)
- return "Realms list created" --realms_list(msg)
- end
- end
- if matches[1] == 'res' and is_momod(msg) then
- local cbres_extra = {
- chatid = msg.to.id
- }
- local username = matches[2]
- local username = username:gsub("@","")
- savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /res "..username)
- return res_user(username, callbackres, cbres_extra)
- end
-end
-
-
-
-return {
- patterns = {
- "^[!/](creategroup) (.*)$",
- "^[!/](createrealm) (.*)$",
- "^[!/](setabout) (%d+) (.*)$",
- "^[!/](setrules) (%d+) (.*)$",
- "^[!/](setname) (.*)$",
- "^[!/](setgpname) (%d+) (.*)$",
- "^[!/](setname) (%d+) (.*)$",
- "^[!/](lock) (%d+) (.*)$",
- "^[!/](unlock) (%d+) (.*)$",
- "^[!/](setting) (%d+)$",
- "^[!/](wholist)$",
- "^[!/](who)$",
- "^[!/](type)$",
- "^[!/](kill) (chat) (%d+)$",
- "^[!/](kill) (realm) (%d+)$",
- "^[!/](addadmin) (.*)$", -- sudoers only
- "^[!/](removeadmin) (.*)$", -- sudoers only
- "^[!/](list) (.*)$",
- "^[!/](log)$",
- "^[!/](help)$",
- "^!!tgservice (.+)$",
- },
- run = run
-}
-end
-
-
diff --git a/plugins/invite.lua b/plugins/invite.lua
deleted file mode 100644
index 45c07fd..0000000
--- a/plugins/invite.lua
+++ /dev/null
@@ -1,41 +0,0 @@
-do
-local function callbackres(extra, success, result) -- Callback for res_user in line 27
- local user = 'user#id'..result.id
- local chat = 'chat#id'..extra.chatid
- if is_banned(result.id, extra.chatid) then -- Ignore bans
- send_large_msg(chat, 'User is banned.')
- elseif is_gbanned(result.id) then -- Ignore globall bans
- send_large_msg(chat, 'User is globaly banned.')
- else
- chat_add_user(chat, user, ok_cb, false) -- Add user on chat
- end
-end
-function run(msg, matches)
- local data = load_data(_config.moderation.data)
- if not is_realm(msg) then
- if data[tostring(msg.to.id)] and data[tostring(msg.to.id)]['settings']['lock_member'] == 'yes' and not is_admin(msg) then
- return 'Group is private.'
- end
- end
- if msg.to.type ~= 'chat' then
- return
- end
- if not is_momod(msg) then
- return
- end
- --if not is_admin(msg) then -- For admins only !
- --return 'Only admins can invite.'
- --end
- local cbres_extra = {chatid = msg.to.id}
- local username = matches[1]
- local username = username:gsub("@","")
- res_user(username, callbackres, cbres_extra)
-end
-return {
- patterns = {
- "^[!/]invite (.*)$"
- },
- run = run
-}
-
-end
diff --git a/plugins/leave_ban.lua b/plugins/leave_ban.lua
deleted file mode 100644
index 6a69a7f..0000000
--- a/plugins/leave_ban.lua
+++ /dev/null
@@ -1,26 +0,0 @@
-local function run(msg, matches)
- local data = load_data(_config.moderation.data)
- if msg.action and msg.action.type then
- local action = msg.action.type
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['settings'] then
- if data[tostring(msg.to.id)]['settings']['leave_ban'] then
- leave_ban = data[tostring(msg.to.id)]['settings']['leave_ban']
- end
- end
- end
- if action == 'chat_del_user' and not is_momod2(msg.action.user.id) and leave_ban == 'yes' then
- local user_id = msg.action.user.id
- local chat_id = msg.to.id
- ban_user(user_id, chat_id)
- end
- end
- end
-
-
-return {
- patterns = {
- "^!!tgservice (.*)$"
- },
- run = run
-}
diff --git a/plugins/onservice.lua b/plugins/onservice.lua
deleted file mode 100644
index 5463399..0000000
--- a/plugins/onservice.lua
+++ /dev/null
@@ -1,22 +0,0 @@
-do
--- Will leave the group if be added
-local function run(msg, matches)
-local bot_id = our_id -- your bot id
- -- like local bot_id = 1234567
- if matches[1] == 'leave' and is_admin(msg) then
- chat_del_user("chat#id"..msg.to.id, 'user#id'..bot_id, ok_cb, false)
- elseif msg.action.type == "chat_add_user" and msg.action.user.id == tonumber(bot_id) and not is_sudo(msg) then
- send_large_msg("chat#id"..msg.to.id, 'this is not one of my groups.', ok_cb, false)
- chat_del_user("chat#id"..msg.to.id, 'user#id'..bot_id, ok_cb, false)
- block_user("user#id"..msg.from.id,ok_cb,false)
- end
-end
-
-return {
- patterns = {
- "^[!/](leave)$",
- "^!!tgservice (.+)$",
- },
- run = run
-}
-end
diff --git a/plugins/owners.lua b/plugins/owners.lua
deleted file mode 100644
index af2ac57..0000000
--- a/plugins/owners.lua
+++ /dev/null
@@ -1,317 +0,0 @@
-
-
-local function lock_group_namemod(msg, data, target)
- local group_name_set = data[tostring(target)]['settings']['set_name']
- local group_name_lock = data[tostring(target)]['settings']['lock_name']
- if group_name_lock == 'yes' then
- return 'Group name is already locked'
- else
- data[tostring(target)]['settings']['lock_name'] = 'yes'
- save_data(_config.moderation.data, data)
- rename_chat('chat#id'..target, group_name_set, ok_cb, false)
- return 'Group name has been locked'
- end
-end
-
-local function unlock_group_namemod(msg, data, target)
- local group_name_set = data[tostring(target)]['settings']['set_name']
- local group_name_lock = data[tostring(target)]['settings']['lock_name']
- if group_name_lock == 'no' then
- return 'Group name is already unlocked'
- else
- data[tostring(target)]['settings']['lock_name'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group name has been unlocked'
- end
-end
-
-local function lock_group_floodmod(msg, data, target)
- local group_flood_lock = data[tostring(target)]['settings']['flood']
- if group_flood_lock == 'yes' then
- return 'Group flood is locked'
- else
- data[tostring(target)]['settings']['flood'] = 'yes'
- save_data(_config.moderation.data, data)
- return 'Group flood has been locked'
- end
-end
-
-local function unlock_group_floodmod(msg, data, target)
- local group_flood_lock = data[tostring(target)]['settings']['flood']
- if group_flood_lock == 'no' then
- return 'Group flood is not locked'
- else
- data[tostring(target)]['settings']['flood'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group flood has been unlocked'
- end
-end
-
-local function lock_group_membermod(msg, data, target)
- local group_member_lock = data[tostring(target)]['settings']['lock_member']
- if group_member_lock == 'yes' then
- return 'Group members are already locked'
- else
- data[tostring(target)]['settings']['lock_member'] = 'yes'
- save_data(_config.moderation.data, data)
- end
- return 'Group members has been locked'
-end
-
-local function unlock_group_membermod(msg, data, target)
- local group_member_lock = data[tostring(target)]['settings']['lock_member']
- if group_member_lock == 'no' then
- return 'Group members are not locked'
- else
- data[tostring(target)]['settings']['lock_member'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group members has been unlocked'
- end
-end
-
-local function unlock_group_photomod(msg, data, target)
- local group_photo_lock = data[tostring(target)]['settings']['lock_photo']
- if group_photo_lock == 'no' then
- return 'Group photo is not locked'
- else
- data[tostring(target)]['settings']['lock_photo'] = 'no'
- save_data(_config.moderation.data, data)
- return 'Group photo has been unlocked'
- end
-end
-
-local function show_group_settingsmod(msg, data, target)
- local data = load_data(_config.moderation.data)
- if data[tostring(msg.to.id)] then
- if data[tostring(msg.to.id)]['settings']['flood_msg_max'] then
- NUM_MSG_MAX = tonumber(data[tostring(msg.to.id)]['settings']['flood_msg_max'])
- print('custom'..NUM_MSG_MAX)
- else
- NUM_MSG_MAX = 5
- end
- end
- local settings = data[tostring(target)]['settings']
- local text = "Group settings:\nLock group name : "..settings.lock_name.."\nLock group photo : "..settings.lock_photo.."\nLock group member : "..settings.lock_member.."\nflood sensitivity : "..NUM_MSG_MAX
- return text
-end
-
-local function set_rules(target, rules)
- local data = load_data(_config.moderation.data)
- local data_cat = 'rules'
- data[tostring(target)][data_cat] = rules
- save_data(_config.moderation.data, data)
- return 'Set group rules to:\n'..rules
-end
-
-local function set_description(target, about)
- local data = load_data(_config.moderation.data)
- local data_cat = 'description'
- data[tostring(target)][data_cat] = about
- save_data(_config.moderation.data, data)
- return 'Set group description to:\n'..about
-end
-
-local function run(msg, matches)
- if msg.to.type ~= 'chat' then
- local chat_id = matches[1]
- local receiver = get_receiver(msg)
- local data = load_data(_config.moderation.data)
- if matches[2] == 'ban' then
- local chat_id = matches[1]
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- if tonumber(matches[3]) == tonumber(our_id) then return false end
- local user_id = matches[3]
- if tonumber(matches[3]) == tonumber(msg.from.id) then
- return "You can't ban yourself"
- end
- ban_user(matches[3], matches[1])
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] banned user ".. matches[3])
- return 'User '..user_id..' banned'
- end
- if matches[2] == 'unban' then
- if tonumber(matches[3]) == tonumber(our_id) then return false end
- local chat_id = matches[1]
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local user_id = matches[3]
- if tonumber(matches[3]) == tonumber(msg.from.id) then
- return "You can't unban yourself"
- end
- local hash = 'banned:'..matches[1]
- redis:srem(hash, user_id)
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] unbanned user ".. matches[3])
- return 'User '..user_id..' unbanned'
- end
- if matches[2] == 'kick' then
- local chat_id = matches[1]
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- if tonumber(matches[3]) == tonumber(our_id) then return false end
- local user_id = matches[3]
- if tonumber(matches[3]) == tonumber(msg.from.id) then
- return "You can't kick yourself"
- end
- kick_user(matches[3], matches[1])
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] kicked user ".. matches[3])
- return 'User '..user_id..' kicked'
- end
- if matches[2] == 'clean' then
- if matches[3] == 'modlist' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- for k,v in pairs(data[tostring(matches[1])]['moderators']) do
- data[tostring(matches[1])]['moderators'][tostring(k)] = nil
- save_data(_config.moderation.data, data)
- end
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] cleaned modlist")
- end
- if matches[3] == 'rules' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local data_cat = 'rules'
- data[tostring(matches[1])][data_cat] = nil
- save_data(_config.moderation.data, data)
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] cleaned rules")
- end
- if matches[3] == 'about' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local data_cat = 'description'
- data[tostring(matches[1])][data_cat] = nil
- save_data(_config.moderation.data, data)
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] cleaned about")
- end
- end
- if matches[2] == "setflood" then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- if tonumber(matches[3]) < 5 or tonumber(matches[3]) > 20 then
- return "Wrong number,range is [5-20]"
- end
- local flood_max = matches[3]
- data[tostring(matches[1])]['settings']['flood_msg_max'] = flood_max
- save_data(_config.moderation.data, data)
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] set flood to ["..matches[3].."]")
- return 'Group flood has been set to '..matches[3]
- end
- if matches[2] == 'lock' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local target = matches[1]
- if matches[3] == 'name' then
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] locked name ")
- return lock_group_namemod(msg, data, target)
- end
- if matches[3] == 'member' then
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] locked member ")
- return lock_group_membermod(msg, data, target)
- end
- end
- if matches[2] == 'unlock' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local target = matches[1]
- if matches[3] == 'name' then
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] unlocked name ")
- return unlock_group_namemod(msg, data, target)
- end
- if matches[3] == 'member' then
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] unlocked member ")
- return unlock_group_membermod(msg, data, target)
- end
- end
- if matches[2] == 'new' then
- if matches[3] == 'link' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local function callback (extra , success, result)
- local receiver = 'chat#'..matches[1]
- vardump(result)
- data[tostring(matches[1])]['settings']['set_link'] = result
- save_data(_config.moderation.data, data)
- return
- end
- local receiver = 'chat#'..matches[1]
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] revoked group link ")
- export_chat_link(receiver, callback, true)
- return "Created a new new link ! \n owner can get it by /owners "..matches[1].." get link"
- end
- end
- if matches[2] == 'get' then
- if matches[3] == 'link' then
- if not is_owner2(msg.from.id, chat_id) then
- return "You are not the owner of this group"
- end
- local group_link = data[tostring(matches[1])]['settings']['set_link']
- if not group_link then
- return "Create a link using /newlink first !"
- end
- local name = user_print_name(msg.from)
- savelog(matches[1], name.." ["..msg.from.id.."] requested group link ["..group_link.."]")
- return "Group link:\n"..group_link
- end
- end
- if matches[1] == 'changeabout' and matches[2] and is_owner2(msg.from.id, matches[2]) then
- local target = matches[2]
- local about = matches[3]
- local name = user_print_name(msg.from)
- savelog(matches[2], name.." ["..msg.from.id.."] has changed group description to ["..matches[3].."]")
- return set_description(target, about)
- end
- if matches[1] == 'changerules' and is_owner2(msg.from.id, matches[2]) then
- local rules = matches[3]
- local target = matches[2]
- local name = user_print_name(msg.from)
- savelog(matches[2], name.." ["..msg.from.id.."] has changed group rules to ["..matches[3].."]")
- return set_rules(target, rules)
- end
- if matches[1] == 'changename' and is_owner2(msg.from.id, matches[2]) then
- local new_name = string.gsub(matches[3], '_', ' ')
- data[tostring(matches[2])]['settings']['set_name'] = new_name
- save_data(_config.moderation.data, data)
- local group_name_set = data[tostring(matches[2])]['settings']['set_name']
- local to_rename = 'chat#id'..matches[2]
- local name = user_print_name(msg.from)
- savelog(matches[2], "Group {} name changed to [ "..new_name.." ] by "..name.." ["..msg.from.id.."]")
- rename_chat(to_rename, group_name_set, ok_cb, false)
- end
- if matches[1] == 'loggroup' and matches[2] and is_owner2(msg.from.id, matches[2]) then
- savelog(matches[2], "------")
- send_document("user#id".. msg.from.id,"./groups/logs/"..matches[2].."log.txt", ok_cb, false)
- end
- end
-end
-return {
- patterns = {
- "^[!/]owners (%d+) ([^%s]+) (.*)$",
- "^[!/]owners (%d+) ([^%s]+)$",
- "^[!/](changeabout) (%d+) (.*)$",
- "^[!/](changerules) (%d+) (.*)$",
- "^[!/](changename) (%d+) (.*)$",
- "^[!/](loggroup) (%d+)$"
- },
- run = run
-}
diff --git a/plugins/set.lua b/plugins/set.lua
deleted file mode 100644
index 5ed46ea..0000000
--- a/plugins/set.lua
+++ /dev/null
@@ -1,32 +0,0 @@
-local function save_value(msg, name, value)
- if (not name or not value) then
- return "Usage: !set var_name value"
- end
- local hash = nil
- if msg.to.type == 'chat' then
- hash = 'chat:'..msg.to.id..':variables'
- end
- if hash then
- redis:hset(hash, name, value)
- return "Saved "..name
- end
-end
-local function run(msg, matches)
- if not is_momod(msg) then
- return "For moderators only!"
- end
- local name = string.sub(matches[1], 1, 50)
- local value = string.sub(matches[2], 1, 1000)
- local name1 = user_print_name(msg.from)
- savelog(msg.to.id, name1.." ["..msg.from.id.."] saved ["..name.."] as > "..value )
- local text = save_value(msg, name, value)
- return text
-end
-
-return {
- patterns = {
- "^[!/]save ([^%s]+) (.+)$"
- },
- run = run
-}
-
diff --git a/plugins/stats.lua b/plugins/stats.lua
deleted file mode 100644
index 7583136..0000000
--- a/plugins/stats.lua
+++ /dev/null
@@ -1,150 +0,0 @@
-do
-
--- Returns a table with `name` and `msgs`
-local function get_msgs_user_chat(user_id, chat_id)
- local user_info = {}
- local uhash = 'user:'..user_id
- local user = redis:hgetall(uhash)
- local um_hash = 'msgs:'..user_id..':'..chat_id
- user_info.msgs = tonumber(redis:get(um_hash) or 0)
- user_info.name = user_print_name(user)..' ['..user_id..']'
- return user_info
-end
-
-local function chat_stats(chat_id)
- -- Users on chat
- local hash = 'chat:'..chat_id..':users'
- local users = redis:smembers(hash)
- local users_info = {}
- -- Get user info
- for i = 1, #users do
- local user_id = users[i]
- local user_info = get_msgs_user_chat(user_id, chat_id)
- table.insert(users_info, user_info)
- end
- -- Sort users by msgs number
- table.sort(users_info, function(a, b)
- if a.msgs and b.msgs then
- return a.msgs > b.msgs
- end
- end)
- local text = 'users in this chat \n'
- for k,user in pairs(users_info) do
- text = text..user.name..' = '..user.msgs..'\n'
- end
- local file = io.open("./groups/lists/"..chat_id.."stats.txt", "w")
- file:write(text)
- file:flush()
- file:close()
- send_document("chat#id"..chat_id,"./groups/lists/"..chat_id.."stats.txt", ok_cb, false)
- return --text
-end
-
-local function chat_stats2(chat_id)
- -- Users on chat
- local hash = 'chat:'..chat_id..':users'
- local users = redis:smembers(hash)
- local users_info = {}
-
- -- Get user info
- for i = 1, #users do
- local user_id = users[i]
- local user_info = get_msgs_user_chat(user_id, chat_id)
- table.insert(users_info, user_info)
- end
-
- -- Sort users by msgs number
- table.sort(users_info, function(a, b)
- if a.msgs and b.msgs then
- return a.msgs > b.msgs
- end
- end)
-
- local text = 'users in this chat \n'
- for k,user in pairs(users_info) do
- text = text..user.name..' = '..user.msgs..'\n'
- end
- return text
-end
--- Save stats, ban user
-local function bot_stats()
-
- local redis_scan = [[
- local cursor = '0'
- local count = 0
-
- repeat
- local r = redis.call("SCAN", cursor, "MATCH", KEYS[1])
- cursor = r[1]
- count = count + #r[2]
- until cursor == '0'
- return count]]
-
- -- Users
- local hash = 'msgs:*:'..our_id
- local r = redis:eval(redis_scan, 1, hash)
- local text = 'Users: '..r
-
- hash = 'chat:*:users'
- r = redis:eval(redis_scan, 1, hash)
- text = text..'\nGroups: '..r
- return text
-end
-local function run(msg, matches)
- if matches[1]:lower() == 'teleseed' then -- Put everything you like :)
- local about = _config.about_text
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] used /teleseed ")
- return about
- end
- if matches[1]:lower() == "statslist" then
- if not is_momod(msg) then
- return "For mods only !"
- end
- local chat_id = msg.to.id
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] requested group stats ")
- return chat_stats2(chat_id)
- end
- if matches[1]:lower() == "stats" then
- if not matches[2] then
- if not is_momod(msg) then
- return "For mods only !"
- end
- if msg.to.type == 'chat' then
- local chat_id = msg.to.id
- local name = user_print_name(msg.from)
- savelog(msg.to.id, name.." ["..msg.from.id.."] requested group stats ")
- return chat_stats(chat_id)
- else
- return
- end
- end
- if matches[2] == "teleseed" then -- Put everything you like :)
- if not is_admin(msg) then
- return "For admins only !"
- else
- return bot_stats()
- end
- end
- if matches[2] == "group" then
- if not is_admin(msg) then
- return "For admins only !"
- else
- return chat_stats(matches[3])
- end
- end
- end
-end
-return {
- patterns = {
- "^[!/]([Ss]tats)$",
- "^[!/]([Ss]tatslist)$",
- "^[!/]([Ss]tats) (group) (%d+)",
- "^[!/]([Ss]tats) (teleseed)",-- Put everything you like :)
- "^[!/]([Tt]eleseed)"-- Put everything you like :)
- },
- run = run
-}
-
-end