From 3a8a355838c10b738051b1705ce3cece9877f2d2 Mon Sep 17 00:00:00 2001 From: iman daneshi Date: Tue, 8 Mar 2016 01:17:23 +0330 Subject: [PATCH 01/58] Update .gitmodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index ff3ebb6..0362730 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "tg"] path = tg - url = https://github.com/SEEDTEAM/tg + url = https://github.com/Rondoozle/tg From 0cf11cd5d2bb159243460c6d8402cbf77fd10133 Mon Sep 17 00:00:00 2001 From: iman daneshi Date: Tue, 8 Mar 2016 20:52:37 +0330 Subject: [PATCH 02/58] Update admin.lua --- plugins/admin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index 355311c..b30014a 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -175,7 +175,7 @@ local function run(msg,matches) if not is_sudo(msg) then-- Sudo only return end - local url = "http://seedteam.ir/Teleseed/Global_bans.json" + 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 From f6080458c94e66811bac85fd5f4c321c32eb20e3 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 01:58:58 +0000 Subject: [PATCH 03/58] TeleSeed v4! --- README.md | 638 ++++------- bot/seedbot.lua | 245 ++++- bot/utils.lua | 521 ++++++--- plugins/admin.lua | 222 +++- plugins/all.lua | 47 +- plugins/anti_spam.lua | 89 +- plugins/arabic_lock.lua | 30 +- plugins/banhammer.lua | 228 ++-- plugins/block_user.lua | 18 + plugins/broadcast.lua | 15 +- plugins/download_media.lua | 33 - plugins/get.lua | 6 +- plugins/ingroup.lua | 875 ++++++++++++---- plugins/inpm.lua | 314 ++++-- plugins/inrealm.lua | 1081 +++++++++++++------ plugins/invite.lua | 45 +- plugins/leave_ban.lua | 30 +- plugins/msg_checks.lua | 283 +++++ plugins/onservice.lua | 17 +- plugins/owners.lua | 416 +++++++- plugins/set.lua | 4 +- plugins/stats.lua | 43 +- plugins/supergroup.lua | 2035 ++++++++++++++++++++++++++++++++++++ plugins/whitelist.lua | 81 ++ 24 files changed, 5734 insertions(+), 1582 deletions(-) create mode 100644 plugins/block_user.lua delete mode 100644 plugins/download_media.lua create mode 100644 plugins/msg_checks.lua create mode 100644 plugins/supergroup.lua create mode 100644 plugins/whitelist.lua diff --git a/README.md b/README.md index b8945da..411fb56 100644 --- a/README.md +++ b/README.md @@ -10,425 +10,218 @@ * **Recalcitrant to any kind of spamming (X/Y bots, name/photo changers, etc.)** * **Global banning** * **Broadcast to all groups** -* **Group links** +* **Group and 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** +* **Only mods, owner and admin can add bots in groups** * **Arabic lock** +* **Chat list * **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 "!"** + +* * * + +##Commands +TeleSeed has several commands that are only usable at certain ranks. + + +## General Commands {#general_commands} +| Command | Description | +|:--------|:------------| +| [#!/]id | Returns group/SuperGroup ID or user id in pm. | +| [#!/]teleseed | Returns bot information. | + + +## Private Message Commands {#privmsg_commands} +| Command | Description | +|:--------|:------------| +| [#!/]help | Returns help text. | +| [#!/]superhelp | Returns SuperGroup help text. | +| [#!/]Chats | Returns public chats in a message(s). | +| [#!/]Chatlist | Returns public chats in a .txt document. | +| [#!/]join [GroupID] | Join a public chat by id | + + +#Moderator commands {#moderator_commands} + +| Command | Description | Groups? | SuperGroups? | +|:--------|:------------|:--------|:-------------| +| [#!/]info | Returns general info about the SuperGroup. | N | Y | +| [#!/]admins | Returns SuperGroup admins list. | N | Y | +| [#!/]modlist | Returns Moderator list. | Y | Y | +| [#!/]owner | Returns group/SuperGroup owner. _Can be used by any user_| Y | Y | +| [#!/]bots | Lists bots in SuperGroup. | N | Y | +| [#!/]who | Lists all users in group *SuperGroup returns .txt document list. | Y | Y | +| [#!/]wholist | Lists all users in group in .txt document. | Y | N | +| [#!/]block | Kicks a user from SuperGroup **Adds user to blocked list**. | N | Y | +| [#!/]kick | kicks user from group. | Y | N | +| [#!/]ban | Bans user from the group/SuperGroup. | Y | Y | +| [#!/]unban | Unbans user from group/SuperGroup. | Y | Y | +| [#!/]id [username|reply] | For userID's: !id @username (**ONLY IN SuperSroups**) or reply `!id` in any group. | Y | Y | +| [#!/]id from | Returns ID of user a message is forwarded from. | N | Y | +| [#!/]kickme | Kicks user from SuperGroup \nIn SuperGroup: **Must be unblocked by owner or use `#join` by pm to return** | Y | Y | +| [#!/]setowner | Sets group/SuperGroup owner. | Y | Y | +| [#!/]promote | Promote a group/SuperGroup moderator. | Y | Y | +| [#!/]demote | Demote a group/SuperGroup moderator. | Y | Y | +| [#!/]setname | Set group/SuperGroup name. | Y | Y | +| [#!/]setphoto | Set group/SuperGroup photo. | Y | Y | +| [#!/]setrules | Set group/SuperGroup rules. | Y | Y | +| [#!/]setabout | Sets the about section in chat info(members list) | N | Y | +| [#!/]set about | | Y | N | +| [#!/]save [value] | Sets extra info for group/SuperGroup by value. | Y | Y | +| [#!/]get [value] | Returns extra info for group/SuperGroup by value. | Y | Y | +| [#!/]newlink | Generate a new group/SuperGroup link. | Y | Y | +| [#!/]setlink | Set a new SuperGroup link _If bot is not creator_. | N | Y | +| [#!/]link | Retrieves the group/SuperGroup link. | Y | Y | +| [#!/]rules | Retrieves the group/SuperGroup rules. | Y | Y | +| [#!/]lock [setting](#settings) | Lock group/SuperGroup settings. | Y | Y | +| [#!/]unlock [setting](#settings) | Unlock group/SuperGroup. | Y | Y | +| [#!/]mute [mute](#mutes) | mute group message types. | Y | Y | +| [#!/]unmute [mute](#mutes) | unmute group message types. | Y | Y | +| [#!/]setflood [value](#settings) | Set [value] as flood sensitivity.| Y | Y | +| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat.\n_If a muted user posts a message, the message is deleted automaically_\n_only owners can mute | mods and owners can unmute_ | Y | Y | +| [#!/]mutelist | Returns list of muted users in group/SuperGroup. | Y | Y | +| [#!/]muteslist | Returns mutes for group/SuperGroup. | Y | Y | +| [#!/]settings | Returns a list of group/SuperGroup settings. | Y | Y | +| [#!/]stats | Returns simple message statistics in a .txt document. | Y | Y | +| [#!/]statslist | Returns simple message statistics in a message. | Y | Y | +| [#!/]banlist | Returns group/SuperGroup banlist. | Y | Y | +| [#!/]clean [rules|about|modlist|mutelist] | Clears rules, about, modlist, or mutelist | Y | Y | +| [#!/]del | Deletes a message by reply. | N | Y | +| [#!/]res [username] | Returns users name and id by username. | Y | Y | +| [#!/]log | Returns group logs.\n_In SuperGroups:_Search for kick reasons using [#RTL|#spam|#lockmember] | Y | Y | + +##Owner commands {#moderator_commands} + +| Command | Description | In group/SuperGroup? | In private? | +|:--------|:------------|:----------------------|:-------------| +| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat.\n_If a muted user posts a message, the message is deleted automaically_\n_only owners can mute | mods and owners can unmute_ | | N | +| [#!/]all | Returns all available information about current group. | Y | N | +| [#!/]all [GroupID] | Returns all available information about group by GroupID. | Y | N | +| [#!/]owners [GroupID] [kick|ban|unban] [UserID] | Kick, ban, or unban a user from a group by GroupID and UserID. | N | Y | +| [#!/]owners [GroupID] clean [modlist|rules|about] | Clear options by GroupID. | N | Y | +| [#!/]owners [GroupID] setflood [value] | Set flood for a group by GroupID and a value [1-5]. | N | Y | +| [#!/]owners [GroupID] lock [setting] | Lock settings for a group by GroupID. | N | Y | +| [#!/]owner [GroupID] unlock [setting] | Unlock settings for a group by GroupID. | N | Y | +| [#!/]owners [GroupID] new link | Create a new group link by GroupID. | N | Y | +| [#!/]owners [GroupID] get link | Returns group link by GroupID. | N | Y | +| [#!/]changename [GroupID] [name] | Change a group's name by GroupID. | N | Y | +| [#!/]changrules [GroupID] [rules] | Change a group's rules by GroupID. | N | Y | +| [#!/]changeabout [GroupID] [about] | Change a group's about by GroupID. | N | Y | +| [#!/]loggroup [GroupID] | get group logs by GroupID. | N | Y | + +##Admin commands + +| Command | Description | Groups? | SuperGroups? | Realms? | +|:--------|:------------|:--------|:-------------|:--------| +| [#!/]creategroup [Name] | Create a group and add it to moderation.json. | Y | Y | Y | +| [#!/]createrealm [Name] | Create a realm and remove it from moderation.json. | Y | Y | Y | +| [#!/]add | Add a group to moderation.json. | Y | Y | Y | +| [#!/]rem | Remove a group from moderation.json. | Y | Y | Y | +| [#!/]rem [GroupID] | Remove a group from moderation by GroupID. | Y | Y | Y | +| [#!/]setname [Name] | Set realm name. | N | -- | Y | +| [#!/]setabout [group|sgroup] [GroupID] [Text] | Set a group's about text. | Y | Y | Y | +| [#!/]setrules [group|sgroup] [GroupID] [Text] | Set a group's rules. | Y | Y | Y | +| [#!/]lock [GroupID] [setting] | Lock a group's setting. | Y | Y | Y | +| [#!/]lock [GroupID] [setting] | Lock a group's setting. | Y | Y | Y | +| [#!/]unlock [GroupID] [setting] | Unlock a group's setting. | Y | Y | Y | +| [#!/]who | Get a list of members in group/realm. | Y | Y | Y | +| [#!/]wholist | Get a .txt document list of members in group/realm. | Y | Y | Y | +| [#!/]type | Get group type. | Y | Y | Y | +| [#!/]addlog | Add a Log_SuperGroup for GBan log. | N | Y | N | +| [#!/]remlog | Remove a Log_SuperGroup for GBan log. | N | Y | N | +| [#!/]kill chat [GroupID] | Kick all users and remove a group from moderation. | Y | Y | Y | +| [#!/]kill realm [RealmID] | Kick all users and remove a realm from moderation. | Y | Y | Y | +| [#!/]banall [id|usename] | Ban a user from all moderated groups where bot is an admin (#global_ban) | Y | Y | Y | +| [#!/]unbanall [id|usename] | Unban a user from all moderated groups where bot is an admin (#global_ban) | Y | Y | Y | +| [#!/]gbanlist [id|usename] | Returns a list of all globally banned user | Y | Y | Y | +| [#!/]list groups | Returns a list of all groups. | Y | Y | Y | +| [#!/]list realms | Returns a list of all realms. | Y | Y | Y | +| [#!/]whitelist | User/Bot will not be subject to message checks. | Y | Y | Y | +| [#!/]support | Promote user to support. | Y | Y | Y | +| [#!/]-support | deomote user from support. | Y | Y | Y | +| [#!/]pm [UserID] | Sends a private message to a user by UserID. | Y | Y | Y | +| [#!/]import | Bot joins a group by GroupLink. | Y | Y | Y | +| [#!/]pmblock [UserID] | Block a user from bot private message and bot photo. | Y | Y | Y | +| [#!/]pmunblock [UserID] | Unblock a user from bot private message and bot photo. | Y | Y | Y | +| [#!/]markread [on|off] | Toggle bot to doubble check or not doubble check messages. | Y | Y | Y | +| [#!/]setbotphoto | Set bot photo. | Y | Y | Y | +| [#!/]contactlist | Bot will generate a list of all it's contacts\nand send it by private message of command sender | Y | Y | Y | +| [#!/]dialoglist | Bot will generate a list of all it's private message users\nand send it by private message of command sender | Y | Y | Y | +| [#!/]delcontact | Delete bot contact. | Y | Y | Y | +| [#!/]reload | Reloads all bot plugins | Y | Y | Y | +| [#!/]updateid | Adds long_id to moderation data for groups. | Y | Y | Y | +| [#!/]!bc [group_id] [text] | This command will send text to [group_id]| Y | Y | Y | +| [#!/]leave | Bot will leave that group and can only be re-invited by an admin with bot phone number | Y | Y | Y | + + +## Sudo Commands {#sudo_commands} + +| Command | Groups? | SuperGroups? | Realms? | +|:--------|:--------|:-------------|---------| +| [#!/]addadmin [id|username] | Set a user as bot admin. | Y | Y | Y | +| [#!/]removeadmin [id|username] | Remove a user from bot admin. | Y | Y | Y | +| [#!/]sync_gbans | Sync your GBans with official @TeleSeed | Y | Y | Y | + + +## Settings {#settings} + +| Command | Groups? | SuperGroups? | +|:--------|:--------|:-------------| +| [#!/](un)lock links | Y | Y | +| [#!/](un)lock flood | Y | Y | +| [#!/]setflood [5-20] | Y | Y | +| [#!/](un)lock bots | Y | N | +| [#!/](un)lock spam | Y | Y | +| [#!/](un)lock arabic | Y | Y | +| [#!/](un)lock member | Y | Y | +| [#!/](un)lock leave | Y | N | +| [#!/](un)lock RTL | Y | Y | +| [#!/](un)lock sticker | Y| Y | +| [#!/]public [yes|no] | Y | Y | +| [#!/](un)lock strict | N | Y | + +/lock [setting] and /unlock [setting]: sets allowed actions and content for groups/SuperGroups + ***/lock strict*** in a supergroup, if strict is locked users will be kicked for violations of settings or mutes + +/public [yes|no]: Set group/SuperGroup visibility in pm `!chats` or `!chatlist` commands. + + +### Mutes {#mutes} + +| Command | +|:--------| +| [#!/]mute audio | +| [#!/]mute video | +| [#!/]mute photo | +| [#!/]mute documents | +| [#!/]mute gifs | +| [#!/]mute all | + +**Groups: _If "muted" message type: user is kicked if message type is posted_** + +**SuperGroups: _A "muted" message type is auto-deleted if posted_ ** + +### Ranks {#ranks} + +| Rank | Description | +|:------|:------------| +| Banned | Cannot enter the group(s). | +| User | Default rank. | +| Moderator | Can set settings and kick/ban/unban users from a group. Can unmute users. | +| Owner | Can mute users. Can promote/demote moderators. Can set SuperGroup admins. | +| Support | Can globally unban users. Acts as owner of all groups. | +| Administrator | Can globally ban/unban users. Can promote/demote owners. | +| Sudo | Can add[#!/]remove groups. Can broadcast. Can promote/demote administrators. | + +Each higher status inherits the privileges of the lower status. + +**You can use "#", "!", or "/" to begin all commands + +* * * # Installation @@ -439,7 +232,7 @@ sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-d # Let's install the bot. cd $HOME -git clone https://github.com/SEEDTEAM/TeleSeed.git +git clone https://github.com/SEEDTEAM/TeleSeed.git -b test cd TeleSeed chmod +x launch.sh ./launch.sh install @@ -449,8 +242,11 @@ chmod +x launch.sh 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 +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 -b test && 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. @@ -469,12 +265,24 @@ Then restart the bot. Create a realm using the `!createrealm` command. +* * * + +**Creating a LOG SuperGroup** + -For GBan Log + + 1. Create a group using the `!creategroup` command. + 2. Add two members or bots, then use `#Tosuper` to convert to a SuperSroup. + 3. Use the `#addlog` command and your ***LOG SuperGroup(s)*** will be set. + Note: you can set multiple Log SuperGroups + +* * * + # 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) +Join our bot development group by sending `/join 1047524697` to [@TeleSeed](https://telegram.me/TeleSeed) # Special thanks to [@seyedan25](https://telegram.me/seyedan25) @@ -489,6 +297,8 @@ For graphic designs. [Juan Potato](https://github.com/JuanPotato) +* * * + # Our team! [Alphonse](https://github.com/hmon) ([Telegram](https://telegram.me/iwals)) diff --git a/bot/seedbot.lua b/bot/seedbot.lua index 8dc5ac4..bd6c2b2 100644 --- a/bot/seedbot.lua +++ b/bot/seedbot.lua @@ -4,7 +4,9 @@ package.cpath = package.cpath .. ';.luarocks/lib/lua/5.2/?.so' require("./bot/utils") -VERSION = '2' +local f = assert(io.popen('/usr/bin/git describe --tags', 'r')) +VERSION = assert(f:read('*a')) +f:close() -- This function is called when tg receive a msg function on_msg_receive (msg) @@ -12,30 +14,29 @@ function on_msg_receive (msg) return end - local receiver = get_receiver(msg) - print (receiver) + msg = backward_msg_format(msg) + 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 + -- mark_read(receiver, ok_cb, false) end end end function ok_cb(extra, success, result) + end function on_binlog_replay_end() started = true postpone (cron_plugins, false, 60*5.0) + -- See plugins/isup.lua as an example for cron _config = load_config() @@ -52,7 +53,7 @@ function msg_valid(msg) end -- Before bot was started - if msg.date < now then + if msg.date < os.time() - 5 then print('\27[36mNot valid: old msg\27[39m') return false end @@ -83,9 +84,8 @@ function msg_valid(msg) 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) + --send_large_msg(*group id*, msg.text) *login code will be sent to GroupID* + return false end return true @@ -117,7 +117,6 @@ function pre_process_msg(msg) msg = plugin.pre_process(msg) end end - return msg end @@ -198,7 +197,7 @@ function load_config( ) end local config = loadfile ("./data/config.lua")() for v,user in pairs(config.sudo_users) do - print("Allowed user: " .. user) + print("Sudo user: " .. user) end return config end @@ -208,6 +207,7 @@ function create_config( ) -- A simple config with basic plugins and ourselves as privileged user config = { enabled_plugins = { + "admin", "onservice", "inrealm", "ingroup", @@ -220,25 +220,27 @@ function create_config( ) "set", "get", "broadcast", - "download_media", "invite", "all", "leave_ban", - "admin" + "block_user", + "supergroup", + "whitelist", + "msg_checks" }, - sudo_users = {110626080,103649648,143723991,111020322,0,tonumber(our_id)},--Sudo users - disabled_channels = {}, + sudo_users = {110626080,103649648,111020322,0,tonumber(our_id)},--Sudo users moderation = {data = 'data/moderation.json'}, - about_text = [[Teleseed v2 - Open Source -An advance Administration bot based on yagop/telegram-bot + about_text = [[Teleseed v4 +An advanced administration bot based on TG-CLI written in Lua https://github.com/SEEDTEAM/TeleSeed Admins -@iwals [Founder] +@Empero [Founder] @imandaneshi [Developer] -@Rondoozle [Developer] +@POTUS [Developer] @seyedan25 [Manager] +@aRandomStranger [Admin] Special thanks to awkward_potato @@ -262,7 +264,7 @@ Create a realm !setname [Name] Set realm name -!setabout [GroupID] [Text] +!setabout [group|sgroup] [GroupID] [Text] Set a group's about text !setrules [GroupID] [Text] @@ -274,6 +276,9 @@ Lock a group's setting !unlock [GroupID] [setting] Unock a group's setting +!settings [group|sgroup] [GroupID] +Set settings for GroupID + !wholist Get a list of members in group/realm @@ -301,8 +306,14 @@ Get a list of all groups !list realms Get a list of all realms +!support +Promote user to support + +!-support +Demote user from support + !log -Grt a logfile of current group or realm +Get a logfile of current group or realm !broadcast [text] !broadcast Hello ! @@ -314,7 +325,7 @@ Only sudo users can run this command This command will send text to [group_id] -**U can use both "/" and "!" +**You can use "#", "!", or "/" to begin all commands *Only admins and sudo can add bots in group @@ -367,12 +378,23 @@ Group rules return group id or user id !help +Returns help text + +!lock [links|flood|spam|Arabic|member|rtl|sticker|contacts|strict] +Lock group settings +*rtl: Kick user if Right To Left Char. is in name* -!lock [member|name|bots|leave] -Locks [member|name|bots|leaveing] +!unlock [links|flood|spam|Arabic|member|rtl|sticker|contacts|strict] +Unlock group settings +*rtl: Kick user if Right To Left Char. is in name* -!unlock [member|name|bots|leave] -Unlocks [member|name|bots|leaving] +!mute [all|audio|gifs|photo|video] +mute group message types +*If "muted" message type: user is kicked if message type is posted + +!unmute [all|audio|gifs|photo|video] +Unmute group message types +*If "unmuted" message type: user is not kicked if message type is posted !set rules Set as rules @@ -383,6 +405,17 @@ Set as about !settings Returns group settings +!muteslist +Returns mutes for chat + +!muteuser [username] +Mute a user in chat +*user is kicked if they talk +*only owners can mute | mods and owners can unmute + +!mutelist +Returns list of muted users in chat + !newlink create/revoke your group link @@ -415,12 +448,12 @@ returns user id "!res @username" !log -will return group logs +Returns group logs !banlist will return group ban list -**U can use both "/" and "!" +**You can use "#", "!", or "/" to begin all commands *Only owner and mods can add bots in group @@ -430,7 +463,149 @@ will return group ban list *Only owner can use res,setowner,promote,demote and log commands -]] +]], + help_text_super =[[ +SuperGroup Commands: + +!info +Displays general info about the SuperGroup + +!admins +Returns SuperGroup admins list + +!owner +Returns group owner + +!modlist +Returns Moderators list + +!bots +Lists bots in SuperGroup + +!who +Lists all users in SuperGroup + +!block +Kicks a user from SuperGroup +*Adds user to blocked list* + +!ban +Bans user from the SuperGroup + +!unban +Unbans user from the SuperGroup + +!id +Return SuperGroup ID or user id +*For userID's: !id @username or reply !id* + +!id from +Get ID of user message is forwarded from + +!kickme +Kicks user from SuperGroup +*Must be unblocked by owner or use join by pm to return* + +!setowner +Sets the SuperGroup owner + +!promote [username|id] +Promote a SuperGroup moderator + +!demote [username|id] +Demote a SuperGroup moderator + +!setname +Sets the chat name + +!setphoto +Sets the chat photo + +!setrules +Sets the chat rules + +!setabout +Sets the about section in chat info(members list) + +!save [value] +Sets extra info for chat + +!get [value] +Retrieves extra info for chat by value + +!newlink +Generates a new group link + +!link +Retireives the group link + +!rules +Retrieves the chat rules + +!lock [links|flood|spam|Arabic|member|rtl|sticker|contacts|strict] +Lock group settings +*rtl: Delete msg if Right To Left Char. is in name* +*strict: enable strict settings enforcement (violating user will be kicked)* + +!unlock [links|flood|spam|Arabic|member|rtl|sticker|contacts|strict] +Unlock group settings +*rtl: Delete msg if Right To Left Char. is in name* +*strict: disable strict settings enforcement (violating user will not be kicked)* + +!mute [all|audio|gifs|photo|video|service] +mute group message types +*A "muted" message type is auto-deleted if posted + +!unmute [all|audio|gifs|photo|video|service] +Unmute group message types +*A "unmuted" message type is not auto-deleted if posted + +!setflood [value] +Set [value] as flood sensitivity + +!settings +Returns chat settings + +!muteslist +Returns mutes for chat + +!muteuser [username] +Mute a user in chat +*If a muted user posts a message, the message is deleted automaically +*only owners can mute | mods and owners can unmute + +!mutelist +Returns list of muted users in chat + +!banlist +Returns SuperGroup ban list + +!clean [rules|about|modlist|mutelist] + +!del +Deletes a message by reply + +!public [yes|no] +Set chat visibility in pm !chats or !chatlist commands + +!res [username] +Returns users name and id by username + + +!log +Returns group logs +*Search for kick reasons using [#RTL|#spam|#lockmember] + +**You can use "#", "!", or "/" to begin all commands + +*Only owner can add members to SuperGroup +(use invite link to invite) + +*Only moderators and owner can use block, ban, unban, newlink, link, setphoto, setname, lock, unlock, setrules, setabout 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') @@ -445,7 +620,7 @@ function on_user_update (user, what) end function on_chat_update (chat, what) - + --vardump (chat) end function on_secret_chat_update (schat, what) @@ -467,14 +642,13 @@ function load_plugins() if not ok then print('\27[31mError loading plugin '..v..'\27[39m') - print(tostring(io.popen("lua plugins/"..v..".lua"):read('*all'))) + 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) @@ -499,6 +673,7 @@ function save_data(filename, data) end + -- Call and postpone execution for cron plugins function cron_plugins() diff --git a/bot/utils.lua b/bot/utils.lua index 2c2498e..4c5866a 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -12,7 +12,6 @@ JSON = (loadfile "./libs/dkjson.lua")() http.TIMEOUT = 10 - function get_receiver(msg) if msg.to.type == 'user' then return 'user#id'..msg.from.id @@ -23,6 +22,9 @@ function get_receiver(msg) if msg.to.type == 'encr_chat' then return msg.to.print_name end + if msg.to.type == 'channel' then + return 'channel#id'..msg.to.id + end end function is_chat_msg( msg ) @@ -41,6 +43,15 @@ function string.random(length) return str; 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) @@ -457,7 +468,6 @@ end -- 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) @@ -479,6 +489,38 @@ function send_large_msg_callback(cb_extra, success, result) end end +function post_large_msg(destination, text) + local cb_extra = { + destination = destination, + text = text + } + post_large_msg_callback(cb_extra, true) +end + +function post_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 + post_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 + } + + post_msg(destination, my_text, post_large_msg_callback, cb_extra) + end +end + -- Returns a table with matches or nil function match_pattern(pattern, text, lower_case) if text then @@ -506,19 +548,19 @@ function load_from_file(file, default_data) print ('Created file', file) else print ('Data loaded from file', file) - f:close() + f:close() end return loadfile (file)() end -- See http://stackoverflow.com/a/14899740 function unescape_html(str) - local map = { - ["lt"] = "<", + local map = { + ["lt"] = "<", ["gt"] = ">", ["amp"] = "&", ["quot"] = '"', - ["apos"] = "'" + ["apos"] = "'" } new = string.gsub(str, '(&(#?x?)([%d%a]+);)', function(orig, n, s) var = map[s] or n == "#" and string.char(s) @@ -529,6 +571,39 @@ function unescape_html(str) return new end +-- Workarrond to format the message as previously was received +function backward_msg_format (msg) + for k,name in pairs({'from', 'to'}) do + local longid = msg[name].id + msg[name].id = msg[name].peer_id + msg[name].peer_id = longid + msg[name].type = msg[name].peer_type + end + if msg.action and (msg.action.user or msg.action.link_issuer) then + local user = msg.action.user or msg.action.link_issuer + local longid = user.id + user.id = user.peer_id + user.peer_id = longid + user.type = user.peer_type + end + return msg +end + +--Table Sort +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 +--End Table Sort --Check if this chat is realm or not @@ -538,26 +613,57 @@ function is_realm(msg) 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 + if data[tostring(realms)][tostring(chat)] 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 data = load_data(_config.moderation.data) local groups = 'groups' + local chat = msg.to.id + if data[tostring(groups)] then + if data[tostring(groups)][tostring(chat)] then + if msg.to.type == 'chat' then + var = true + end + end + return var + end +end + +function is_super_group(msg) + local var = false local data = load_data(_config.moderation.data) + local groups = 'groups' local chat = msg.to.id if data[tostring(groups)] then - if data[tostring(groups)][tostring(msg.to.id)] then + if data[tostring(groups)][tostring(chat)] then + if msg.to.type == 'channel' then var = true - end + end return var + end end end +function is_log_group(msg) + local var = false + local data = load_data(_config.moderation.data) + local GBan_log = 'GBan_log' + if data[tostring(GBan_log)] then + if data[tostring(GBan_log)][tostring(msg.to.id)] then + if msg.to.type == 'channel' then + var = true + end + return var + end + end +end function savelog(group, logtxt) @@ -589,7 +695,6 @@ 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 @@ -597,12 +702,19 @@ function is_owner(msg) end end end + + local hash = 'support' + local support = redis:sismember(hash, user) + if support then + var = true + 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 @@ -614,7 +726,7 @@ end function is_owner2(user_id, group_id) local var = false local data = load_data(_config.moderation.data) - + local user = user_id 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 @@ -623,11 +735,18 @@ function is_owner2(user_id, group_id) end end + local hash = 'support' + local support = redis:sismember(hash, user) + if support then + var = true + 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 @@ -637,7 +756,7 @@ function is_owner2(user_id, group_id) end --Check if user is admin or not -function is_admin(msg) +function is_admin1(msg) local var = false local data = load_data(_config.moderation.data) local user = msg.from.id @@ -673,8 +792,6 @@ function is_admin2(user_id) return var end - - --Check if user is the mod of that group or not function is_momod(msg) local var = false @@ -695,12 +812,19 @@ function is_momod(msg) end end end + + local hash = 'support' + local support = redis:sismember(hash, user) + if support then + var = true + 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 @@ -729,11 +853,18 @@ function is_momod2(user_id, group_id) end end + local hash = 'support' + local support = redis:sismember(hash, user_id) + if support then + var = true + 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 @@ -743,16 +874,27 @@ function is_momod2(user_id, group_id) end -- Returns the name of the sender -function kick_user(user_id, chat_id) +function kick_user_any(user_id, chat_id) + local channel = 'channel#id'..chat_id + local chat = 'chat#id'..chat_id + local user = 'user#id'..user_id + chat_del_user(chat, user, ok_cb, true) + channel_kick(channel, user, ok_cb, false) +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 + if is_admin2(user_id) then -- Ignore admins return end + local channel = 'channel#id'..chat_id local chat = 'chat#id'..chat_id local user = 'user#id'..user_id - chat_del_user(chat, user, ok_cb, true) + chat_del_user(chat, user, ok_cb, false) + channel_kick(channel, user, ok_cb, false) end -- Ban @@ -769,8 +911,9 @@ function ban_user(user_id, chat_id) -- Kick from chat kick_user(user_id, chat_id) end + -- Global ban -function banall_user(user_id) +function banall_user(user_id) if tonumber(user_id) == tonumber(our_id) then -- Ignore bot return end @@ -781,16 +924,17 @@ function banall_user(user_id) local hash = 'gbanned' redis:sadd(hash, user_id) end + -- Global unban function unbanall_user(user_id) - --Save on redis + --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 + --Save on redis local hash = 'banned:'..chat_id local banned = redis:sismember(hash, user_id) return banned or false @@ -806,153 +950,280 @@ 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" + 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) + if user_info and user_info.print_name then + local print_name = string.gsub(user_info.print_name, "_", " ") + local print_name = string.gsub(print_name, "‮", "") + text = text..k.." - "..print_name.." ["..v.."]\n" + else + text = text..k.." - "..v.."\n" end end - return text + 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" +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) + if user_info and user_info.print_name then + local print_name = string.gsub(user_info.print_name, "_", " ") + local print_name = string.gsub(print_name, "‮", "") + text = text..k.." - "..print_name.." ["..v.."]\n" + else + text = text..k.." - "..v.."\n" end end - return text + return text +end + +-- Support Team +function support_add(support_id) + -- Save to redis + local hash = 'support' + redis:sadd(hash, support_id) +end + +function is_support(support_id) + --Save on redis + local hash = 'support' + local support = redis:sismember(hash, support_id) + return support or false +end + +function support_remove(support_id) + --Save on redis + local hash = 'support' + redis:srem(hash, support_id) +end + +-- Whitelist +function is_whitelisted(user_id) + --Save on redis + local hash = 'whitelist' + local is_whitelisted = redis:sismember(hash, user_id) + return is_whitelisted or false +end + +--Begin Chat Mutes +function set_mutes(chat_id) + mutes = {[1]= "Audio: no",[2]= "Photo: no",[3]= "All: no",[4]="Documents: no",[5]="Text: no",[6]= "Video: no",[7]= "Gifs: no"} + local hash = 'mute:'..chat_id + for k,v in pairsByKeys(mutes) do + setting = v + redis:sadd(hash, setting) + end +end + +function has_mutes(chat_id) + mutes = {[1]= "Audio: no",[2]= "Photo: no",[3]= "All: no",[4]="Documents: no",[5]="Text: no",[6]= "Video: no",[7]= "Gifs: no"} + local hash = 'mute:'..chat_id + for k,v in pairsByKeys(mutes) do + local has_mutes = redis:sismember(hash, mutes) + return has_mutes or false + end +end + +function rem_mutes(chat_id) + local hash = 'mute:'..chat_id + redis:del(hash) +end + +function mute(chat_id, msg_type) + local hash = 'mute:'..chat_id + local yes = "yes" + local no = 'no' + local old_setting = msg_type..': '..no + local setting = msg_type..': '..yes + redis:srem(hash, old_setting) + redis:sadd(hash, setting) +end + +function is_muted(chat_id, msg_type) + local hash = 'mute:'..chat_id + local setting = msg_type + local muted = redis:sismember(hash, setting) + return muted or false +end + +function unmute(chat_id, msg_type) + --Save on redis + local hash = 'mute:'..chat_id + local yes = 'yes' + local no = 'no' + local old_setting = msg_type..': '..yes + local setting = msg_type..': '..no + redis:srem(hash, old_setting) + redis:sadd(hash, setting) +end + +function mute_user(chat_id, user_id) + local hash = 'mute_user:'..chat_id + redis:sadd(hash, user_id) +end + +function is_muted_user(chat_id, user_id) + local hash = 'mute_user:'..chat_id + local muted = redis:sismember(hash, user_id) + return muted or false +end + +function unmute_user(chat_id, user_id) + --Save on redis + local hash = 'mute_user:'..chat_id + redis:srem(hash, user_id) +end + +-- Returns chat_id mute list +function mutes_list(chat_id) + local hash = 'mute:'..chat_id + local list = redis:smembers(hash) + local text = "Mutes for: [ID: "..chat_id.." ]:\n\n" + for k,v in pairsByKeys(list) do + text = text.."Mute "..v.."\n" + end + return text +end + +-- Returns chat_user mute list +function muted_user_list(chat_id) + local hash = 'mute_user:'..chat_id + local list = redis:smembers(hash) + local text = "Muted Users for: [ID: "..chat_id.." ]:\n\n" + for k,v in pairsByKeys(list) do + local user_info = redis:hgetall('user:'..v) + if user_info and user_info.print_name then + local print_name = string.gsub(user_info.print_name, "_", " ") + local print_name = string.gsub(print_name, "‮", "") + text = text..k.." - "..print_name.." ["..v.."]\n" + else + text = text..k.." - [ "..v.." ]\n" + end + return text end +--End Chat Mutes + -- /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) + local chat = 'chat#id'..result.to.peer_id + send_large_msg(chat, result.from.peer_id) else - return 'Use This in Your Groups' + return 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" + if result.to.type == 'chat' or result.to.type == 'channel' then + local chat = 'chat#id'..result.to.peer_id + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + return end - if is_momod2(result.from.id, result.to.id) then -- Ignore mods,owner,admin - return "you can't kick mods,owner and admins" + if is_momod2(result.from.peer_id, result.to.peer_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' + chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) + channel_kick(channel, 'user#id'..result.from.peer_id, ok_cb, false) + else + return 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" + if result.to.type == 'chat' or result.to.type == 'channel' then + local chat = 'chat#id'..result.to.peer_id + local channel = 'channel#id'..result.to.peer_id + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + return end - if is_admin2(result.from.id) then -- Ignore admins - return + if is_admin2(result.from.peer_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 + chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) + channel_kick(channel, 'user#id'..result.from.peer_id, ok_cb, false) + else + return + 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 + if result.to.type == 'chat' or result.to.type == 'channel' then + local chat = 'chat#id'..result.to.peer_id + local channel = 'channel#id'..result.to.peer_id + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + return + end + if is_momod2(result.from.peer_id, result.to.peer_id) then -- Ignore mods,owner,admin + return "you can't kick mods,owner and admins" + end + ban_user(result.from.peer_id, result.to.peer_id) + send_large_msg(chat, "User "..result.from.peer_id.." Banned") + else + return + 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 + if result.to.peer_type == 'chat' or result.to.peer_type == 'channel' then + local chat = 'chat#id'..result.to.peer_id + local channel = 'channel#id'..result.to.peer_id + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + return + end + if is_admin2(result.from.peer_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 + ban_user(result.from.peer_id, result.to.peer_id) + send_large_msg(chat, "User "..result.from.peer_id.." Banned") + send_large_msg(channel, "User "..result.from.peer_id.." Banned") + else + return + 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") +function unban_by_reply(extra, success, result) + if result.to.type == 'chat' or result.to.type == 'channel' then + local chat = 'chat#id'..result.to.peer_id + local channel = 'channel#id'..result.to.peer_id + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + return + end + send_large_msg(chat, "User "..result.from.peer_id.." Unbanned") -- Save on redis - local hash = 'banned:'..result.to.id - redis:srem(hash, result.from.id) - else - return 'Use This in Your Groups' + local hash = 'banned:'..result.to.peer_id + redis:srem(hash, result.from.peer_id) + else + return 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' + if result.to.type == 'chat' or result.to.type == 'channel' then + local chat = 'chat#id'..result.to.peer_id + local channel = 'channel#id'..result.to.peer_id + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + return + end + if is_admin2(result.from.peer_id) then -- Ignore admins + return + end + local name = user_print_name(result.from) + banall_user(result.from.peer_id) + chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) + send_large_msg(chat, "User "..name.."["..result.from.peer_id.."] globally banned") + else + return end end diff --git a/plugins/admin.lua b/plugins/admin.lua index 355311c..c9b721c 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -1,3 +1,53 @@ +--check member add log SuperGroup +local function check_member_logadd(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) do + local member_id = v.peer_id + if member_id == our_id then + local GBan_log = 'GBan_log' + if not data[tostring(GBan_log)] then + data[tostring(GBan_log)] = {} + save_data(_config.moderation.data, data) + end + data[tostring(GBan_log)][tostring(msg.to.id)] = msg.to.peer_id + save_data(_config.moderation.data, data) + local text = 'Log_SuperGroup has has been set!' + reply_msg(msg.id,text,ok_cb,false) + return + else + reply_msg(msg.id,"Failed to set log SuperGroup",ok_cb, false) + return + end + end +end + +--Check Members rem log SuperGroup +local function check_member_logrem(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) do + local member_id = v.peer_id + if member_id == our_id then + local GBan_log = 'GBan_log' + if not data[tostring(GBan_log)] then + data[tostring(GBan_log)] = nil + save_data(_config.moderation.data, data) + end + data[tostring(GBan_log)][tostring(msg.to.id)] = nil + save_data(_config.moderation.data, data) + local text = 'Log_SuperGroup has has been removed!' + reply_msg(msg.id,text,ok_cb,false) + return + else + reply_msg(msg.id,"Failed to remove log SuperGroup",ok_cb,false) + return + end + end +end + local function set_bot_photo(msg, success, result) local receiver = get_receiver(msg) if success then @@ -13,11 +63,28 @@ local function set_bot_photo(msg, success, result) send_large_msg(receiver, 'Failed, please try again!', ok_cb, false) end end + +--Function to add log supergroup +local function logadd(msg) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + channel_get_admins(receiver, check_member_logadd,{receiver = receiver, data = data, msg = msg}) +end + +--Function to remove log supergroup +local function logrem(msg) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + channel_get_users(receiver, check_member_logrem,{receiver = receiver, data = data, msg = msg}) +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 @@ -36,27 +103,10 @@ local function get_contact_list_callback (cb_extra, success, result) 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 + for k,v in pairsByKeys(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..")" @@ -105,12 +155,40 @@ local function get_dialog_list_callback(cb_extra, success, result) file:close() send_document("user#id"..cb_extra.target,"dialog_list.json", ok_cb, false)--json format end + +-- Returns the key (index) in the config.enabled_plugins table +local function plugin_enabled( name ) + for k,v in pairs(_config.enabled_plugins) do + if name == v then + return k + end + end + -- If not found + return false +end + +-- Returns true if file exists in plugins folder +local function plugin_exists( name ) + for k,v in pairs(plugins_names()) do + if name..'.lua' == v then + return true + end + end + return false +end + +local function reload_plugins( ) + plugins = {} + return load_plugins() +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 + local print_name = user_print_name(msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + if not is_admin1(msg) then + return end if msg.media then if msg.media.type == 'photo' and redis:get("bot:photo") then @@ -138,14 +216,14 @@ local function run(msg,matches) send_large_msg("user#id"..matches[2],matches[3]) return "Msg sent" end - if matches[1] == "block" then + if matches[1] == "pmblock" 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 + if matches[1] == "pmunblock" then unblock_user("user#id"..matches[2],ok_cb,false) return "User unblocked" end @@ -157,53 +235,81 @@ local function run(msg,matches) 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.ir/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 + return "I've sent a group dialog list with both json and text format to your private" end + if matches[1] == 'reload' then + receiver = get_receiver(msg) + reload_plugins(true) + post_msg(receiver, "Reloaded!", ok_cb, false) + return "Reloaded!" + end + --[[*For Debug* + if matches[1] == "vardumpmsg" and is_admin1(msg) then + local text = serpent.block(msg, {comment=false}) + send_large_msg("channel#id"..msg.to.id, text) + end]] + if matches[1] == 'updateid' then + local data = load_data(_config.moderation.data) + local long_id = data[tostring(msg.to.id)]['long_id'] + if not long_id then + data[tostring(msg.to.id)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + return "Updated ID" + end + end + if matches[1] == 'addlog' and not matches[2] then + if is_log_group(msg) then + return "Already a Log_SuperGroup" + end + print("Log_SuperGroup "..msg.to.title.."("..msg.to.id..") added") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added Log_SuperGroup") + logadd(msg) + end + if matches[1] == 'remlog' and not matches[2] then + if not is_log_group(msg) then + return "Not a Log_SuperGroup" + end + print("Log_SuperGroup "..msg.to.title.."("..msg.to.id..") removed") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added Log_SuperGroup") + logrem(msg) + end return end + +local function pre_process(msg) + if not msg.text and msg.media then + msg.text = '['..msg.media.type..']' + end + return msg +end + return { patterns = { - "^[!/](pm) (%d+) (.*)$", - "^[!/](import) (.*)$", - "^[!/](unblock) (%d+)$", - "^[!/](block) (%d+)$", - "^[!/](markread) (on)$", - "^[!/](markread) (off)$", - "^[!/](setbotphoto)$", + "^[#!/](pm) (%d+) (.*)$", + "^[#!/](import) (.*)$", + "^[#!/](pmunblock) (%d+)$", + "^[#!/](pmblock) (%d+)$", + "^[#!/](markread) (on)$", + "^[#!/](markread) (off)$", + "^[#!/](setbotphoto)$", + "^[#!/](contactlist)$", + "^[#!/](dialoglist)$", + "^[#!/](delcontact) (%d+)$", + "^[#/!](reload)$", + "^[#/!](updateid)$", + "^[#/!](addlog)$", + "^[#/!](remlog)$", "%[(photo)%]", - "^[!/](contactlist)$", - "^[!/](dialoglist)$", - "^[!/](delcontact) (%d+)$", - "^[!/](addcontact) (.*) (.*) (.*)$", - "^[!/](whois) (%d+)$", - "^/(sync_gbans)$"--sync your global bans with seed }, run = run, + pre_process = pre_process } --By @imandaneshi :) ---https://github.com/SEEDTEAM/TeleSeed/blob/master/plugins/admin.lua +--https://github.com/SEEDTEAM/TeleSeed/blob/test/plugins/admin.lua +---Modified by @Rondoozle for supergroups \ No newline at end of file diff --git a/plugins/all.lua b/plugins/all.lua index fe4751c..820074d 100644 --- a/plugins/all.lua +++ b/plugins/all.lua @@ -1,5 +1,4 @@ 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 @@ -34,23 +33,9 @@ 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.' + return 'No group type available.\nUse /type in the group to set type.' 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 + return group_type end local function get_description(target) @@ -101,12 +86,17 @@ local function get_link(target) return "Group link:\n"..group_link end -local function all(target, receiver) +local function all(msg,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 + if group_type == "Group" or group_type == "Realm" then + local settings = show_group_settingsmod(msg,target) + text = text.."\n\n"..settings + elseif group_type == "SuperGroup" then + local settings = show_supergroup_settingsmod(msg,target) + text = text..'\n\n'..settings + end local rules = get_rules(target) text = text.."\n\nRules: \n"..rules local description = get_description(target) @@ -117,6 +107,10 @@ local function all(target, receiver) text = text.."\n\nLink: \n"..link local stats = chat_stats(target) text = text.."\n\n"..stats + local mutes_list = mutes_list(target) + text = text.."\n\n"..mutes_list + local muted_user_list = muted_user_list(target) + text = text.."\n\n"..muted_user_list local ban_list = ban_list(target) text = text.."\n\n"..ban_list local file = io.open("./groups/all/"..target.."all.txt", "w") @@ -127,29 +121,26 @@ local function all(target, receiver) return end -function run(msg, matches) +local 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) + return all(msg,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) + return all(msg,msg.to.id,receiver) end end return { patterns = { - "^[!/](all)$", - "^[!/](all) (%d+)$" + "^[#!/](all)$", + "^[#!/](all) (%d+)$" }, run = run } diff --git a/plugins/anti_spam.lua b/plugins/anti_spam.lua index 689857c..8f0f9fe 100644 --- a/plugins/anti_spam.lua +++ b/plugins/anti_spam.lua @@ -1,11 +1,9 @@ - --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 @@ -29,9 +27,6 @@ local function pre_process(msg) 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 @@ -41,7 +36,18 @@ local function pre_process(msg) redis:sadd(hash, msg.from.id) end - + -- Save stats on Redis + if msg.to.type == 'channel' then + -- User is on channel + local hash = 'channel:'..msg.to.id..':users' + redis:sadd(hash, msg.from.id) + end + + if msg.to.type == 'user' then + -- User is on chat + local hash = 'PM:'..msg.from.id + redis:sadd(hash, msg.from.id) + end -- Total user msgs local hash = 'msgs:'..msg.from.id..':'..msg.to.id @@ -49,7 +55,7 @@ local function pre_process(msg) --Load moderation data local data = load_data(_config.moderation.data) - if data[tostring(msg.to.id)] then + if data[tostring(msg.to.id)] and not data[tostring(msg.to.id)]['group_type'] == 'GBan_log' then --Check if flood is one or off if data[tostring(msg.to.id)]['settings']['flood'] == 'no' then return msg @@ -69,24 +75,45 @@ local function pre_process(msg) end local max_msg = NUM_MSG_MAX * 1 if msgs > max_msg then - local user = msg.from.id + local user = msg.from.id + local chat = msg.to.id + local whitelist = "whitelist" + local is_whitelisted = redis:sismember(whitelist, user) -- 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 + if is_whitelisted == true then + return msg + end + local receiver = get_receiver(msg) + if msg.to.type == 'user' then + local max_msg = 7 * 1 + print(msgs) + if msgs >= max_msg then + print("Pass2") + send_large_msg("user#id"..msg.from.id, "User ["..msg.from.id.."] blocked for spam.") + savelog(msg.from.id.." PM", "User ["..msg.from.id.."] blocked for spam.") + block_user("user#id"..msg.from.id,ok_cb,false)--Block user if spammed in private + end end - local name = user_print_name(msg.from) - --save it to log file - savelog(msg.to.id, name.." ["..msg.from.id.."] spammed and kicked ! ") + if kicktable[user] == true then + return + end + delete_msg(msg.id, ok_cb, false) + kick_user(user, chat) + local username = msg.from.username + local print_name = user_print_name(msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", "") + if msg.to.type == 'chat' or msg.to.type == 'channel' then + if username then + savelog(msg.to.id, name_log.." @"..username.." ["..msg.from.id.."] kicked for #spam") + send_large_msg(receiver , "Flooding is not allowed here\n@"..username.."["..msg.from.id.."]\nStatus: User kicked") + else + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked for #spam") + send_large_msg(receiver , "Flooding is not allowed here\nName:"..name_log.."["..msg.from.id.."]\nStatus: User kicked") + end + end -- incr it on redis local gbanspam = 'gban:spam'..msg.from.id redis:incr(gbanspam) @@ -100,16 +127,24 @@ local function pre_process(msg) 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 + else + username = "---" end - local name = user_print_name(msg.from) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") --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)") + send_large_msg("chat#id"..msg.to.id, "User [ "..name.." ]"..msg.from.id.." globally banned (spamming)") + send_large_msg("channel#id"..msg.to.id, "User [ "..name.." ]"..msg.from.id.." globally banned (spamming)") + local GBan_log = 'GBan_log' + local GBan_log = data[tostring(GBan_log)] + for k,v in pairs(GBan_log) do + log_SuperGroup = v + gban_text = "User [ "..name.." ] ( @"..username.." )"..msg.from.id.." Globally banned from ( "..msg.to.print_name.." ) [ "..msg.to.id.." ] (spamming)" + --send it to log group/channel + send_large_msg(log_SuperGroup, gban_text) + end end end kicktable[user] = true @@ -122,7 +157,7 @@ end local function cron() --clear that table on the top of the plugins - kicktable = {} + kicktable = {} end return { diff --git a/plugins/arabic_lock.lua b/plugins/arabic_lock.lua index 86e462f..fbc0dd1 100644 --- a/plugins/arabic_lock.lua +++ b/plugins/arabic_lock.lua @@ -1,4 +1,3 @@ - antiarabic = {}-- An empty table for solving multiple kicking problem do @@ -9,28 +8,43 @@ local function run(msg, matches) 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 is_whitelisted(msg.from.id) then + return + end 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 + if msg.to.type == 'chat' then + local receiver = get_receiver(msg) + local username = msg.from.username + local name = msg.from.first_name + if username and is_super_group(msg) then + send_large_msg(receiver , "Arabic/Persian is not allowed here\n@"..username.."["..msg.from.id.."]\nStatus: User kicked/msg deleted") + else + send_large_msg(receiver , "Arabic/Persian is not allowed here\nName: "..name.."["..msg.from.id.."]\nStatus: User kicked/msg deleted") + end + local name = user_print_name(msg.from) + savelog(msg.to.id, name.." ["..msg.from.id.."] kicked (arabic was locked) ") + local chat_id = msg.to.id + local user_id = msg.from.id + kick_user(user_id, chat_id) + end + antiarabic[msg.from.id] = true end end return end + local function cron() antiarabic = {} -- Clear antiarabic table end + return { patterns = { "([\216-\219][\128-\191])" }, run = run, - cron = cron + cron = cron } end diff --git a/plugins/banhammer.lua b/plugins/banhammer.lua index eda9676..f09f902 100644 --- a/plugins/banhammer.lua +++ b/plugins/banhammer.lua @@ -1,5 +1,6 @@ local function pre_process(msg) + local data = load_data(_config.moderation.data) -- SERVICE MESSAGE if msg.action and msg.action.type then local action = msg.action.type @@ -10,7 +11,8 @@ local function pre_process(msg) 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) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] is banned and kicked ! ")-- Save to logs kick_user(user_id, msg.to.id) end @@ -20,20 +22,21 @@ local function pre_process(msg) 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 + if banned and not is_momod2(msg.from.id, msg.to.id) or is_gbanned(user_id) and not is_admin2(msg.from.id) then -- Check it with redis print('User is banned!') - local name = user_print_name(msg.from) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") 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 + 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 + 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 @@ -42,14 +45,15 @@ local function pre_process(msg) 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 + 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) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") 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 @@ -59,20 +63,20 @@ local function pre_process(msg) return msg end -- banned user is talking ! - if msg.to.type == 'chat' then - local data = load_data(_config.moderation.data) + if msg.to.type == 'chat' or msg.to.type == 'channel' then 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 + --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) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] banned user is talking !")-- Save to logs kick_user(user_id, chat_id) msg.text = '' @@ -82,29 +86,38 @@ local function pre_process(msg) end local function kick_ban_res(extra, success, result) ---vardump(result) ---vardump(extra) - local member_id = result.id + local chat_id = extra.chat_id + local chat_type = extra.chat_type + if chat_type == "chat" then + receiver = 'chat#id'..chat_id + else + receiver = 'channel#id'..chat_id + end + if success == 0 then + return send_large_msg(receiver, "Cannot find user by that username!") + end + local member_id = result.peer_id local user_id = member_id local member = result.username - local chat_id = extra.chat_id - local from_id = extra.from_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") + send_large_msg(receiver, "You can't kick yourself") + return 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") + send_large_msg(receiver, "You can't kick mods/owner/admins") + return end - return kick_user(member_id, chat_id) + 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") + send_large_msg(receiver, "You can't ban mods/owner/admins") + return end send_large_msg(receiver, 'User @'..member..' ['..member_id..'] banned') - return ban_user(member_id, chat_id) + 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 @@ -112,85 +125,90 @@ local function kick_ban_res(extra, success, result) 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) + banall_user(member_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 + send_large_msg(receiver, 'User @'..member..' ['..member_id..'] globally unbanned') + unbanall_user(member_id) + end end local function run(msg, matches) - if matches[1]:lower() == 'id' then +local support_id = msg.from.id + if matches[1]:lower() == 'id' and msg.to.type == "chat" or msg.to.type == "user" 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) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") 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 + return "Group ID for " ..string.gsub(msg.to.print_name, "_", " ").. ":\n\n"..msg.to.id end end - if matches[1]:lower() == 'kickme' then-- /kickme + if matches[1]:lower() == 'kickme' and msg.to.type == "chat" then-- /kickme local receiver = get_receiver(msg) if msg.to.type == 'chat' then - local name = user_print_name(msg.from) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") 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 + 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] + if matches[2] and is_admin1(msg) then + chat_id = matches[2] end return ban_list(chat_id) end - if matches[1]:lower() == 'ban' then-- /ban + 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) + print('ok1') + if is_admin1(msg) then + print('ok2') + 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 + elseif 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 + if not is_admin1(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) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] baned user ".. matches[2]) - ban_user(user_id, chat_id) + ban_user(matches[2], msg.to.id) else local cbres_extra = { chat_id = msg.to.id, get_cmd = 'ban', - from_id = msg.from.id + from_id = msg.from.id, + chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') - res_user(username, kick_ban_res, cbres_extra) - end + resolve_username(username, kick_ban_res, cbres_extra) + end end - if matches[1]:lower() == 'unban' then -- /unban + 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 @@ -201,104 +219,105 @@ local function run(msg, matches) local user_id = targetuser local hash = 'banned:'..chat_id redis:srem(hash, user_id) - local name = user_print_name(msg.from) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") 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 + from_id = msg.from.id, + chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') - res_user(username, kick_ban_res, cbres_extra) + resolve_username(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 + if is_admin1(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 + elseif 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 + if not is_admin1(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) + local user_id = matches[2] + local chat_id = msg.to.id + print("sexy") + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", "") 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 + from_id = msg.from.id, + chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') - res_user(username, kick_ban_res, cbres_extra) + resolve_username(username, kick_ban_res, cbres_extra) end end - if not is_admin(msg) then - return - end + if not is_admin1(msg) and not is_support(support_id) 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) + if matches[1]:lower() == 'banall' and is_admin1(msg) then -- Global ban + if type(msg.reply_id) ~="nil" and is_admin1(msg) then + banall = 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 + return false end banall_user(targetuser) return 'User ['..user_id..' ] globally banned' - else + else local cbres_extra = { chat_id = msg.to.id, get_cmd = 'banall', - from_id = msg.from.id + from_id = msg.from.id, + chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') - res_user(username, kick_ban_res, cbres_extra) - end + resolve_username(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 + 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] + return 'User ['..user_id..' ] globally unbanned' + else + local cbres_extra = { + chat_id = msg.to.id, + get_cmd = 'unbanall', + from_id = msg.from.id, + chat_type = msg.to.type + } local username = string.gsub(matches[2], '@', '') - res_user(username, kick_ban_res, cbres_extra) + resolve_username(username, kick_ban_res, cbres_extra) end end if matches[1]:lower() == "gbanlist" then -- Global ban list @@ -308,24 +327,23 @@ 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)$", + "^[#!/]([Bb]anall) (.*)$", + "^[#!/]([Bb]anall)$", + "^[#!/]([Bb]anlist) (.*)$", + "^[#!/]([Bb]anlist)$", + "^[#!/]([Gg]banlist)$", + "^[#!/]([Kk]ickme)", + "^[#!/]([Kk]ick)$", + "^[#!/]([Bb]an)$", + "^[#!/]([Bb]an) (.*)$", + "^[#!/]([Uu]nban) (.*)$", + "^[#!/]([Uu]nbanall) (.*)$", + "^[#!/]([Uu]nbanall)$", + "^[#!/]([Kk]ick) (.*)$", + "^[#!/]([Uu]nban)$", + "^[#!/]([Ii]d)$", "^!!tgservice (.+)$" }, run = run, pre_process = pre_process } - diff --git a/plugins/block_user.lua b/plugins/block_user.lua new file mode 100644 index 0000000..837cba1 --- /dev/null +++ b/plugins/block_user.lua @@ -0,0 +1,18 @@ +local function run(msg, matches) + if matches[1] == "block" then + local user_id = "user#id"..matches[2] + block_user(user_id, ok_cb, false) + end + if matches[1] == "unblock" then + local user_id = "user#id"..matches[2] + unblock_user(user_id, ok_cb, false) + end +end + +return { + patterns = { + "^[!/](block) (.*)$", + "^[!/](unblock) (.*)$" + }, + run = run +} diff --git a/plugins/broadcast.lua b/plugins/broadcast.lua index eea356e..37ff6c2 100644 --- a/plugins/broadcast.lua +++ b/plugins/broadcast.lua @@ -1,7 +1,8 @@ local function run(msg, matches) - if matches[1] == 'bc' and is_admin(msg) then + if matches[1] == 'bc' and is_admin1(msg) then local response = matches[3] - send_large_msg("chat#id"..matches[2], response) + --send_large_msg("chat#id"..matches[2], response) + send_large_msg("channel#id"..matches[2], response) end if matches[1] == 'broadcast' then if is_sudo(msg) then -- Only sudo ! @@ -10,16 +11,18 @@ local function run(msg, matches) 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) + local chat = 'chat#id'..chat_id + local channel = 'channel#id'..chat_id + send_large_msg(chat, response) + send_large_msg(channel, response) end end end end return { patterns = { - "^[!/](broadcast) +(.+)$", - "^[!/](bc) (%d+) (.*)$" + "^[#!/](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 index 5ca47d5..881a877 100644 --- a/plugins/get.lua +++ b/plugins/get.lua @@ -1,5 +1,5 @@ local function get_variables_hash(msg) - if msg.to.type == 'chat' then + if msg.to.type == 'chat' or msg.to.type == 'channel' then return 'chat:'..msg.to.id..':variables' end end @@ -11,7 +11,7 @@ local function get_value(msg, var_name) if not value then return else - return var_name..' :\n'..value + return var_name..':\n'..value end end end @@ -31,7 +31,7 @@ end return { patterns = { - "^([!/]get) (.+)$" + "^([#!/]get) (.+)$" }, run = run } diff --git a/plugins/ingroup.lua b/plugins/ingroup.lua index 5606327..58238a1 100644 --- a/plugins/ingroup.lua +++ b/plugins/ingroup.lua @@ -6,7 +6,7 @@ local function check_member_autorealm(cb_extra, success, result) local data = cb_extra.data local msg = cb_extra.msg for k,v in pairs(result.members) do - local member_id = v.id + local member_id = v.peer_id if member_id ~= our_id then -- Group configuration data[tostring(msg.to.id)] = { @@ -36,7 +36,7 @@ local function check_member_realm_add(cb_extra, success, result) local data = cb_extra.data local msg = cb_extra.msg for k,v in pairs(result.members) do - local member_id = v.id + local member_id = v.peer_id if member_id ~= our_id then -- Group configuration data[tostring(msg.to.id)] = { @@ -66,7 +66,7 @@ function check_member_group(cb_extra, success, result) local data = cb_extra.data local msg = cb_extra.msg for k,v in pairs(result.members) do - local member_id = v.id + local member_id = v.peer_id if member_id ~= our_id then -- Group configuration data[tostring(msg.to.id)] = { @@ -98,11 +98,12 @@ local function check_member_modadd(cb_extra, success, result) local data = cb_extra.data local msg = cb_extra.msg for k,v in pairs(result.members) do - local member_id = v.id + local member_id = v.peer_id if member_id ~= our_id then -- Group configuration data[tostring(msg.to.id)] = { group_type = 'Group', + long_id = msg.to.peer_id, moderators = {}, set_owner = member_id , settings = { @@ -165,7 +166,7 @@ local function check_member_modrem(cb_extra, success, result) local data = cb_extra.data local msg = cb_extra.msg for k,v in pairs(result.members) do - local member_id = v.id + local member_id = v.peer_id if member_id ~= our_id then -- Group configuration removal data[tostring(msg.to.id)] = nil @@ -182,35 +183,55 @@ local function check_member_modrem(cb_extra, success, result) end end --End Check Member -local function show_group_settingsmod(msg, data, target) +function show_group_settingsmod(msg, 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']) + 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 + 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'] + if data[tostring(target)]['settings']['lock_bots'] then + bots_protection = data[tostring(target)]['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'] + if data[tostring(target)]['settings']['leave_ban'] then + leave_ban = data[tostring(target)]['settings']['leave_ban'] end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_link'] then + data[tostring(target)]['settings']['lock_link'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_sticker'] then + data[tostring(target)]['settings']['lock_sticker'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['public'] then + data[tostring(target)]['settings']['public'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_rtl'] then + data[tostring(target)]['settings']['lock_rtl'] = 'no' + 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.."\nLock group leave : "..leave_ban.."\nflood sensitivity : "..NUM_MSG_MAX.."\nBot protection : "..bots_protection--"\nPublic: "..public + 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.."\nLock links : "..settings.lock_link.."\nLock RTL: "..settings.lock_rtl.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public return text end local function set_descriptionmod(msg, data, target, about) if not is_momod(msg) then - return "For moderators only!" + return end local data_cat = 'description' data[tostring(target)][data_cat] = about @@ -228,7 +249,7 @@ local function get_description(msg, data) end local function lock_group_arabic(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] if group_arabic_lock == 'yes' then @@ -242,7 +263,7 @@ end local function unlock_group_arabic(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] if group_arabic_lock == 'no' then @@ -256,7 +277,7 @@ end local function lock_group_bots(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_bots_lock = data[tostring(target)]['settings']['lock_bots'] if group_bots_lock == 'yes' then @@ -270,7 +291,7 @@ end local function unlock_group_bots(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_bots_lock = data[tostring(target)]['settings']['lock_bots'] if group_bots_lock == 'no' then @@ -284,7 +305,7 @@ end local function lock_group_namemod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_name_set = data[tostring(target)]['settings']['set_name'] local group_name_lock = data[tostring(target)]['settings']['lock_name'] @@ -299,7 +320,7 @@ local function lock_group_namemod(msg, data, target) end local function unlock_group_namemod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_name_set = data[tostring(target)]['settings']['set_name'] local group_name_lock = data[tostring(target)]['settings']['lock_name'] @@ -312,8 +333,8 @@ local function unlock_group_namemod(msg, data, target) end end local function lock_group_floodmod(msg, data, target) - if not is_owner(msg) then - return "Only admins can do it for now" + if not is_momod(msg) then + return end local group_flood_lock = data[tostring(target)]['settings']['flood'] if group_flood_lock == 'yes' then @@ -326,8 +347,11 @@ local function lock_group_floodmod(msg, data, target) end local function unlock_group_floodmod(msg, data, target) + if not is_momod(msg) then + return + end if not is_owner(msg) then - return "Only admins can do it for now" + return "Only owners can unlock flood" end local group_flood_lock = data[tostring(target)]['settings']['flood'] if group_flood_lock == 'no' then @@ -341,7 +365,7 @@ end local function lock_group_membermod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_member_lock = data[tostring(target)]['settings']['lock_member'] if group_member_lock == 'yes' then @@ -355,7 +379,7 @@ end local function unlock_group_membermod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_member_lock = data[tostring(target)]['settings']['lock_member'] if group_member_lock == 'no' then @@ -370,9 +394,14 @@ end local function set_public_membermod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_member_lock = data[tostring(target)]['settings']['public'] + local long_id = data[tostring(target)]['long_id'] + if not long_id then + data[tostring(target)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + end if group_member_lock == 'yes' then return 'Group is already public' else @@ -384,9 +413,14 @@ end local function unset_public_membermod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_member_lock = data[tostring(target)]['settings']['public'] + local long_id = data[tostring(target)]['long_id'] + if not long_id then + data[tostring(target)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + end if group_member_lock == 'no' then return 'Group is not public' else @@ -398,13 +432,13 @@ end local function lock_group_leave(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end - local leave_ban = data[tostring(msg.to.id)]['settings']['leave_ban'] + local leave_ban = data[tostring(target)]['settings']['leave_ban'] if leave_ban == 'yes' then return 'Leaving users will be banned' else - data[tostring(msg.to.id)]['settings']['leave_ban'] = 'yes' + data[tostring(target)]['settings']['leave_ban'] = 'yes' save_data(_config.moderation.data, data) end return 'Leaving users will be banned' @@ -412,13 +446,13 @@ end local function unlock_group_leave(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return 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' + data[tostring(target)]['settings']['leave_ban'] = 'no' save_data(_config.moderation.data, data) return 'Leaving users will not be banned' end @@ -426,7 +460,7 @@ end local function unlock_group_photomod(msg, data, target) if not is_momod(msg) then - return "For moderators only!" + return end local group_photo_lock = data[tostring(target)]['settings']['lock_photo'] if group_photo_lock == 'no' then @@ -438,6 +472,146 @@ local function unlock_group_photomod(msg, data, target) end end +local function lock_group_links(msg, data, target) + if not is_momod(msg) then + return + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'yes' then + return 'Link posting is already locked' + else + data[tostring(target)]['settings']['lock_link'] = 'yes' + save_data(_config.moderation.data, data) + return 'Link posting has been locked' + end +end + +local function unlock_group_links(msg, data, target) + if not is_momod(msg) then + return + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'no' then + return 'Link posting is not locked' + else + data[tostring(target)]['settings']['lock_link'] = 'no' + save_data(_config.moderation.data, data) + return 'Link posting has been unlocked' + end +end + +local function lock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'yes' then + return 'RTL is already locked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'yes' + save_data(_config.moderation.data, data) + return 'RTL has been locked' + end +end + +local function unlock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'no' then + return 'RTL is already unlocked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'no' + save_data(_config.moderation.data, data) + return 'RTL has been unlocked' + end +end + +local function lock_group_sticker(msg, data, target) + if not is_momod(msg) then + return + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'yes' then + return 'Sticker posting is already locked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'yes' + save_data(_config.moderation.data, data) + return 'Sticker posting has been locked' + end +end + +local function unlock_group_sticker(msg, data, target) + if not is_momod(msg) then + return + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'no' then + return 'Sticker posting is already unlocked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'no' + save_data(_config.moderation.data, data) + return 'Sticker posting has been unlocked' + end +end + +local function lock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'yes' then + return 'Contact posting is already locked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'yes' + save_data(_config.moderation.data, data) + return 'Contact posting has been locked' + end +end + +local function unlock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'no' then + return 'Contact posting is already unlocked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'no' + save_data(_config.moderation.data, data) + return 'Contact posting has been unlocked' + end +end + +local function enable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['strict'] + if strict == 'yes' then + return 'Settings are already strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'yes' + save_data(_config.moderation.data, data) + return 'Settings will be strictly enforced' + end +end + +local function disable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['strict'] + if strict == 'no' then + return 'Settings are not strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'no' + save_data(_config.moderation.data, data) + return 'Settings will not be strictly enforced' + end +end + local function set_rulesmod(msg, data, target) if not is_momod(msg) then return "For moderators only!" @@ -445,11 +619,14 @@ local function set_rulesmod(msg, data, target) local data_cat = 'rules' data[tostring(target)][data_cat] = rules save_data(_config.moderation.data, data) - return 'Set group rules to:\n'..rules + return 'Set group rules to:\n\n'..rules end local function modadd(msg) -- superuser and admins only (because sudo are always has privilege) - if not is_admin(msg) then + if not is_momod(msg) then + return + end + if not is_admin1(msg) then return "You're not admin" end local data = load_data(_config.moderation.data) @@ -461,7 +638,10 @@ local function modadd(msg) end local function realmadd(msg) -- superuser and admins only (because sudo are always has privilege) - if not is_admin(msg) then + if not is_momod(msg) then + return + end + if not is_admin1(msg) then return "You're not admin" end local data = load_data(_config.moderation.data) @@ -469,12 +649,12 @@ local function realmadd(msg) return 'Realm is already added.' end receiver = get_receiver(msg) - chat_info(receiver, check_member_realm_add,{receiver=receiver, data=data, msg = 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 + if not is_admin1(msg) then return "You're not admin" end local data = load_data(_config.moderation.data) @@ -487,7 +667,7 @@ end function realmrem(msg) -- superuser and admins only (because sudo are always has privilege) - if not is_admin(msg) then + if not is_admin1(msg) then return "You're not admin" end local data = load_data(_config.moderation.data) @@ -503,7 +683,7 @@ local function get_rules(msg, data) return 'No rules available.' end local rules = data[tostring(msg.to.id)][data_cat] - local rules = 'Chat rules:\n'..rules + local rules = 'Chat rules:\n\n'..rules return rules end @@ -549,10 +729,10 @@ local function promote_by_reply(extra, success, result) else member_username = full_name end - local member_id = msg.from.id - if msg.to.type == 'chat' then + local member_id = msg.from.peer_id + if msg.to.peer_type == 'chat' then return promote(get_receiver(msg), member_username, member_id) - end + end end local function demote(receiver, member_username, member_id) @@ -577,10 +757,10 @@ local function demote_by_reply(extra, success, result) else member_username = full_name end - local member_id = msg.from.id - if msg.to.type == 'chat' then + local member_id = msg.from.peer_id + if msg.to.peer_type == 'chat' then return demote(get_receiver(msg), member_username, member_id) - end + end end local function setowner_by_reply(extra, success, result) @@ -590,7 +770,7 @@ local function setowner_by_reply(extra, success, result) 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") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set ["..msg.from.id.."] as owner") local text = msg.from.print_name:gsub("_", " ").." is the owner now" return send_large_msg(receiver, text) end @@ -598,7 +778,7 @@ end local function promote_demote_res(extra, success, result) --vardump(result) --vardump(extra) - local member_id = result.id + local member_id = result.peer_id local member_username = "@"..result.username local chat_id = extra.chat_id local mod_cmd = extra.mod_cmd @@ -610,6 +790,28 @@ local function promote_demote_res(extra, success, result) end end +local function mute_user_callback(extra, success, result) + if result.service then + local action = result.action.type + if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then + if result.action.user then + user_id = result.action.user.peer_id + end + end + else + user_id = result.from.peer_id + end + local receiver = extra.receiver + local chat_id = string.gsub(receiver, 'channel#id', '') + if is_muted_user(chat_id, user_id) then + mute_user(chat_id, user_id) + send_large_msg(receiver, "["..user_id.."] removed from the muted user list") + else + unmute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] added to the muted user list") + end +end + local function modlist(msg) local data = load_data(_config.moderation.data) local groups = "groups" @@ -631,13 +833,25 @@ end local function callbackres(extra, success, result) --vardump(result) - local user = result.id + local user = result.peer_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 callback_mute_res(extra, success, result) + local user_id = result.peer_id + local receiver = extra.receiver + local chat_id = string.gsub(receiver, 'chat#id', '') + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] removed from muted user list") + else + mute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] added to muted user list") + end +end local function help() local help_text = tostring(_config.help_text) @@ -649,7 +863,7 @@ local function cleanmember(cb_extra, success, result) 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) + kick_user(v.id, result.peer_id) end end @@ -658,7 +872,7 @@ local function killchat(cb_extra, success, result) 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) + kick_user_any(v.id, result.peer_id) end end @@ -667,11 +881,11 @@ local function killrealm(cb_extra, success, result) 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) + kick_user_any(v.id, result.peer_id) end end -local function user_msgs(user_id, chat_id) +--[[local function user_msgs(user_id, chat_id) local user_info local uhash = 'user:'..user_id local user = redis:hgetall(uhash) @@ -687,7 +901,7 @@ local function kick_zero(cb_extra, success, result) local re_user for k,v in pairs(result.members) do local si = false - ci_user = v.id + ci_user = v.peer_id local hash = 'chat:'..chat_id..':users' local users = redis:smembers(hash) for i = 1, #users do @@ -721,7 +935,7 @@ local function kick_inactive(chat_id, num, receiver) end end return chat_info(receiver, kick_zero, {chat_id = chat_id}) -end +end]] local function run(msg, matches) local data = load_data(_config.moderation.data) @@ -733,6 +947,7 @@ local function run(msg, matches) load_photo(msg.id, set_group_photo, msg) end end +if msg.to.type == 'chat' then if matches[1] == 'add' and not matches[2] then if is_realm(msg) then return 'Error: Already a realm.' @@ -758,15 +973,25 @@ local function run(msg, matches) if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "group" then return automodadd(msg) end + + --[[Experimental + if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "super_group" then + local chat_id = get_receiver(msg) + users = {[1]="user#id167472799",[2]="user#id170131770"} + for k,v in pairs(users) do + chat_add_user(chat_id, v, ok_cb, false) + end + --chat_upgrade(chat_id, ok_cb, false) + 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?" + return end local group_member_lock = settings.lock_member local user = 'user#id'..msg.action.user.id @@ -789,7 +1014,7 @@ local function run(msg, matches) end if matches[1] == 'chat_delete_photo' then if not msg.service then - return "Are you trying to troll me?" + return end local group_photo_lock = settings.lock_photo if group_photo_lock == 'yes' then @@ -797,18 +1022,18 @@ local function run(msg, matches) 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 + 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 + 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 @@ -817,7 +1042,7 @@ local function run(msg, matches) 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?" + return end local group_photo_lock = settings.lock_photo if group_photo_lock == 'yes' then @@ -825,18 +1050,18 @@ local function run(msg, matches) 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 + 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 + 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 @@ -845,7 +1070,7 @@ local function run(msg, matches) end if matches[1] == 'chat_rename' then if not msg.service then - return "Are you trying to troll me?" + return end local group_name_set = settings.set_name local group_name_lock = settings.lock_name @@ -855,18 +1080,17 @@ local function run(msg, matches) 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 + 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 + 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 @@ -881,7 +1105,7 @@ local function run(msg, matches) 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 @@ -890,6 +1114,9 @@ local function run(msg, matches) return 'Please send me new group photo now' end if matches[1] == 'promote' and not matches[2] then + if not is_momod(msg) then + return + end if not is_owner(msg) then return "Only the owner can prmote new moderators" end @@ -905,17 +1132,20 @@ local function run(msg, matches) return "Only owner can promote" end local member = matches[2] - savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted @".. member) + 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 + 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) + return resolve_username(username, promote_demote_res, cbres_extra) end if matches[1] == 'demote' and not matches[2] then + if not is_momod(msg) then + return + end if not is_owner(msg) then return "Only the owner can demote moderators" end @@ -937,12 +1167,12 @@ local function run(msg, matches) savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted @".. member) local cbres_extra = { chat_id = msg.to.id, - mod_cmd = 'demote', + 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) + return resolve_username(username, promote_demote_res, cbres_extra) end if matches[1] == 'modlist' then savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group modlist") @@ -971,71 +1201,299 @@ local function run(msg, matches) return set_descriptionmod(msg, data, target, about) end end +end +--Begin chat settings 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 + 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 + if matches[2] == 'links' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked link posting ") + return lock_group_links(msg, data, target) + end + if matches[2]:lower() == 'rtl' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked rtl chars. in names") + return lock_group_rtl(msg, data, target) + end + if matches[2] == 'sticker' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked sticker posting") + return lock_group_sticker(msg, data, target) + end + if matches[2] == 'contacts' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked contact posting") + return lock_group_contacts(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 + if matches[2] == 'links' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked link posting") + return unlock_group_links(msg, data, target) + end + if matches[2]:lower() == 'rtl' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked RTL chars. in names") + return unlock_group_rtl(msg, data, target) + end + if matches[2] == 'sticker' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked sticker posting") + return unlock_group_sticker(msg, data, target) + end + if matches[2] == 'contacts' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked contact posting") + return unlock_group_contacts(msg, data, target) + end + end + --End chat settings + + --Begin Chat mutes + + if matches[1] == 'mute' and is_owner(msg) then + local chat_id = msg.to.id + if matches[2] == 'audio' then + local msg_type = 'Audio' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return "Group "..matches[2].." has been muted" + else + return "Group mute "..matches[2].." is already on" + end + end + if matches[2] == 'photo' then + local msg_type = 'Photo' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return "Group "..matches[2].." has been muted" + else + return "Group mute "..matches[2].." is already on" + end + end + if matches[2] == 'video' then + local msg_type = 'Video' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return "Group "..matches[2].." has been muted" + else + return "Group mute "..matches[2].." is already on" + end + end + if matches[2] == 'gifs' then + local msg_type = 'Gifs' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." have been muted" + else + return "Group mute "..msg_type.." is already on" + end + end + if matches[2] == 'documents' then + local msg_type = 'Documents' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." have been muted" + else + return "Group mute "..msg_type.." is already on" + end + end + if matches[2] == 'text' then + local msg_type = 'Text' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return "Group text has been muted" + else + return "Group mute text is already on" + end + end + if matches[2] == 'all' then + local msg_type = 'All' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: mute "..msg_type) + mute(chat_id, msg_type) + return "Mute "..msg_type.." has been enabled" + else + return "Mute "..msg_type.." is already on" + end + end + end + if matches[1] == 'unmute' and is_owner(msg) then + local chat_id = msg.to.id + if matches[2] == 'audio' then + local msg_type = 'Audio' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute "..msg_type) + unmute(chat_id, msg_type) + return "Group "..msg_type.." has been unmuted" + else + return "Group mute "..msg_type.." is already off" + end + end + if matches[2] == 'photo' then + local msg_type = 'Photo' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute "..msg_type) + unmute(chat_id, msg_type) + return "Group "..msg_type.." has been unmuted" + else + return "Group mute "..msg_type.." is already off" + end + end + if matches[2] == 'Video' then + local msg_type = 'Video' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute "..msg_type) + unmute(chat_id, msg_type) + return "Group "..msg_type.." has been unmuted" + else + return "Group mute "..msg_type.." is already off" + end + end + if matches[2] == 'gifs' then + local msg_type = 'Gifs' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." have been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'documents' then + local msg_type = 'Documents' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." have been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'text' then + local msg_type = 'Text' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute message") + unmute(chat_id, msg_type) + return "Group text has been unmuted" + else + return "Group mute text is already off" + end + end + if matches[2] == 'all' then + local msg_type = 'All' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: unmute "..msg_type) + unmute(chat_id, msg_type) + return "Mute "..msg_type.." has been disabled" + else + return "Mute "..msg_type.." is already disabled" + end + end + end + + --Begin chat muteuser + if matches[1] == "muteuser" and is_momod(msg) then + local chat_id = msg.to.id + local hash = "mute_user"..chat_id + local user_id = "" + if type(msg.reply_id) ~= "nil" then + local receiver = get_receiver(msg) + local get_cmd = "mute_user" + get_message(msg.reply_id, mute_user_callback, {receiver = receiver, get_cmd = get_cmd}) + elseif matches[1] == "muteuser" and string.match(matches[2], '^%d+$') then + local user_id = matches[2] + if is_muted_user(chat_id, user_id) then + mute_user(chat_id, user_id) + return "["..user_id.."] removed from the muted users list" + else + unmute_user(chat_id, user_id) + return "["..user_id.."] added to the muted user list" + end + elseif matches[1] == "muteuser" and not string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local get_cmd = "mute_user" + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + resolve_username(username, callback_mute_res, {receiver = receiver, get_cmd = get_cmd}) + end + end + + --End Chat muteuser + if matches[1] == "muteslist" and is_momod(msg) then + local chat_id = msg.to.id + if not has_mutes(chat_id) then + set_mutes(chat_id) + return mutes_list(chat_id) + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup muteslist") + return mutes_list(chat_id) + end + if matches[1] == "mutelist" and is_momod(msg) then + local chat_id = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup mutelist") + return muted_user_list(chat_id) + end + + if matches[1] == 'settings' and is_momod(msg) 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 + return show_group_settingsmod(msg, target) + end - --[[if matches[1] == 'public' then + if matches[1] == 'public' and is_momod(msg) then local target = msg.to.id if matches[2] == 'yes' then savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: public") @@ -1045,8 +1503,9 @@ local function run(msg, matches) savelog(msg.to.id, name_log.." ["..msg.from.id.."] set group to: not public") return unset_public_membermod(msg, data, target) end - end]] + end +if msg.to.type == 'chat' then if matches[1] == 'newlink' and not is_realm(msg) then if not is_momod(msg) then return "For moderators only!" @@ -1069,7 +1528,7 @@ local function run(msg, matches) return "For moderators only!" end local group_link = data[tostring(msg.to.id)]['settings']['set_link'] - if not group_link then + 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.."]") @@ -1093,22 +1552,18 @@ local function run(msg, matches) msgr = get_message(msg.reply_id, setowner_by_reply, false) end 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 + 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 + return "Group owner is ["..group_owner..']' end if matches[1] == 'setgpowner' then local receiver = "chat#id"..matches[2] - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end data[tostring(matches[2])]['set_owner'] = matches[3] @@ -1117,7 +1572,7 @@ local function run(msg, matches) send_large_msg(receiver, text) return end - if matches[1] == 'setflood' then + if matches[1] == 'setflood' then if not is_momod(msg) then return "For moderators only!" end @@ -1130,6 +1585,8 @@ local function run(msg, matches) 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 msg.to.type == 'chat' then if matches[1] == 'clean' then if not is_owner(msg) then return "Only owner can clean" @@ -1141,6 +1598,7 @@ local function run(msg, matches) local receiver = get_receiver(msg) chat_info(receiver, cleanmember, {receiver=receiver}) end + end if matches[2] == 'modlist' then if next(data[tostring(msg.to.id)]['moderators']) == nil then --fix way return 'No moderator in this group.' @@ -1152,21 +1610,22 @@ local function run(msg, matches) end savelog(msg.to.id, name_log.." ["..msg.from.id.."] cleaned modlist") end - if matches[2] == 'rules' then + 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 + 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 end +if msg.to.type == 'chat' then if matches[1] == 'kill' and matches[2] == 'chat' then - if not is_admin(msg) then + if not is_admin1(msg) then return nil end if not is_realm(msg) then @@ -1179,7 +1638,7 @@ local function run(msg, matches) end end if matches[1] == 'kill' and matches[2] == 'realm' then - if not is_admin(msg) then + if not is_admin1(msg) then return nil end if not is_group(msg) then @@ -1198,14 +1657,14 @@ local function run(msg, matches) savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /help") return help() end - if matches[1] == 'res' and is_momod(msg) then + if matches[1] == 'res' 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) + resolve_username(username, callbackres, cbres_extra) + return end if matches[1] == 'kickinactive' then --send_large_msg('chat#id'..msg.to.id, 'I\'m in matches[1]') @@ -1220,48 +1679,64 @@ local function run(msg, matches) local receiver = get_receiver(msg) return kick_inactive(chat_id, num, receiver) end - end + 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 { 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+)$", + "^[#!/](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)$", + "^[#!/]([Mm]ute) ([^%s]+)$", + "^[#!/]([Uu]nmute) ([^%s]+)$", + "^[#!/]([Mm]uteuser)$", + "^[#!/]([Mm]uteuser) (.*)$", + "^[#!/]([Mm]uteslist)$", + "^[#!/]([Mm]utelist)$", + "^[#!/](kickinactive)$", + "^[#!/](kickinactive) (%d+)$", + "%[(document)%]", "%[(photo)%]", + "%[(video)%]", + "%[(audio)%]", "^!!tgservice (.+)$", }, - run = run + run = run, + pre_process = pre_process } end - - diff --git a/plugins/inpm.lua b/plugins/inpm.lua index 5c031f6..87affb8 100644 --- a/plugins/inpm.lua +++ b/plugins/inpm.lua @@ -1,90 +1,258 @@ -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 pre_process(msg) +local to = msg.to.type +local service = msg.service + if to == 'user' and msg.fwd_from then + if not is_support(msg.from.id) and not is_admin1(msg) then + return + end + local user = 'user#id'..msg.from.id + local from_id = msg.fwd_from.peer_id + if msg.fwd_from.first_name then + from_first_name = msg.fwd_from.first_name:gsub("_", " ") + else + from_first_name = "None" + end + if msg.fwd_from.last_name then + from_last_name = msg.fwd_from.last_name:gsub("_", " ") + else + from_last_name = "None" + end + if msg.fwd_from.username then + from_username = "@"..msg.fwd_from.username + else + from_username = "@[none]" + end + text = "User From Info:\n\nID: "..from_id.."\nFirst: "..from_first_name.."\nLast: "..from_last_name.."\nUsername: "..from_username + send_large_msg(user, text) + end + return msg +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 ' + i = 1 + 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 pairsByKeys(data[tostring(groups)]) do + local group_id = v + if data[tostring(group_id)] then + settings = data[tostring(group_id)]['settings'] + end + if settings then + if not settings.public then + public = 'no' + else + public = settings.public + end + end + for m,n in pairsByKeys(settings) do + --if m == 'public' then + --public = n + --end + if public == 'no' then + group_info = "" + elseif m == 'set_name' and public == 'yes' then + name = n:gsub("", "") + chat_name = name:gsub("‮", "") + group_name_id = name .. '\n(ID: ' ..group_id.. ')\n\n' + if name:match("[\216-\219][\128-\191]") then + group_info = i..' - \n'..group_name_id + else + group_info = i..' - '..group_name_id + end + i = i + 1 + end end + message = message..group_info + end local file = io.open("./groups/lists/listed_groups.txt", "w") file:write(message) file:flush() file:close() - return message + return message +end + +function super_help() + local help_text = tostring(_config.help_text_super) + return help_text 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 +local to = msg.to.type +local service = msg.service +local name_log = user_print_name(msg.from) +if to == 'user' or service or is_admin1(msg) and to == "chat" or to == "channel" then + if is_gbanned(msg.from.id) then + return 'You are globally banned.' + end + if matches[1] == 'join' then + local data = load_data(_config.moderation.data) + if matches[2]:lower() == 'english' and matches[3]:lower() == 'support' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] tried to join English support") + local target = 1041751030 + local long_id = data[tostring(target)]['long_id'] + if is_banned(msg.from.id, tostring(target)) then + return 'You are banned.' + end + if data[tostring(target)]['settings']['lock_member'] == 'yes' and not is_owner2(msg.from.id, tostring(target)) then + return 'Group is private.' + end + if is_admin1(msg) then + user_type = 'admin' + else + user_type = "regular" + end + group_name = data[tostring(target)]['settings']['set_name'] + local chat = long_id + local channel = long_id + local user = msg.from.peer_id + chat_add_user(chat, user, ok_cb, false) + channel_invite(channel, user, ok_cb, false) + elseif matches[2]:lower() == 'persian' and matches[3]:lower() == 'support' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] tried to join Persian support") + local target = 1017700355 + local long_id = data[tostring(target)]['long_id'] + if is_banned(msg.from.id, tostring(target)) then + return 'You are banned.' + end + if data[tostring(target)]['settings']['lock_member'] == 'yes' and not is_owner2(msg.from.id, '36088606') then + return 'Group is private.' + end + if is_admin1(msg) then + user_type = 'admin' + else + user_type = "regular" + end + group_name = data[tostring(target)]['settings']['set_name'] + local chat = long_id + local channel = long_id + local user = msg.from.peer_id + chat_add_user(chat, user, ok_cb, false) + channel_invite(channel, user, ok_cb, false) + elseif string.match(matches[2], '^%d+$') then + local long_id = tostring(data[tostring(matches[2])]['long_id']) + if not data[tostring(matches[2])] then + return "Chat not found." + end + group_name = data[tostring(matches[2])]['settings']['set_name'] + if is_admin1(msg) then + user_type = 'admin' + local receiver = get_receiver(msg) + local chat = long_id + local channel = long_id + local user = msg.from.peer_id + chat_add_user(chat, user, ok_cb, false) + channel_set_admin(channel, user, ok_cb, false) + end + if is_support(msg.from.id) and not is_admin1(msg) and not is_owner2(msg.fom.id, matches[2]) then + user_type = "support" + local receiver = get_receiver(msg) + local chat = long_id + local channel = long_id + local user = msg.from.peer_id + chat_add_user(chat, user, ok_cb, false) + channel_set_mod(channel, user, ok_cb, false) + end 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 + return 'You are 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 + if not is_support(msg.from.id) and not is_admin1(msg) then + user_type = "regular" + local chat = long_id + local channel = long_id + local user = msg.from.peer_id + chat_add_user(chat, user, ok_cb, false) + channel_invite(channel, user, ok_cb, false) + end + end + end + end + + if msg.service and user_type == "support" and msg.action.type == "chat_add_user" and msg.from.id == 0 then + local user_id = msg.action.user.id + local user_name = msg.action.user.print_name + local username = msg.action.user.username + local group_name = string.gsub(msg.to.print_name, '_', ' ') + savelog(msg.from.id, "Added Support member "..user_name.." to chat "..group_name.." (ID:"..msg.to.id..")") + if username then + send_large_msg("user#id"..user_id, "Added support member\n@"..username.."["..user_id.."] to chat:\n 👥 "..group_name.." (ID:"..msg.to.id..")" ) + else + send_large_msg("user#id"..user_id, "Added support member\n["..user_id.."] to chat:\n 👥 "..group_name.." (ID:"..msg.to.id..")" ) + end + end + if msg.service and user_type == "admin" and msg.action.type == "chat_add_user" and msg.from.id == 0 then + local user_id = msg.action.user.id + local user_name = msg.action.user.print_name + local username = msg.action.user.username + savelog(msg.from.id, "Added Admin "..user_name.." "..user_id.." to chat "..group_name.." (ID:"..msg.to.id..")") + if username then + send_large_msg("user#id"..user_id, "Added admin\n@"..username.."["..user_id.."] to chat:\n 👥 "..group_name.." (ID:"..msg.to.id..")" ) + else + send_large_msg("user#id"..user_id, "Added admin:\n["..user_id.."] to chat:\n 👥 "..group_name.." (ID:"..msg.to.id..")" ) + end + end + + if msg.service and user_type == "regular" and msg.action.type == "chat_add_user" and msg.from.id == 0 then + local user_id = msg.action.user.id + local user_name = msg.action.user.print_name + print("Added "..user_id.." to chat "..msg.to.print_name.." (ID:"..msg.to.id..")") + savelog(msg.from.id, "Added "..user_name.." to chat "..msg.to.print_name.." (ID:"..msg.to.id..")") + send_large_msg("user#id"..user_id, "Added you to chat:\n\n"..group_name.." (ID:"..msg.to.id..")") + end + + if matches[1] == 'help' and msg.to.type == 'user' or matches[1] == 'pmhelp' and is_admin1(msg) and msg.to.type ~= 'user' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] used pm help") + text = "Welcome to TeleSeed!\n\nTo get a list of TeleSeed groups use /chats or /chatlist for a document list of chats.\n\nTo get a new TeleSeed group, contact a support group:\n\nFor English support, use: /join English support\n\nFor Persian support, use: /join Persian support\n\nFor more information, check out our channels:\n\n@TeleseedCH [English]\n@Iranseed [Persian]\n\nThanks for using @TeleSeed!" + return text + end + + if matches[1] == 'superhelp' and is_admin1(msg)then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /superhelp") + return super_help() + elseif matches[1] == 'superhelp' and to == "user" then + local name_log = user_print_name(msg.from) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /superhelp") + return super_help() + end + + if matches[1] == 'chats' and is_admin1(msg)then + return chat_list(msg) + elseif matches[1] == 'chats' and to == 'user' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /chats") + return chat_list(msg) + end + + if matches[1] == 'chatlist' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /chatlist") + if is_admin1(msg) and msg.to.type == 'chat' or msg.to.type == 'channel' then + chat_list(msg) + send_document("chat#id"..msg.to.id, "./groups/lists/listed_groups.txt", ok_cb, false) + send_document("channel#id"..msg.to.id, "./groups/lists/listed_groups.txt", ok_cb, false) + elseif msg.to.type == 'user' then + chat_list(msg) + send_document("user#id"..msg.from.id, "./groups/lists/listed_groups.txt", ok_cb, false) + end + end end return { patterns = { - "^[/!](chats)$", - "^[/!](chatlist)$", - "^[/!](join) (.*)$", - "^[/!](kickme) (.*)$", - "^!!tgservice (chat_add_user)$" + "^[#!/](help)$", + "^[#!/](pmhelp)$", + "^[#!/](superhelp)$", + "^[#!/](chats)$", + "^[#!/](chatlist)$", + "^[#!/](join) (%d+)$", + "^[#!/](join) (.*) (support)$", + "^[#!/](kickme) (.*)$", + "^!!tgservice (chat_add_user)$", }, run = run, -} -end - + pre_process = pre_process +} \ No newline at end of file diff --git a/plugins/inrealm.lua b/plugins/inrealm.lua index 3388fa7..177fd1a 100644 --- a/plugins/inrealm.lua +++ b/plugins/inrealm.lua @@ -3,39 +3,39 @@ 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 + -- superuser and admins only (because sudo are always has privilege) + if is_sudo(msg) or is_realm(msg) and is_admin1(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 + if is_sudo(msg) or is_realm(msg) and is_admin1(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 chat_id = "chat#id"..result.peer_id local chatname = result.print_name for k,v in pairs(result.members) do - kick_user_any(v.id, result.id) + kick_user_any(v.peer_id, result.peer_id) end end local function killrealm(cb_extra, success, result) local receiver = cb_extra.receiver - local chat_id = "chat#id"..result.id + local chat_id = "chat#id"..result.peer_id local chatname = result.print_name for k,v in pairs(result.members) do - kick_user_any(v.id, result.id) + kick_user_any(v.peer_id, result.peer_id) end end @@ -43,26 +43,34 @@ 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.' + if msg.to.type == 'chat' and not is_realm(msg) then + data[tostring(msg.to.id)]['group_type'] = 'Group' + save_data(_config.moderation.data, data) + elseif msg.to.type == 'channel' then + data[tostring(msg.to.id)]['group_type'] = 'SuperGroup' + save_data(_config.moderation.data, data) + end end - local group_type = data[tostring(msg.to.id)]['group_type'] - return group_type - else - return 'Chat type not found.' - 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 user = result.peer_id local name = string.gsub(result.print_name, "_", " ") local chat = 'chat#id'..extra.chatid + local channel = 'channel#id'..extra.chatid send_large_msg(chat, user..'\n'..name) + send_large_msg(channel, user..'\n'..name) return user end local function set_description(msg, data, target, about) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end local data_cat = 'description' @@ -70,9 +78,9 @@ local function set_description(msg, data, target, 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 + if not is_admin1(msg) then return "For admins only!" end local data_cat = 'rules' @@ -82,7 +90,7 @@ local function set_rules(msg, data, target) 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 + if not is_admin1(msg) then return "For admins only!" end local group_name_set = data[tostring(target)]['settings']['set_name'] @@ -94,11 +102,11 @@ local function lock_group_name(msg, data, target) 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 end - + local function unlock_group_name(msg, data, target) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end local group_name_set = data[tostring(target)]['settings']['set_name'] @@ -109,11 +117,11 @@ local function unlock_group_name(msg, data, target) data[tostring(target)]['settings']['lock_name'] = 'no' save_data(_config.moderation.data, data) return 'Group name has been unlocked' - end + 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 + if not is_admin1(msg) then return "For admins only!" end local group_member_lock = data[tostring(target)]['settings']['lock_member'] @@ -125,9 +133,9 @@ local function lock_group_member(msg, data, target) end return 'Group members has been locked' end - + local function unlock_group_member(msg, data, target) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end local group_member_lock = data[tostring(target)]['settings']['lock_member'] @@ -137,12 +145,12 @@ local function unlock_group_member(msg, data, target) data[tostring(target)]['settings']['lock_member'] = 'no' save_data(_config.moderation.data, data) return 'Group members has been unlocked' - end + 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 + if not is_admin1(msg) then return "For admins only!" end local group_photo_lock = data[tostring(target)]['settings']['lock_photo'] @@ -152,11 +160,11 @@ local function lock_group_photo(msg, data, target) data[tostring(target)]['settings']['set_photo'] = 'waiting' save_data(_config.moderation.data, data) end - return 'Please send me the group photo now' + return 'Please send me the group photo now' end - + local function unlock_group_photo(msg, data, target) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end local group_photo_lock = data[tostring(target)]['settings']['lock_photo'] @@ -166,11 +174,11 @@ local function unlock_group_photo(msg, data, target) data[tostring(target)]['settings']['lock_photo'] = 'no' save_data(_config.moderation.data, data) return 'Group photo has been unlocked' - end + end end - + local function lock_group_flood(msg, data, target) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end local group_flood_lock = data[tostring(target)]['settings']['flood'] @@ -180,11 +188,11 @@ local function lock_group_flood(msg, data, target) data[tostring(target)]['settings']['flood'] = 'yes' save_data(_config.moderation.data, data) return 'Group flood has been locked' - end + end end - + local function unlock_group_flood(msg, data, target) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only!" end local group_flood_lock = data[tostring(target)]['settings']['flood'] @@ -194,71 +202,301 @@ local function unlock_group_flood(msg, data, target) data[tostring(target)]['settings']['flood'] = 'no' save_data(_config.moderation.data, data) return 'Group flood has been unlocked' - end + end +end + +local function lock_group_arabic(msg, data, target) + if not is_admin1(msg) then + return "For admins 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_admin1(msg) then + return "For admins only!" + end + local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] + if group_arabic_lock == 'no' then + return 'Arabic/Persian is already unlocked' + else + data[tostring(target)]['settings']['lock_arabic'] = 'no' + save_data(_config.moderation.data, data) + return 'Arabic/Persian has been unlocked' + end +end + +local function lock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'yes' then + return 'RTL char. in names is already locked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'yes' + save_data(_config.moderation.data, data) + return 'RTL char. in names has been locked' + end +end + +local function unlock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'no' then + return 'RTL char. in names is already unlocked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'no' + save_data(_config.moderation.data, data) + return 'RTL char. in names has been unlocked' + end end + +local function lock_group_links(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'yes' then + return 'Link posting is already locked' + else + data[tostring(target)]['settings']['lock_link'] = 'yes' + save_data(_config.moderation.data, data) + return 'Link posting has been locked' + end +end + +local function unlock_group_links(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'no' then + return 'Link posting is not locked' + else + data[tostring(target)]['settings']['lock_link'] = 'no' + save_data(_config.moderation.data, data) + return 'Link posting has been unlocked' + end +end + +local function lock_group_spam(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'yes' then + return 'SuperGroup spam is already locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'yes' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been locked' + end +end + +local function unlock_group_spam(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'no' then + return 'SuperGroup spam is not locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been unlocked' + end +end + +local function lock_group_rtl(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'yes' then + return 'RTL char. in names is already locked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'yes' + save_data(_config.moderation.data, data) + return 'RTL char. in names has been locked' + end +end + +local function unlock_group_rtl(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'no' then + return 'RTL char. in names is already unlocked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'no' + save_data(_config.moderation.data, data) + return 'RTL char. in names has been unlocked' + end +end + +local function lock_group_sticker(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'yes' then + return 'Sticker posting is already locked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'yes' + save_data(_config.moderation.data, data) + return 'Sticker posting has been locked' + end +end + +local function unlock_group_sticker(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'no' then + return 'Sticker posting is already unlocked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'no' + save_data(_config.moderation.data, data) + return 'Sticker posting has been unlocked' + end +end + +local function set_public_membermod(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_public_lock = data[tostring(target)]['settings']['public'] + if group_public_lock == 'yes' then + return 'Group is already public' + else + data[tostring(target)]['settings']['public'] = 'yes' + save_data(_config.moderation.data, data) + end + return 'SuperGroup is now: public' +end + +local function unset_public_membermod(msg, data, target) + if not is_admin1(msg) then + return "For admins only!" + end + local group_public_lock = data[tostring(target)]['settings']['public'] + if group_public_lock == 'no' then + return 'Group is not public' + else + data[tostring(target)]['settings']['public'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup is now: not public' + 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 + if not is_admin1(msg) then return "For admins only!" end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['public'] then + data[tostring(target)]['settings']['public'] = 'no' + 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 - return text + local text = "Group settings for "..target..":\nLock group name : "..settings.lock_name.."\nLock group photo : "..settings.lock_photo.."\nLock group member : "..settings.lock_member.."\nPublic: "..settings.public 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 +-- show SuperGroup settings +local function show_super_group_settings(msg, data, target) + local data = load_data(_config.moderation.data, data) + if not is_admin1(msg) then + return "For admins only!" end - send_large_msg(receiver, text) - local file = io.open("./groups/lists/"..result.id.."memberlist.txt", "w") - file:write(text) - file:flush() - file:close() + if data[tostring(msg.to.id)]['settings'] then + if not data[tostring(msg.to.id)]['settings']['public'] then + data[tostring(msg.to.id)]['settings']['public'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_rtl'] then + data[tostring(target)]['settings']['lock_rtl'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_member'] then + data[tostring(target)]['settings']['lock_member'] = 'no' + end + end + local settings = data[tostring(target)]['settings'] + local text = "SuperGroup settings for "..target..":\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict + return text end - -local function returnidsfile(cb_extra, success, result) + +local function returnids(cb_extra, success, result) + local i = 1 local receiver = cb_extra.receiver - local chat_id = "chat#id"..result.id + local chat_id = "chat#id"..result.peer_id local chatname = result.print_name - local text = 'Users in '..string.gsub(chatname,"_"," ")..' ('..result.id..'):'..'\n'..'' + local text = 'Users in '..string.gsub(chatname,"_"," ")..' (ID: '..result.peer_id..'):\n\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 + if v.print_name then + local username = "" + text = text ..i..' - '.. string.gsub(v.print_name,"_"," ") .. " [" .. v.peer_id .. "] \n\n" + i = i + 1 + 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) + local file = io.open("./groups/lists/"..result.peer_id.."memberlist.txt", "w") + file:write(text) + file:flush() + file:close() end - + +local function cb_user_info(cb_extra, success, result) + local receiver = cb_extra.receiver + if result.first_name then + first_name = result.first_name:gsub("_", " ") + else + first_name = "None" + end + if result.last_name then + last_name = result.last_name:gsub("_", " ") + else + last_name = "None" + end + if result.username then + username = "@"..result.username + else + username = "@[none]" + end + text = "User Info:\n\nID: "..result.peer_id.."\nFirst: "..first_name.."\nLast: "..last_name.."\nUsername: "..username + send_large_msg(receiver, text) +end + local function admin_promote(msg, admin_id) - if not is_sudo(msg) then + 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.' + 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_id..' 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) @@ -267,125 +505,125 @@ local function admin_demote(msg, admin_id) 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.' + 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 + local admins = 'admins' + if not data[tostring(admins)] then + data[tostring(admins)] = {} + save_data(_config.moderation.data, data) + end + local message = 'List of global 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 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 + if data[tostring(v)] then + if data[tostring(v)]['settings'] then + 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'] + group_link = data[tostring(v)]['settings']['set_link'] + end + message = message .. '- '.. name .. ' (' .. v .. ') ['..group_owner..'] \n {'..group_link.."}\n" + end 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 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']) + 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_link = "No link" - if data[tostring(v)]['settings']['set_link'] then + 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 + 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) + 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.') + return send_large_msg(receiver, '@'..member_username..' is already an 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.') + 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 + if not data['admins'] then + data['admins'] = {} save_data(_config.moderation.data, data) - return send_large_msg(receiver, 'Admin '..member_username..' has been demoted.') + end + if not data['admins'][tostring(member_id)] then + send_large_msg(receiver, "@"..member_username..' is not an admin.') + return + end + data['admins'][tostring(member_id)] = nil + save_data(_config.moderation.data, data) + 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 @@ -395,7 +633,7 @@ local function username_id(cb_extra, success, result) vusername = v.username if vusername == member then member_username = member - member_id = v.id + member_id = v.peer_id if mod_cmd == 'addadmin' then return admin_user_promote(receiver, member_username, member_id) elseif mod_cmd == 'removeadmin' then @@ -406,71 +644,114 @@ local function username_id(cb_extra, success, result) send_large_msg(receiver, text) end -local function set_log_group(msg) - if not is_admin(msg) then - return +local function res_user_support(cb_extra, success, result) + local receiver = cb_extra.receiver + local get_cmd = cb_extra.get_cmd + local support_id = result.peer_id + if get_cmd == 'addsupport' then + support_add(support_id) + send_large_msg(receiver, "User ["..support_id.."] has been added to the support team") + elseif get_cmd == 'removesupport' then + support_remove(support_id) + send_large_msg(receiver, "User ["..support_id.."] has been removed from the support team") + end +end + +local function set_log_group(target, data) + if not is_admin1(msg) then + return end - local log_group = data[tostring(groups)][tostring(msg.to.id)]['log_group'] + local log_group = data[tostring(target)]['log_group'] if log_group == 'yes' then return 'Log group is already set' else - data[tostring(groups)][tostring(msg.to.id)]['log_group'] = 'yes' + data[tostring(target)]['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 + if not is_admin1(msg) then + return end - local log_group = data[tostring(groups)][tostring(msg.to.id)]['log_group'] + local log_group = data[tostring(target)]['log_group'] if log_group == 'no' then - return 'Log group is already disabled' + return 'Log group is not set' else - data[tostring(groups)][tostring(msg.to.id)]['log_group'] = 'no' + data[tostring(target)]['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) +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] == 'log' and is_owner(msg) then + local receiver = get_receiver(msg) + savelog(msg.to.id, "log file created by owner/support/admin") + send_document(receiver,"./groups/logs/"..msg.to.id.."log.txt", ok_cb, false) + end - if matches[1] == 'who' and is_momod(msg) then + if matches[1] == 'who' and msg.to.type == 'chat' 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}) + chat_info(receiver, returnids, {receiver=receiver}) + local file = io.open("./groups/lists/"..msg.to.id.."memberlist.txt", "r") + text = file:read("*a") + send_large_msg(receiver,text) + file:close() 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}) + send_document("chat#id"..msg.to.id,"./groups/lists/"..msg.to.id.."memberlist.txt", ok_cb, false) end + if matches[1] == 'whois' and is_momod(msg) then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + user_info(user_id, cb_user_info, {receiver = receiver}) + end + + if not is_sudo(msg) and not is_realm(msg) and is_admin1(msg) then + return + end + if matches[1] == 'creategroup' and matches[2] then + if not is_momod(msg) then + return + end + if not is_sudo(msg) or is_admin1(msg) and is_realm(msg) then + return "You cant create groups!" + end 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 + + --[[ Experimental + if matches[1] == 'createsuper' and matches[2] then + if not is_sudo(msg) or is_admin1(msg) and is_realm(msg) then + return "You cant create groups!" end + group_name = matches[2] + group_type = 'super_group' + return create_group(msg) + end]] if matches[1] == 'createrealm' and matches[2] then + if not is_sudo(msg) or not is_admin1(msg) and is_realm(msg) then + return "You cant create groups!" + end group_name = matches[2] group_type = 'realm' return create_realm(msg) @@ -478,118 +759,188 @@ function run(msg, matches) 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 + if matches[1] == 'setabout' and matches[2] == 'group' and is_realm(msg) then + local target = matches[3] + local about = matches[4] + return set_description(msg, data, target, about) + end + if matches[1] == 'setabout' and matches[2] == 'sgroup'and is_realm(msg) then + local channel = 'channel#id'..matches[3] + local about_text = matches[4] + local data_cat = 'description' + local target = matches[3] + channel_set_about(channel, about_text, ok_cb, false) + data[tostring(target)][data_cat] = about_text + save_data(_config.moderation.data, data) + return "Description has been set for ["..matches[2]..']' + 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 + 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 + if matches[2] == 'arabic' then + return lock_group_arabic(msg, data, target) + end + if matches[3] == 'links' then + return lock_group_links(msg, data, target) + end + if matches[3] == 'spam' then + + return lock_group_spam(msg, data, target) + end + if matches[3] == 'rtl' then + return unlock_group_rtl(msg, data, target) + end + if matches[3] == 'sticker' then + return lock_group_sticker(msg, data, target) + end + end + if matches[1] == 'unlock' then + 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 + if matches[3] == 'arabic' then + return unlock_group_arabic(msg, data, target) + end + if matches[3] == 'links' then + return unlock_group_links(msg, data, target) + end + if matches[3] == 'spam' then + return unlock_group_spam(msg, data, target) + end + if matches[3] == 'rtl' then + return unlock_group_rtl(msg, data, target) + end + if matches[3] == 'sticker' then + return unlock_group_sticker(msg, data, target) + end + end + + if matches[1] == 'settings' and matches[2] == 'group' and data[tostring(matches[3])]['settings'] then + local target = matches[3] + text = show_group_settingsmod(msg, target) + return text.."\nID: "..target.."\n" end - if matches[1] == 'settings' and data[tostring(matches[2])]['settings'] then - local target = matches[2] - return show_group_settings(msg, data, target) + if matches[1] == 'settings' and matches[2] == 'sgroup' and data[tostring(matches[3])]['settings'] then + local target = matches[3] + text = show_supergroup_settingsmod(msg, target) + return text.."\nID: "..target.."\n" 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 + if matches[1] == 'setname' and is_realm(msg) then + local settings = data[tostring(matches[2])]['settings'] + 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_admin1(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] + local chat_to_rename = 'chat#id'..matches[2] + local channel_to_rename = 'channel#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.."]") + rename_channel(channel_to_rename, group_name_set, ok_cb, false) + savelog(matches[3], "Group { "..group_name_set.." } 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] == 'set' then + if matches[2] == 'loggroup' and is_sudo(msg) then + local target = msg.to.peer_id + savelog(msg.to.peer_id, name_log.." ["..msg.from.id.."] set as log group") + return set_log_group(target, data) + end + end + if matches[1] == 'rem' then + if matches[2] == 'loggroup' and is_sudo(msg) then + local target = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set as log group") + return unset_log_group(target, data) + end + end]] + if matches[1] == 'kill' and matches[2] == 'chat' and matches[3] then + if not is_admin1(msg) then + return + 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' and matches[3] then + if not is_admin1(msg) then + return + 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] == 'rem' and matches[2] then + -- Group configuration removal + data[tostring(matches[2])] = 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(matches[2])] = nil + save_data(_config.moderation.data, data) + send_large_msg(receiver, 'Chat '..matches[2]..' removed') + end + if matches[1] == 'chat_add_user' then if not msg.service then - return "Are you trying to troll me?" + return 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) + if not is_admin1(msg) and is_realm(msg) then + chat_del_user(chat, user, ok_cb, true) end end if matches[1] == 'addadmin' then @@ -598,7 +949,7 @@ function run(msg, matches) print("user "..admin_id.." has been promoted as admin") return admin_promote(msg, admin_id) else - local member = string.gsub(matches[2], "@", "") + local member = string.gsub(matches[2], "@", "") local mod_cmd = "addadmin" chat_info(receiver, username_id, {mod_cmd= mod_cmd, receiver=receiver, member=member}) end @@ -614,74 +965,112 @@ function run(msg, matches) chat_info(receiver, username_id, {mod_cmd= mod_cmd, receiver=receiver, member=member}) end end + if matches[1] == 'support' and matches[2] then + if string.match(matches[2], '^%d+$') then + local support_id = matches[2] + print("User "..support_id.." has been added to the support team") + support_add(support_id) + return "User ["..support_id.."] has been added to the support team" + else + local member = string.gsub(matches[2], "@", "") + local receiver = get_receiver(msg) + local get_cmd = "addsupport" + resolve_username(member, res_user_support, {get_cmd = get_cmd, receiver = receiver}) + end + end + if matches[1] == '-support' then + if string.match(matches[2], '^%d+$') then + local support_id = matches[2] + print("User "..support_id.." has been removed from the support team") + support_remove(support_id) + return "User ["..support_id.."] has been removed from the support team" + else + local member = string.gsub(matches[2], "@", "") + local receiver = get_receiver(msg) + local get_cmd = "removesupport" + resolve_username(member, res_user_support, {get_cmd = get_cmd, receiver = receiver}) + end + end if matches[1] == 'type'then - local group_type = get_group_type(msg) + local group_type = get_group_type(msg) return group_type end - if matches[1] == 'list' and matches[2] == 'admins' then - return admin_list(msg) + if matches[1] == 'list' then + if matches[2] == 'admins' then + return admin_list(msg) + end + -- if matches[2] == 'support' and not matches[2] then + -- return support_list() + -- end 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 + if msg.to.type == 'chat' or msg.to.type == 'channel' then + groups_list(msg) + send_document("chat#id"..msg.to.id, "./groups/lists/groups.txt", ok_cb, false) + send_document("channel#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 + if msg.to.type == 'chat' or msg.to.type == 'channel' then + realms_list(msg) + send_document("chat#id"..msg.to.id, "./groups/lists/realms.txt", ok_cb, false) + send_document("channel#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) + 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 resolve_username(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 (.+)$", + "^[#!/](creategroup) (.*)$", + "^[#!/](createsuper) (.*)$", + "^[#!/](createrealm) (.*)$", + "^[#!/](setabout) (%d+) (.*)$", + "^[#!/](setrules) (%d+) (.*)$", + "^[#!/](setname) (.*)$", + "^[#!/](setgpname) (%d+) (.*)$", + "^[#!/](setname) (%d+) (.*)$", + "^[#!/](lock) (%d+) (.*)$", + "^[#!/](unlock) (%d+) (.*)$", + "^[#!/](mute) (%d+)$", + "^[#!/](unmute) (%d+)$", + "^[#!/](settings) (.*) (%d+)$", + "^[#!/](wholist)$", + "^[#!/](who)$", + "^[#!/]([Ww]hois) (.*)", + "^[#!/](type)$", + "^[#!/](kill) (chat) (%d+)$", + "^[#!/](kill) (realm) (%d+)$", + "^[#!/](rem) (%d+)$", + "^[#!/](addadmin) (.*)$", -- sudoers only + "^[#!/](removeadmin) (.*)$", -- sudoers only + "[#!/ ](support)$", + "^[#!/](support) (.*)$", + "^[#!/](-support) (.*)$", + "^[#!/](list) (.*)$", + "^[#!/](log)$", + "^[#!/](help)$", + "^!!tgservice (.+)$", }, run = run } end - - diff --git a/plugins/invite.lua b/plugins/invite.lua index 300f89f..b9df272 100644 --- a/plugins/invite.lua +++ b/plugins/invite.lua @@ -1,39 +1,42 @@ do -local function callbackres(extra, success, result) -- Callback for res_user in line 27 - local user = 'user#id'..result.id +local function callbackres(extra, success, result) + local user = 'user#id'..result.peer_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 + local channel = 'channel#id'..extra.chatid + if is_banned(result.id, extra.chatid) then + send_large_msg(chat, 'User is banned.') + send_large_msg(channel, 'User is banned.') + elseif is_gbanned(result.id) then send_large_msg(chat, 'User is globaly banned.') + send_large_msg(channel, 'User is globaly banned.') else - chat_add_user(chat, user, ok_cb, false) -- Add user on chat + chat_add_user(chat, user, ok_cb, false) + channel_invite(channel, user, ok_cb, false) end end function run(msg, matches) local data = load_data(_config.moderation.data) + if not is_momod(msg) then + return + end + if not is_admin1(msg) then -- For admins only ! + return 'Only admins can invite.' + end if not is_realm(msg) then - if data[tostring(msg.to.id)]['settings']['lock_member'] == 'yes' and not is_admin(msg) then + if data[tostring(msg.to.id)]['settings']['lock_member'] == 'yes' and not is_admin1(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) + if msg.to.type ~= 'chat' or msg.to.type ~= 'channel' then + local cbres_extra = {chatid = msg.to.id} + local username = matches[1] + local username = username:gsub("@","") + resolve_username(username, callbackres, cbres_extra) + end end return { patterns = { - "^[!/]invite (.*)$" + "^[#!/]invite (.*)$" }, run = run } diff --git a/plugins/leave_ban.lua b/plugins/leave_ban.lua index 6a69a7f..828da06 100644 --- a/plugins/leave_ban.lua +++ b/plugins/leave_ban.lua @@ -1,21 +1,21 @@ 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 + 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 + 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 + 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 { diff --git a/plugins/msg_checks.lua b/plugins/msg_checks.lua new file mode 100644 index 0000000..17639db --- /dev/null +++ b/plugins/msg_checks.lua @@ -0,0 +1,283 @@ +--Begin msg_checks.lua +--Begin pre_process function +local function pre_process(msg) +-- Begin 'RondoMsgChecks' text checks by @rondoozle +if is_chat_msg(msg) or is_super_group(msg) then + if msg and not is_momod(msg) and not is_whitelisted(msg.from.id) then --if regular user + local data = load_data(_config.moderation.data) + local print_name = user_print_name(msg.from):gsub("‮", "") -- get rid of rtl in names + local name_log = print_name:gsub("_", " ") -- name for log + local to_chat = msg.to.type == 'chat' + if data[tostring(msg.to.id)] and data[tostring(msg.to.id)]['settings'] then + settings = data[tostring(msg.to.id)]['settings'] + end + if settings.lock_arabic then + lock_arabic = settings.lock_arabic + else + lock_arabic = 'no' + end + if settings.lock_rtl then + lock_rtl = settings.lock_rtl + else + lock_rtl = 'no' + end + if settings.lock_link then + lock_link = settings.lock_link + else + lock_link = 'no' + end + if settings.lock_member then + lock_member = settings.lock_member + else + lock_member = 'no' + end + if settings.lock_spam then + lock_spam = settings.lock_spam + else + lock_spam = 'no' + end + if settings.lock_sticker then + lock_sticker = settings.lock_sticker + else + lock_sticker = 'no' + end + if settings.lock_contacts then + lock_contacts = settings.lock_contacts + else + lock_contacts = 'no' + end + if settings.strict then + strict = settings.strict + else + strict = 'no' + end + if msg and not msg.service and is_muted(msg.to.id, 'All: yes') or is_muted_user(msg.to.id, msg.from.id) and not msg.service then + delete_msg(msg.id, ok_cb, false) + if to_chat then + -- kick_user(msg.from.id, msg.to.id) + end + end + if msg.text then -- msg.text checks + local _nl, ctrl_chars = string.gsub(msg.text, '%c', '') + local _nl, real_digits = string.gsub(msg.text, '%d', '') + if lock_spam == "yes" and string.len(msg.text) > 2049 or ctrl_chars > 40 or real_digits > 2000 then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + delete_msg(msg.id, ok_cb, false) + kick_user(msg.from.id, msg.to.id) + end + end + local is_link_msg = msg.text:match("[Tt][Ee][Ll][Ee][Gg][Rr][Aa][Mm].[Mm][Ee]/") or msg.text:match("[Tt][Ll][Gg][Rr][Mm].[Mm][Ee]/") + local is_bot = msg.text:match("?[Ss][Tt][Aa][Rr][Tt]=") + if is_link_msg and lock_link == "yes" and not is_bot then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_squig_msg = msg.text:match("[\216-\219][\128-\191]") + if is_squig_msg and lock_arabic == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local print_name = msg.from.print_name + local is_rtl = print_name:match("‮") or msg.text:match("‮") + if is_rtl and lock_rtl == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + if is_muted(msg.to.id, "Text: yes") and msg.text and not msg.media and not msg.service then + delete_msg(msg.id, ok_cb, false) + if to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + end + if msg.media then -- msg.media checks + if msg.media.title then + local is_link_title = msg.media.title:match("[Tt][Ee][Ll][Ee][Gg][Rr][Aa][Mm].[Mm][Ee]/") or msg.media.title:match("[Tt][Ll][Gg][Rr][Mm].[Mm][Ee]/") + if is_link_title and lock_link == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_squig_title = msg.media.title:match("[\216-\219][\128-\191]") + if is_squig_title and lock_arabic == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + end + if msg.media.description then + local is_link_desc = msg.media.description:match("[Tt][Ee][Ll][Ee][Gg][Rr][Aa][Mm].[Mm][Ee]/") or msg.media.description:match("[Tt][Ll][Gg][Rr][Mm].[Mm][Ee]/") + if is_link_desc and lock_link == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_squig_desc = msg.media.description:match("[\216-\219][\128-\191]") + if is_squig_desc and lock_arabic == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + end + if msg.media.caption then -- msg.media.caption checks + local is_link_caption = msg.media.caption:match("[Tt][Ee][Ll][Ee][Gg][Rr][Aa][Mm].[Mm][Ee]/") or msg.media.caption:match("[Tt][Ll][Gg][Rr][Mm].[Mm][Ee]/") + if is_link_caption and lock_link == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_squig_caption = msg.media.caption:match("[\216-\219][\128-\191]") + if is_squig_caption and lock_arabic == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_username_caption = msg.media.caption:match("^@[%a%d]") + if is_username_caption and lock_link == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + if lock_sticker == "yes" and msg.media.caption:match("sticker.webp") then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + end + if msg.media.type:match("contact") and lock_contacts == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_photo_caption = msg.media.caption and msg.media.caption:match("photo")--".jpg", + if is_muted(msg.to.id, 'Photo: yes') and msg.media.type:match("photo") or is_photo_caption and not msg.service then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + -- kick_user(msg.from.id, msg.to.id) + end + end + local is_gif_caption = msg.media.caption and msg.media.caption:match(".mp4") + if is_muted(msg.to.id, 'Gifs: yes') and is_gif_caption and msg.media.type:match("document") and not msg.service then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + -- kick_user(msg.from.id, msg.to.id) + end + end + if is_muted(msg.to.id, 'Audio: yes') and msg.media.type:match("audio") and not msg.service then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_video_caption = msg.media.caption and msg.media.caption:lower(".mp4","video") + if is_muted(msg.to.id, 'Video: yes') and msg.media.type:match("video") and not msg.service then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + if is_muted(msg.to.id, 'Documents: yes') and msg.media.type:match("document") and not msg.service then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + end + if msg.fwd_from then + if msg.fwd_from.title then + local is_link_title = msg.fwd_from.title:match("[Tt][Ee][Ll][Ee][Gg][Rr][Aa][Mm].[Mm][Ee]/") or msg.fwd_from.title:match("[Tt][Ll][Gg][Rr][Mm].[Mm][Ee]/") + if is_link_title and lock_link == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + local is_squig_title = msg.fwd_from.title:match("[\216-\219][\128-\191]") + if is_squig_title and lock_arabic == "yes" then + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + kick_user(msg.from.id, msg.to.id) + end + end + end + if is_muted_user(msg.to.id, msg.fwd_from.peer_id) then + delete_msg(msg.id, ok_cb, false) + end + end + if msg.service then -- msg.service checks + local action = msg.action.type + if action == 'chat_add_user_link' then + local user_id = msg.from.id + local _nl, ctrl_chars = string.gsub(msg.text, '%c', '') + if string.len(msg.from.print_name) > 70 or ctrl_chars > 40 and lock_group_spam == 'yes' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] joined and Service Msg deleted (#spam name)") + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] joined and kicked (#spam name)") + kick_user(msg.from.id, msg.to.id) + end + end + local print_name = msg.from.print_name + local is_rtl_name = print_name:match("‮") + if is_rtl_name and lock_rtl == "yes" then + savelog(msg.to.id, name_log.." User ["..msg.from.id.."] joined and kicked (#RTL char in name)") + kick_user(user_id, msg.to.id) + end + if lock_member == 'yes' then + savelog(msg.to.id, name_log.." User ["..msg.from.id.."] joined and kicked (#lockmember)") + kick_user(user_id, msg.to.id) + delete_msg(msg.id, ok_cb, false) + end + end + if action == 'chat_add_user' and not is_momod2(msg.from.id, msg.to.id) then + local user_id = msg.action.user.id + if string.len(msg.action.user.print_name) > 70 and lock_group_spam == 'yes' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added ["..user_id.."]: Service Msg deleted (#spam name)") + delete_msg(msg.id, ok_cb, false) + if strict == "yes" or to_chat then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added ["..user_id.."]: added user kicked (#spam name) ") + delete_msg(msg.id, ok_cb, false) + kick_user(msg.from.id, msg.to.id) + end + end + local print_name = msg.action.user.print_name + local is_rtl_name = print_name:match("‮") + if is_rtl_name and lock_rtl == "yes" then + savelog(msg.to.id, name_log.." User ["..msg.from.id.."] added ["..user_id.."]: added user kicked (#RTL char in name)") + kick_user(user_id, msg.to.id) + end + if msg.to.type == 'channel' and lock_member == 'yes' then + savelog(msg.to.id, name_log.." User ["..msg.from.id.."] added ["..user_id.."]: added user kicked (#lockmember)") + kick_user(user_id, msg.to.id) + delete_msg(msg.id, ok_cb, false) + end + end + end + end +end +-- End 'RondoMsgChecks' text checks by @Rondoozle + return msg +end +--End pre_process function +return { + patterns = {}, + pre_process = pre_process +} +--End msg_checks.lua +--By @Rondoozle \ No newline at end of file diff --git a/plugins/onservice.lua b/plugins/onservice.lua index 5463399..160602e 100644 --- a/plugins/onservice.lua +++ b/plugins/onservice.lua @@ -1,20 +1,21 @@ 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 +local bot_id = our_id +local receiver = get_receiver(msg) + if matches[1] == 'leave' and is_admin1(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) + leave_channel(receiver, ok_cb, false) + elseif msg.service and msg.action.type == "chat_add_user" and msg.action.user.id == tonumber(bot_id) and not is_admin1(msg) then + send_large_msg(receiver, 'This is not one of my groups.', ok_cb, false) + chat_del_user(receiver, 'user#id'..bot_id, ok_cb, false) + leave_channel(receiver, ok_cb, false) end end return { patterns = { - "^[!/](leave)$", + "^[#!/](leave)$", "^!!tgservice (.+)$", }, run = run diff --git a/plugins/owners.lua b/plugins/owners.lua index af2ac57..204eee1 100644 --- a/plugins/owners.lua +++ b/plugins/owners.lua @@ -1,5 +1,3 @@ - - 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'] @@ -80,18 +78,210 @@ local function unlock_group_photomod(msg, data, target) end end +local function lock_group_arabic(msg, data, target) + 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) + local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] + if group_arabic_lock == 'no' then + return 'Arabic/Persian is already unlocked' + else + data[tostring(target)]['settings']['lock_arabic'] = 'no' + save_data(_config.moderation.data, data) + return 'Arabic/Persian has been unlocked' + end +end + +local function lock_group_links(msg, data, target) + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'yes' then + return 'Link posting is already locked' + else + data[tostring(target)]['settings']['lock_link'] = 'yes' + save_data(_config.moderation.data, data) + return 'Link posting has been locked' + end +end + +local function unlock_group_links(msg, data, target) + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'no' then + return 'Link posting is not locked' + else + data[tostring(target)]['settings']['lock_link'] = 'no' + save_data(_config.moderation.data, data) + return 'Link posting has been unlocked' + end +end + +local function lock_group_spam(msg, data, target) + + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'yes' then + return 'SuperGroup spam is already locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'yes' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been locked' + end +end + +local function unlock_group_spam(msg, data, target) + + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'no' then + return 'SuperGroup spam is not locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been unlocked' + end +end + +local function lock_group_sticker(msg, data, target) + + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'yes' then + return 'Sticker posting is already locked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'yes' + save_data(_config.moderation.data, data) + return 'Sticker posting has been locked' + end +end + +local function unlock_group_sticker(msg, data, target) + + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'no' then + return 'Sticker posting is already unlocked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'no' + save_data(_config.moderation.data, data) + return 'Sticker posting has been unlocked' + end +end + +local function lock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'yes' then + return 'Contact posting is already locked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'yes' + save_data(_config.moderation.data, data) + return 'Contact posting has been locked' + end +end + +local function unlock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'no' then + return 'Contact posting is already unlocked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'no' + save_data(_config.moderation.data, data) + return 'Contact posting has been unlocked' + end +end + +local function enable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['strict'] + if strict == 'yes' then + return 'Settings are already strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'yes' + save_data(_config.moderation.data, data) + return 'Settings will be strictly enforced' + end +end + +local function disable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['strict'] + if strict == 'no' then + return 'Settings will not be strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'no' + save_data(_config.moderation.data, data) + return 'Settings are not strictly enforced' + end +end + +-- Show group settings 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']) + 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 bots_protection = "Yes" + if data[tostring(target)]['settings']['lock_bots'] then + bots_protection = data[tostring(target)]['settings']['lock_bots'] + end + local leave_ban = "no" + if data[tostring(target)]['settings']['leave_ban'] then + leave_ban = data[tostring(target)]['settings']['leave_ban'] + end + local public = "no" + if data[tostring(target)]['settings'] then + if data[tostring(target)]['settings']['public'] then + public = data[tostring(target)]['settings']['public'] + 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.."\nLock group leave : "..leave_ban.."\nflood sensitivity : "..NUM_MSG_MAX.."\nBot protection : "..bots_protection.."\nPublic: "..public + return text +end + +-- Show SuperGroup settings +local function show_super_group_settings(msg, data, target) + 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 + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['public'] then + data[tostring(target)]['settings']['public'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_rtl'] then + data[tostring(target)]['settings']['lock_rtl'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_member'] then + data[tostring(target)]['settings']['lock_member'] = 'no' + 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 + local text = "SuperGroup settings for "..target..":\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict return text end @@ -112,7 +302,9 @@ local function set_description(target, about) end local function run(msg, matches) - if msg.to.type ~= 'chat' then + if msg.to.type == 'user' then + local print_name = user_print_name(msg.from):gsub("‮", "") + local name = print_name:gsub("_", " ") local chat_id = matches[1] local receiver = get_receiver(msg) local data = load_data(_config.moderation.data) @@ -131,6 +323,7 @@ local function run(msg, matches) 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] @@ -143,10 +336,10 @@ local function run(msg, matches) 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 @@ -157,11 +350,11 @@ local function run(msg, matches) 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) + kick_user(matches[3], chat_id) 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 @@ -171,7 +364,6 @@ local function run(msg, matches) 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 @@ -181,7 +373,6 @@ local function run(msg, matches) 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 @@ -191,10 +382,18 @@ local function run(msg, matches) 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") + channel_set_about(receiver, about_text, ok_cb, false) + return "About has been cleaned" end + if matches[3] == 'mutelist' then + chat_id = string.match(matches[1], '^%d+$') + local hash = 'mute_user:'..chat_id + redis:del(hash) + return "Mutelist Cleaned" + 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" @@ -205,61 +404,134 @@ local function run(msg, matches) 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] + local group_type = data[tostring(matches[1])]['group_type'] 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 + if matches[3] == 'arabic' then + savelog(matches[1], name.." ["..msg.from.id.."] locked arabic ") + return lock_group_arabic(msg, data, target) + end + if matches[3] == 'links' then + savelog(matches[1], name.." ["..msg.from.id.."] locked links ") + return lock_group_links(msg, data, target) + end + if matches[3] == 'spam' then + savelog(matches[1], name.." ["..msg.from.id.."] locked spam ") + return lock_group_spam(msg, data, target) + end + if matches[3] == 'rtl' then + savelog(matches[1], name.." ["..msg.from.id.."] locked RTL chars. in names") + return unlock_group_rtl(msg, data, target) + end + if matches[3] == 'sticker' then + savelog(matches[1], name.." ["..msg.from.id.."] locked sticker") + return lock_group_sticker(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] + local group_type = data[tostring(matches[1])]['group_type'] 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 + if matches[3] == 'arabic' then + savelog(matches[1], name.." ["..msg.from.id.."] unlocked arabic ") + return unlock_group_arabic(msg, data, target) + end + if matches[3] == 'links' and group_type == "SuperGroup" then + savelog(matches[1], name.." ["..msg.from.id.."] unlocked links ") + return unlock_group_links(msg, data, target) + end + if matches[3] == 'spam' and group_type == "SuperGroup" then + savelog(matches[1], name.." ["..msg.from.id.."] unlocked spam ") + return unlock_group_spam(msg, data, target) + end + if matches[3] == 'rtl' then + savelog(matches[1], name.." ["..msg.from.id.."] unlocked RTL chars. in names") + return unlock_group_rtl(msg, data, target) + end + if matches[3] == 'sticker' and group_type == "SuperGroup" then + savelog(matches[1], name.." ["..msg.from.id.."] unlocked sticker") + return unlock_group_sticker(msg, data, target) + end + if matches[3] == 'contacts' and group_type == "SuperGroup" then + savelog(matches[1], name_log.." ["..msg.from.id.."] locked contact posting") + return lock_group_contacts(msg, data, target) + end + if matches[3] == 'strict' and group_type == "SuperGroup" then + savelog(matches[1], name_log.." ["..msg.from.id.."] locked enabled strict settings") + return enable_strict_rules(msg, data, target) + end end - if matches[2] == 'new' then + + if matches[2] == 'new' then if matches[3] == 'link' then + local group_type = data[tostring(matches[1])]['group_type'] 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 + local function callback_grouplink (extra , success, result) + local receiver = 'chat#id'..matches[1] + if success == 0 then + send_large_msg(receiver, '*Error: Failed to retrieve link* \nReason: Not creator.') + end + data[tostring(matches[1])]['settings']['set_link'] = result + save_data(_config.moderation.data, data) + return + end + local function callback_superlink (extra , success, result) + vardump(result) + local receiver = 'channel#id'..matches[1] + local user = extra.user + if success == 0 then + data[tostring(matches[1])]['settings']['set_link'] = nil + save_data(_config.moderation.data, data) + return send_large_msg(user, '*Error: Failed to retrieve link* \nReason: Not creator.\n\nIf you have the link, please use /setlink to set it') + else + data[tostring(matches[1])]['settings']['set_link'] = result + save_data(_config.moderation.data, data) + return send_large_msg(user, "Created a new link") + end + end + if group_type == "Group" then + local receiver = 'chat#id'..matches[1] + savelog(matches[1], name.." ["..msg.from.id.."] created/revoked group link ") + export_chat_link(receiver, callback_grouplink, false) + return "Created a new new link ! \n owner can get it by /owners "..matches[1].." get link" + elseif group_type == "SuperGroup" then + local receiver = 'channel#id'..matches[1] + local user = 'user#id'..msg.from.id + savelog(matches[1], name.." ["..msg.from.id.."] attempted to create a new SuperGroup link") + export_channel_link(receiver, callback_superlink, {user = user}) + end + end + end + if matches[2] == 'get' then if matches[3] == 'link' then if not is_owner2(msg.from.id, chat_id) then @@ -269,18 +541,50 @@ local function run(msg, matches) 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) + + if matches[1] == 'changeabout' and matches[2] then + if not is_owner2(msg.from.id, matches[2]) then + return "You are not the owner of this group" + end + local group_type = data[tostring(matches[2])]['group_type'] + if group_type == "Group" or group_type == "Realm" 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) + elseif group_type == "SuperGroup" then + local channel = 'channel#id'..matches[2] + local about_text = matches[3] + local data_cat = 'description' + local target = matches[2] + channel_set_about(channel, about_text, ok_cb, false) + data[tostring(target)][data_cat] = about_text + save_data(_config.moderation.data, data) + savelog(matches[2], name.." ["..msg.from.id.."] has changed SuperGroup description to ["..matches[3].."]") + return "Description has been set for ["..matches[2]..']' + end end + + if matches[1] == 'viewsettings' and data[tostring(matches[2])]['settings'] then + if not is_owner2(msg.from.id, matches[2]) then + return "You are not the owner of this group" + end + local target = matches[2] + local group_type = data[tostring(matches[2])]['group_type'] + if group_type == "Group" or group_type == "Realm" then + savelog(matches[2], name.." ["..msg.from.id.."] requested group settings ") + return show_group_settings(msg, data, target) + elseif group_type == "SuperGroup" then + savelog(matches[2], name.." ["..msg.from.id.."] requested SuperGroup settings ") + return show_super_group_settings(msg, data, target) + end + end + if matches[1] == 'changerules' and is_owner2(msg.from.id, matches[2]) then local rules = matches[3] local target = matches[2] @@ -291,27 +595,31 @@ local function run(msg, matches) 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 + local group_name_set = data[tostring(matches[2])]['settings']['set_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) + local chat_to_rename = 'chat#id'..matches[2] + local channel_to_rename = 'channel#id'..matches[2] + savelog(matches[2], "Group name changed to [ "..new_name.." ] by "..name.." ["..msg.from.id.."]") + rename_chat(chat_to_rename, group_name_set, ok_cb, false) + rename_channel(channel_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], "------") + savelog(matches[2], "log file created by owner/support/admin") 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+)$" + "^[#!/]owners (%d+) ([^%s]+) (.*)$", + "^[#!/]owners (%d+) ([^%s]+)$", + "^[#!/](changeabout) (%d+) (.*)$", + "^[#!/](changerules) (%d+) (.*)$", + "^[#!/](changename) (%d+) (.*)$", + "^[#!/](viewsettings) (%d+)$", + "^[#!/](loggroup) (%d+)$" }, run = run -} +} \ No newline at end of file diff --git a/plugins/set.lua b/plugins/set.lua index 5ed46ea..9a425fb 100644 --- a/plugins/set.lua +++ b/plugins/set.lua @@ -3,7 +3,7 @@ local function save_value(msg, name, value) return "Usage: !set var_name value" end local hash = nil - if msg.to.type == 'chat' then + if msg.to.type == 'chat' or msg.to.type == 'channel' then hash = 'chat:'..msg.to.id..':variables' end if hash then @@ -25,7 +25,7 @@ end return { patterns = { - "^[!/]save ([^%s]+) (.+)$" + "^[#!/]save ([^%s]+) (.+)$" }, run = run } diff --git a/plugins/stats.lua b/plugins/stats.lua index 7583136..3c9efe3 100644 --- a/plugins/stats.lua +++ b/plugins/stats.lua @@ -11,7 +11,7 @@ local function get_msgs_user_chat(user_id, chat_id) return user_info end -local function chat_stats(chat_id) +local function chat_stats(receiver, chat_id) -- Users on chat local hash = 'chat:'..chat_id..':users' local users = redis:smembers(hash) @@ -24,11 +24,11 @@ local function chat_stats(chat_id) end -- Sort users by msgs number table.sort(users_info, function(a, b) - if a.msgs and b.msgs then + if a.msgs and b.msgs then return a.msgs > b.msgs - end - end) - local text = 'users in this chat \n' + 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 @@ -36,7 +36,7 @@ local function chat_stats(chat_id) file:write(text) file:flush() file:close() - send_document("chat#id"..chat_id,"./groups/lists/"..chat_id.."stats.txt", ok_cb, false) + send_document(receiver,"./groups/lists/"..chat_id.."stats.txt", ok_cb, false) return --text end @@ -60,7 +60,7 @@ local function chat_stats2(chat_id) end end) - local text = 'users in this chat \n' + local text = 'Users in this chat \n' for k,user in pairs(users_info) do text = text..user.name..' = '..user.msgs..'\n' end @@ -74,9 +74,9 @@ local function bot_stats() local count = 0 repeat - local r = redis.call("SCAN", cursor, "MATCH", KEYS[1]) - cursor = r[1] - count = count + #r[2] + local r = redis.call("SCAN", cursor, "MATCH", KEYS[1]) + cursor = r[1] + count = count + #r[2] until cursor == '0' return count]] @@ -111,24 +111,25 @@ local function run(msg, matches) if not is_momod(msg) then return "For mods only !" end - if msg.to.type == 'chat' then + if msg.to.type == 'chat' or msg.to.type == 'channel' then + local receiver = get_receiver(msg) 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) + return chat_stats(receiver, chat_id) else return end end if matches[2] == "teleseed" then -- Put everything you like :) - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only !" else return bot_stats() end end if matches[2] == "group" then - if not is_admin(msg) then + if not is_admin1(msg) then return "For admins only !" else return chat_stats(matches[3]) @@ -136,15 +137,15 @@ local function run(msg, matches) 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 :) + "^[#!/]([Ss]tats)$", + "^[#!/]([Ss]tatslist)$", + "^[#!/]([Ss]tats) (group) (%d+)", + "^[#!/]([Ss]tats) (teleseed)", + "^[#!/]([Tt]eleseed)" }, run = run } - -end +end \ No newline at end of file diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua new file mode 100644 index 0000000..8f021b9 --- /dev/null +++ b/plugins/supergroup.lua @@ -0,0 +1,2035 @@ +--Begin supergrpup.lua +--Check members #Add supergroup +local function check_member_super(cb_extra, success, result) + local receiver = cb_extra.receiver + local data = cb_extra.data + local msg = cb_extra.msg + if success == 0 then + send_large_msg(receiver, "Promote me to admin first!") + end + for k,v in pairs(result) do + local member_id = v.peer_id + if member_id ~= our_id then + -- SuperGroup configuration + data[tostring(msg.to.id)] = { + group_type = 'SuperGroup', + long_id = msg.to.peer_id, + moderators = {}, + set_owner = member_id , + settings = { + set_name = string.gsub(msg.to.title, '_', ' '), + lock_arabic = 'no', + lock_link = "no", + flood = 'yes', + lock_spam = 'yes', + lock_sticker = 'no', + member = 'no', + public = 'no', + lock_rtl = 'no', + lock_contacts = 'no', + strict = 'no' + } + } + 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) + local text = 'SuperGroup has been added!' + return reply_msg(msg.id, text, ok_cb, false) + end + end +end + +--Check Members #rem supergroup +local function check_member_superrem(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) 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) + local text = 'SuperGroup has been removed' + return reply_msg(msg.id, text, ok_cb, false) + end + end +end + +--Function to Add supergroup +local function superadd(msg) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + channel_get_users(receiver, check_member_super,{receiver = receiver, data = data, msg = msg}) +end + +--Function to remove supergroup +local function superrem(msg) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + channel_get_users(receiver, check_member_superrem,{receiver = receiver, data = data, msg = msg}) +end + +--Get and output admins and bots in supergroup +local function callback(cb_extra, success, result) +local i = 1 +local chat_name = string.gsub(cb_extra.msg.to.print_name, "_", " ") +local member_type = cb_extra.member_type +local text = member_type.." for "..chat_name..":\n" +for k,v in pairsByKeys(result) do +if not v.first_name then + name = " " +else + vname = v.first_name:gsub("‮", "") + name = vname:gsub("_", " ") + end + text = text.."\n"..i.." - "..name.."["..v.peer_id.."]" + i = i + 1 + end + send_large_msg(cb_extra.receiver, text) +end + +--Get and output info about supergroup +local function callback_info(cb_extra, success, result) +local title ="Info for SuperGroup: ["..result.title.."]\n\n" +local admin_num = "Admin count: "..result.admins_count.."\n" +local user_num = "User count: "..result.participants_count.."\n" +local kicked_num = "Kicked user count: "..result.kicked_count.."\n" +local channel_id = "ID: "..result.peer_id.."\n" +if result.username then + channel_username = "Username: @"..result.username +else + channel_username = "" +end +local text = title..admin_num..user_num..kicked_num..channel_id..channel_username + send_large_msg(cb_extra.receiver, text) +end + +--Get and output members of supergroup +local function callback_who(cb_extra, success, result) +local text = "Members for "..cb_extra.receiver +local i = 1 +for k,v in pairsByKeys(result) do +if not v.print_name then + name = " " +else + vname = v.print_name:gsub("‮", "") + name = vname:gsub("_", " ") +end + if v.username then + username = " @"..v.username + else + username = "" + end + text = text.."\n"..i.." - "..name.." "..username.." [ "..v.peer_id.." ]\n" + --text = text.."\n"..username + i = i + 1 +end + local file = io.open("./groups/lists/supergroups/"..cb_extra.receiver..".txt", "w") + file:write(text) + file:flush() + file:close() + send_document(cb_extra.receiver,"./groups/lists/supergroups/"..cb_extra.receiver..".txt", ok_cb, false) + post_msg(cb_extra.receiver, text, ok_cb, false) +end + +--Get and output list of kicked users for supergroup +local function callback_kicked(cb_extra, success, result) +--vardump(result) +local text = "Kicked Members for SuperGroup "..cb_extra.receiver.."\n\n" +local i = 1 +for k,v in pairsByKeys(result) do +if not v.print_name then + name = " " +else + vname = v.print_name:gsub("‮", "") + name = vname:gsub("_", " ") +end + if v.username then + name = name.." @"..v.username + end + text = text.."\n"..i.." - "..name.." [ "..v.peer_id.." ]\n" + i = i + 1 +end + local file = io.open("./groups/lists/supergroups/kicked/"..cb_extra.receiver..".txt", "w") + file:write(text) + file:flush() + file:close() + send_document(cb_extra.receiver,"./groups/lists/supergroups/kicked/"..cb_extra.receiver..".txt", ok_cb, false) + --send_large_msg(cb_extra.receiver, text) +end + +--Begin supergroup locks +local function lock_group_links(msg, data, target) + if not is_momod(msg) then + return + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'yes' then + return 'Link posting is already locked' + else + data[tostring(target)]['settings']['lock_link'] = 'yes' + save_data(_config.moderation.data, data) + return 'Link posting has been locked' + end +end + +local function unlock_group_links(msg, data, target) + if not is_momod(msg) then + return + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'no' then + return 'Link posting is not locked' + else + data[tostring(target)]['settings']['lock_link'] = 'no' + save_data(_config.moderation.data, data) + return 'Link posting has been unlocked' + end +end + +local function lock_group_spam(msg, data, target) + if not is_momod(msg) then + return + end + if not is_owner(msg) then + return "Owners only!" + end + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'yes' then + return 'SuperGroup spam is already locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'yes' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been locked' + end +end + +local function unlock_group_spam(msg, data, target) + if not is_momod(msg) then + return + end + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'no' then + return 'SuperGroup spam is not locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been unlocked' + end +end + +local function lock_group_flood(msg, data, target) + if not is_momod(msg) then + return + end + local group_flood_lock = data[tostring(target)]['settings']['flood'] + if group_flood_lock == 'yes' then + return 'Flood is already locked' + else + data[tostring(target)]['settings']['flood'] = 'yes' + save_data(_config.moderation.data, data) + return 'Flood has been locked' + end +end + +local function unlock_group_flood(msg, data, target) + if not is_momod(msg) then + return + end + local group_flood_lock = data[tostring(target)]['settings']['flood'] + if group_flood_lock == 'no' then + return 'Flood is not locked' + else + data[tostring(target)]['settings']['flood'] = 'no' + save_data(_config.moderation.data, data) + return 'Flood has been unlocked' + end +end + +local function lock_group_arabic(msg, data, target) + if not is_momod(msg) then + return + 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 + end + local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] + if group_arabic_lock == 'no' then + return 'Arabic/Persian is already unlocked' + else + data[tostring(target)]['settings']['lock_arabic'] = 'no' + save_data(_config.moderation.data, data) + return 'Arabic/Persian has been unlocked' + end +end + +local function lock_group_membermod(msg, data, target) + if not is_momod(msg) then + return + end + local group_member_lock = data[tostring(target)]['settings']['lock_member'] + if group_member_lock == 'yes' then + return 'SuperGroup members are already locked' + else + data[tostring(target)]['settings']['lock_member'] = 'yes' + save_data(_config.moderation.data, data) + end + return 'SuperGroup members has been locked' +end + +local function unlock_group_membermod(msg, data, target) + if not is_momod(msg) then + return + end + local group_member_lock = data[tostring(target)]['settings']['lock_member'] + if group_member_lock == 'no' then + return 'SuperGroup members are not locked' + else + data[tostring(target)]['settings']['lock_member'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup members has been unlocked' + end +end + +local function lock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'yes' then + return 'RTL is already locked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'yes' + save_data(_config.moderation.data, data) + return 'RTL has been locked' + end +end + +local function unlock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'no' then + return 'RTL is already unlocked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'no' + save_data(_config.moderation.data, data) + return 'RTL has been unlocked' + end +end + +local function lock_group_sticker(msg, data, target) + if not is_momod(msg) then + return + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'yes' then + return 'Sticker posting is already locked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'yes' + save_data(_config.moderation.data, data) + return 'Sticker posting has been locked' + end +end + +local function unlock_group_sticker(msg, data, target) + if not is_momod(msg) then + return + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'no' then + return 'Sticker posting is already unlocked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'no' + save_data(_config.moderation.data, data) + return 'Sticker posting has been unlocked' + end +end + +local function lock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'yes' then + return 'Contact posting is already locked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'yes' + save_data(_config.moderation.data, data) + return 'Contact posting has been locked' + end +end + +local function unlock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'no' then + return 'Contact posting is already unlocked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'no' + save_data(_config.moderation.data, data) + return 'Contact posting has been unlocked' + end +end + +local function enable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_strict_lock = data[tostring(target)]['settings']['strict'] + if group_strict_lock == 'yes' then + return 'Settings are already strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'yes' + save_data(_config.moderation.data, data) + return 'Settings will be strictly enforced' + end +end + +local function disable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_strict_lock = data[tostring(target)]['settings']['strict'] + if group_strict_lock == 'no' then + return 'Settings are not strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'no' + save_data(_config.moderation.data, data) + return 'Settings will not be strictly enforced' + end +end +--End supergroup locks + +--'Set supergroup rules' function +local function set_rulesmod(msg, data, target) + if not is_momod(msg) then + return + end + local data_cat = 'rules' + data[tostring(target)][data_cat] = rules + save_data(_config.moderation.data, data) + return 'SuperGroup rules set' +end + +--'Get supergroup rules' function +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 group_name = data[tostring(msg.to.id)]['settings']['set_name'] + local rules = group_name..' rules:\n\n'..rules:gsub("/n", " ") + return rules +end + +--Set supergroup to public or not public function +local function set_public_membermod(msg, data, target) + if not is_momod(msg) then + return "For moderators only!" + end + local group_public_lock = data[tostring(target)]['settings']['public'] + local long_id = data[tostring(target)]['long_id'] + if not long_id then + data[tostring(target)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + end + if group_public_lock == 'yes' then + return 'Group is already public' + else + data[tostring(target)]['settings']['public'] = 'yes' + save_data(_config.moderation.data, data) + end + return 'SuperGroup is now: public' +end + +local function unset_public_membermod(msg, data, target) + if not is_momod(msg) then + return + end + local group_public_lock = data[tostring(target)]['settings']['public'] + local long_id = data[tostring(target)]['long_id'] + if not long_id then + data[tostring(target)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + end + if group_public_lock == 'no' then + return 'Group is not public' + else + data[tostring(target)]['settings']['public'] = 'no' + data[tostring(target)]['long_id'] = msg.to.long_id + save_data(_config.moderation.data, data) + return 'SuperGroup is now: not public' + end +end + +--Show supergroup settings; function +function show_supergroup_settingsmod(msg, target) + if not is_momod(msg) then + return + end + 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 + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['public'] then + data[tostring(target)]['settings']['public'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_rtl'] then + data[tostring(target)]['settings']['lock_rtl'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_member'] then + data[tostring(target)]['settings']['lock_member'] = 'no' + end + end + local settings = data[tostring(target)]['settings'] + local text = "SuperGroup settings:\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nFlood sensitivity : "..NUM_MSG_MAX.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict + return text +end + +local function promote_admin(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + local member_tag_username = string.gsub(member_username, '@', '(at)') + if not data[group] then + return + end + if data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_username..' is already a moderator.') + end + data[group]['moderators'][tostring(user_id)] = member_tag_username + save_data(_config.moderation.data, data) +end + +local function demote_admin(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + if not data[group] then + return + end + if not data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_tag_username..' is not a moderator.') + end + data[group]['moderators'][tostring(user_id)] = nil + save_data(_config.moderation.data, data) +end + +local function promote2(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + local member_tag_username = string.gsub(member_username, '@', '(at)') + if not data[group] then + return send_large_msg(receiver, 'SuperGroup is not added.') + end + if data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_username..' is already a moderator.') + end + data[group]['moderators'][tostring(user_id)] = member_tag_username + save_data(_config.moderation.data, data) + send_large_msg(receiver, member_username..' has been promoted.') +end + +local function demote2(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + if not data[group] then + return send_large_msg(receiver, 'Group is not added.') + end + if not data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_tag_username..' is not a moderator.') + end + data[group]['moderators'][tostring(user_id)] = nil + save_data(_config.moderation.data, data) + send_large_msg(receiver, member_username..' has been demoted.') +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 'SuperGroup is not added.' + end + -- determine if table is empty + if next(data[tostring(msg.to.id)]['moderators']) == nil then + 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 + +-- Start by reply actions +function get_message_callback(extra, success, result) + local get_cmd = extra.get_cmd + local msg = extra.msg + local data = load_data(_config.moderation.data) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + if get_cmd == "id" and not result.action then + local channel = 'channel#id'..result.to.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id for: ["..result.from.peer_id.."]") + id1 = send_large_msg(channel, result.from.peer_id) + elseif get_cmd == 'id' and result.action then + local action = result.action.type + if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then + if result.action.user then + user_id = result.action.user.peer_id + else + user_id = result.peer_id + end + local channel = 'channel#id'..result.to.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id by service msg for: ["..user_id.."]") + id1 = send_large_msg(channel, user_id) + end + elseif get_cmd == "idfrom" then + local channel = 'channel#id'..result.to.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id for msg fwd from: ["..result.fwd_from.peer_id.."]") + id2 = send_large_msg(channel, result.fwd_from.peer_id) + elseif get_cmd == 'channel_block' and not result.action then + local member_id = result.from.peer_id + local channel_id = result.to.peer_id + if member_id == msg.from.id then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(member_id, channel_id) and not is_admin2(msg.from.id) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(member_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + --savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..user_id.."] by reply") + kick_user(member_id, channel_id) + elseif get_cmd == 'channel_block' and result.action and result.action.type == 'chat_add_user' then + local user_id = result.action.user.peer_id + local channel_id = result.to.peer_id + if member_id == msg.from.id then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(member_id, channel_id) and not is_admin2(msg.from.id) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(member_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..user_id.."] by reply to sev. msg.") + kick_user(user_id, channel_id) + elseif get_cmd == "del" then + delete_msg(result.id, ok_cb, false) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] deleted a message by reply") + elseif get_cmd == "setadmin" then + local user_id = result.from.peer_id + local channel_id = "channel#id"..result.to.peer_id + channel_set_admin(channel_id, "user#id"..user_id, ok_cb, false) + if result.from.username then + text = "@"..result.from.username.." set as an admin" + else + text = "[ "..user_id.." ]set as an admin" + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set: ["..user_id.."] as admin by reply") + send_large_msg(channel_id, text) + elseif get_cmd == "demoteadmin" then + local user_id = result.from.peer_id + local channel_id = "channel#id"..result.to.peer_id + if is_admin2(result.from.peer_id) then + return send_large_msg(channel_id, "You can't demote global admins!") + end + channel_demote(channel_id, "user#id"..user_id, ok_cb, false) + if result.from.username then + text = "@"..result.from.username.." has been demoted from admin" + else + text = "[ "..user_id.." ] has been demoted from admin" + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted: ["..user_id.."] from admin by reply") + send_large_msg(channel_id, text) + elseif get_cmd == "setowner" then + local group_owner = data[tostring(result.to.peer_id)]['set_owner'] + if group_owner then + if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then + local channel_id = 'channel#id'..result.to.peer_id + local user = "user#id"..group_owner + channel_demote(channel_id, user, ok_cb, false) + end + local user_id = "user#id"..result.from.peer_id + channel_set_admin(channel_id, user_id, ok_cb, false) + data[tostring(result.to.peer_id)]['set_owner'] = tostring(result.from.peer_id) + save_data(_config.moderation.data, data) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set: ["..result.from.peer_id.."] as owner by reply") + if result.from.username then + text = "@"..result.from.username.." [ "..result.from.peer_id.." ] added as owner" + else + text = "[ "..result.from.peer_id.." ] added as owner" + end + send_large_msg(channel_id, text) + end + elseif get_cmd == "promote" then + local receiver = result.to.peer_id + local full_name = (result.from.first_name or '')..' '..(result.from.last_name or '') + local member_name = full_name:gsub("‮", "") + local member_username = member_name:gsub("_", " ") + if result.from.username then + member_username = '@'.. result.from.username + end + local member_id = result.from.peer_id + if result.to.peer_type == 'channel' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted mod: @"..member_username.."["..result.from.peer_id.."] by reply") + promote2("channel#id"..result.to.peer_id, member_username, member_id) + --channel_set_mod(channel_id, user, ok_cb, false) + end + elseif get_cmd == "demote" then + local full_name = (result.from.first_name or '')..' '..(result.from.last_name or '') + local member_name = full_name:gsub("‮", "") + local member_username = member_name:gsub("_", " ") + if result.from.username then + member_username = '@'.. result.from.username + end + local member_id = result.from.peer_id + --local user = "user#id"..result.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted mod: @"..member_username.."["..user_id.."] by reply") + demote2("channel#id"..result.to.peer_id, member_username, member_id) + --channel_demote(channel_id, user, ok_cb, false) + elseif get_cmd == 'mute_user' then + if result.service then + local action = result.action.type + if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then + if result.action.user then + user_id = result.action.user.peer_id + end + end + if action == 'chat_add_user_link' then + if result.from then + user_id = result.from.peer_id + end + end + else + user_id = result.from.peer_id + end + local receiver = extra.receiver + local chat_id = msg.to.id + print(user_id) + print(chat_id) + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + send_large_msg(receiver, "["..user_id.."] removed from the muted user list") + elseif is_admin1(msg) then + mute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] added to the muted user list") + end + end +end +-- End by reply actions + +--By ID actions +local function cb_user_info(extra, success, result) + local receiver = extra.receiver + local user_id = result.peer_id + local get_cmd = extra.get_cmd + local data = load_data(_config.moderation.data) + --[[if get_cmd == "setadmin" then + local user_id = "user#id"..result.peer_id + channel_set_admin(receiver, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been set as an admin" + else + text = "[ "..result.peer_id.." ] has been set as an admin" + end + send_large_msg(receiver, text)]] + if get_cmd == "demoteadmin" then + if is_admin2(result.peer_id) then + return send_large_msg(receiver, "You can't demote global admins!") + end + local user_id = "user#id"..result.peer_id + channel_demote(receiver, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been demoted from admin" + send_large_msg(receiver, text) + else + text = "[ "..result.peer_id.." ] has been demoted from admin" + send_large_msg(receiver, text) + end + elseif get_cmd == "promote" then + if result.username then + member_username = "@"..result.username + else + member_username = string.gsub(result.print_name, '_', ' ') + end + promote2(receiver, member_username, user_id) + elseif get_cmd == "demote" then + if result.username then + member_username = "@"..result.username + else + member_username = string.gsub(result.print_name, '_', ' ') + end + demote2(receiver, member_username, user_id) + end +end + +-- Begin resolve username actions +local function callbackres(extra, success, result) + local member_id = result.peer_id + local member_username = "@"..result.username + local get_cmd = extra.get_cmd + if get_cmd == "res" then + local user = result.peer_id + local name = string.gsub(result.print_name, "_", " ") + local channel = 'channel#id'..extra.channelid + send_large_msg(channel, user..'\n'..name) + return user + elseif get_cmd == "id" then + local user = result.peer_id + local channel = 'channel#id'..extra.channelid + send_large_msg(channel, user) + return user + elseif get_cmd == "invite" then + local receiver = extra.channel + local user_id = "user#id"..result.peer_id + channel_invite(receiver, user_id, ok_cb, false) + --[[elseif get_cmd == "channel_block" then + local user_id = result.peer_id + local channel_id = extra.channelid + local sender = extra.sender + if member_id == sender then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(member_id, channel_id) and not is_admin2(sender) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(member_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + kick_user(user_id, channel_id) + elseif get_cmd == "setadmin" then + local user_id = "user#id"..result.peer_id + local channel_id = extra.channel + channel_set_admin(channel_id, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been set as an admin" + send_large_msg(channel_id, text) + else + text = "@"..result.peer_id.." has been set as an admin" + send_large_msg(channel_id, text) + end + elseif get_cmd == "setowner" then + local receiver = extra.channel + local channel = string.gsub(receiver, 'channel#id', '') + local from_id = extra.from_id + local group_owner = data[tostring(channel)]['set_owner'] + if group_owner then + local user = "user#id"..group_owner + if not is_admin2(group_owner) and not is_support(group_owner) then + channel_demote(receiver, user, ok_cb, false) + end + local user_id = "user#id"..result.peer_id + channel_set_admin(receiver, user_id, ok_cb, false) + data[tostring(channel)]['set_owner'] = tostring(result.peer_id) + save_data(_config.moderation.data, data) + savelog(channel, name_log.." ["..from_id.."] set ["..result.peer_id.."] as owner by username") + if result.username then + text = member_username.." [ "..result.peer_id.." ] added as owner" + else + text = "[ "..result.peer_id.." ] added as owner" + end + send_large_msg(receiver, text) + end]] + elseif get_cmd == "promote" then + local receiver = extra.channel + local user_id = result.peer_id + --local user = "user#id"..result.peer_id + promote2(receiver, member_username, user_id) + --channel_set_mod(receiver, user, ok_cb, false) + elseif get_cmd == "demote" then + local receiver = extra.channel + local user_id = result.peer_id + local user = "user#id"..result.peer_id + demote2(receiver, member_username, user_id) + elseif get_cmd == "demoteadmin" then + local user_id = "user#id"..result.peer_id + local channel_id = extra.channel + if is_admin2(result.peer_id) then + return send_large_msg(channel_id, "You can't demote global admins!") + end + channel_demote(channel_id, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been demoted from admin" + send_large_msg(channel_id, text) + else + text = "@"..result.peer_id.." has been demoted from admin" + send_large_msg(channel_id, text) + end + local receiver = extra.channel + local user_id = result.peer_id + demote_admin(receiver, member_username, user_id) + elseif get_cmd == 'mute_user' then + local user_id = result.peer_id + local receiver = extra.receiver + local chat_id = string.gsub(receiver, 'channel#id', '') + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] removed from muted user list") + elseif is_owner(extra.msg) then + mute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] added to muted user list") + end + end +end +--End resolve username actions + +--Begin non-channel_invite username actions +local function in_channel_cb(cb_extra, success, result) + local get_cmd = cb_extra.get_cmd + local receiver = cb_extra.receiver + local msg = cb_extra.msg + local data = load_data(_config.moderation.data) + local print_name = user_print_name(cb_extra.msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + local member = cb_extra.username + local memberid = cb_extra.user_id + if member then + text = 'No user @'..member..' in this SuperGroup.' + else + text = 'No user ['..memberid..'] in this SuperGroup.' + end +if get_cmd == "channel_block" then + for k,v in pairs(result) do + vusername = v.username + vpeer_id = tostring(v.peer_id) + if vusername == member or vpeer_id == memberid then + local user_id = v.peer_id + local channel_id = cb_extra.msg.to.id + local sender = cb_extra.msg.from.id + if user_id == sender then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(user_id, channel_id) and not is_admin2(sender) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(user_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + if v.username then + text = "" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: @"..v.username.." ["..v.peer_id.."]") + else + text = "" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..v.peer_id.."]") + end + kick_user(user_id, channel_id) + end + end +elseif get_cmd == "setadmin" then + for k,v in pairs(result) do + vusername = v.username + vpeer_id = tostring(v.peer_id) + if vusername == member or vpeer_id == memberid then + local user_id = "user#id"..v.peer_id + local channel_id = "channel#id"..cb_extra.msg.to.id + channel_set_admin(channel_id, user_id, ok_cb, false) + if v.username then + text = "@"..v.username.." ["..v.peer_id.."] has been set as an admin" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin @"..v.username.." ["..v.peer_id.."]") + else + text = "["..v.peer_id.."] has been set as an admin" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin "..v.peer_id) + end + if v.username then + member_username = "@"..v.username + else + member_username = string.gsub(v.print_name, '_', ' ') + end + local receiver = channel_id + local user_id = v.peer_id + promote_admin(receiver, member_username, user_id) + end + send_large_msg(channel_id, text) + end + elseif get_cmd == 'setowner' then + for k,v in pairs(result) do + vusername = v.username + vpeer_id = tostring(v.peer_id) + if vusername == member or vpeer_id == memberid then + local channel = string.gsub(receiver, 'channel#id', '') + local from_id = cb_extra.msg.from.id + local group_owner = data[tostring(channel)]['set_owner'] + if group_owner then + if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then + local user = "user#id"..group_owner + channel_demote(receiver, user, ok_cb, false) + end + local user_id = "user#id"..v.peer_id + channel_set_admin(receiver, user_id, ok_cb, false) + data[tostring(channel)]['set_owner'] = tostring(v.peer_id) + save_data(_config.moderation.data, data) + savelog(channel, name_log.."["..from_id.."] set ["..v.peer_id.."] as owner by username") + if result.username then + text = member_username.." ["..v.peer_id.."] added as owner" + else + text = "["..v.peer_id.."] added as owner" + end + end + elseif memberid and vusername ~= member and vpeer_id ~= memberid then + local channel = string.gsub(receiver, 'channel#id', '') + local from_id = cb_extra.msg.from.id + local group_owner = data[tostring(channel)]['set_owner'] + if group_owner then + if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then + local user = "user#id"..group_owner + channel_demote(receiver, user, ok_cb, false) + end + data[tostring(channel)]['set_owner'] = tostring(memberid) + save_data(_config.moderation.data, data) + savelog(channel, name_log.."["..from_id.."] set ["..memberid.."] as owner by username") + text = "["..memberid.."] added as owner" + end + end + end + end +send_large_msg(receiver, text) +end +--End non-channel_invite username actions + +--'Set supergroup photo' function +local function set_supergroup_photo(msg, success, result) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + if success then + local file = 'data/photos/channel_photo_'..msg.to.id..'.jpg' + print('File downloaded to:', result) + os.rename(result, file) + print('File moved to:', file) + channel_set_photo(receiver, file, ok_cb, false) + data[tostring(msg.to.id)]['settings']['set_photo'] = file + 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 + +--Run function +local function run(msg, matches) + if msg.to.type == 'chat' then + if matches[1] == 'tosuper' then + if not is_admin1(msg) then + return + end + local receiver = get_receiver(msg) + chat_upgrade(receiver, ok_cb, false) + end + elseif msg.to.type == 'channel'then + if matches[1] == 'tosuper' then + if not is_admin1(msg) then + return + end + return "Already a SuperGroup" + end + end + if msg.to.type == 'channel' then + local support_id = msg.from.id + local receiver = get_receiver(msg) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + local data = load_data(_config.moderation.data) + if matches[1] == 'add' and not matches[2] then + if not is_admin1(msg) and not is_support(support_id) then + return + end + if is_super_group(msg) then + return reply_msg(msg.id, 'SuperGroup is already added.', ok_cb, false) + end + print("SuperGroup "..msg.to.print_name.."("..msg.to.id..") added") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added SuperGroup") + superadd(msg) + set_mutes(msg.to.id) + channel_set_admin(receiver, 'user#id'..msg.from.id, ok_cb, false) + end + + if matches[1] == 'rem' and is_admin1(msg) and not matches[2] then + if not is_super_group(msg) then + return reply_msg(msg.id, 'SuperGroup is not added.', ok_cb, false) + end + print("SuperGroup "..msg.to.print_name.."("..msg.to.id..") removed") + superrem(msg) + rem_mutes(msg.to.id) + end + + if matches[1] == "info" then + if not is_owner(msg) then + return + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup info") + channel_info(receiver, callback_info, {receiver = receiver, msg = msg}) + end + + if matches[1] == "admins" then + if not is_owner(msg) and not is_support(msg.from.id) then + return + end + member_type = 'Admins' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup Admins list") + admins = channel_get_admins(receiver,callback, {receiver = receiver, msg = msg, member_type = member_type}) + end + + if matches[1] == "owner" then + local group_owner = data[tostring(msg.to.id)]['set_owner'] + if not group_owner then + return "no owner,ask admins in support groups to set owner for your SuperGroup" + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] used /owner") + return "SuperGroup owner is ["..group_owner..']' + end + + if matches[1] == "modlist" then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group modlist") + return modlist(msg) + -- channel_get_admins(receiver,callback, {receiver = receiver}) + end + + if matches[1] == "bots" and is_momod(msg) then + member_type = 'Bots' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup bots list") + channel_get_bots(receiver, callback, {receiver = receiver, msg = msg, member_type = member_type}) + end + + if matches[1] == "who" and not matches[2] and is_momod(msg) then + local user_id = msg.from.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup users list") + channel_get_users(receiver, callback_who, {receiver = receiver}) + end + + if matches[1] == "kicked" and is_momod(msg) then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested Kicked users list") + channel_get_kicked(receiver, callback_kicked, {receiver = receiver}) + end + + if matches[1] == 'del' and is_momod(msg) then + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'del', + msg = msg + } + delete_msg(msg.id, ok_cb, false) + get_message(msg.reply_id, get_message_callback, cbreply_extra) + end + end + + if matches[1] == 'block' and is_momod(msg) then + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'channel_block', + msg = msg + } + get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'block' and string.match(matches[2], '^%d+$') then + --[[local user_id = matches[2] + local channel_id = msg.to.id + if is_momod2(user_id, channel_id) and not is_admin2(user_id) then + return send_large_msg(receiver, "You can't kick mods/owner/admins") + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: [ user#id"..user_id.." ]") + kick_user(user_id, channel_id)]] + local get_cmd = 'channel_block' + local msg = msg + local user_id = matches[2] + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) + elseif msg.text:match("@[%a%d]") then + --[[local cbres_extra = { + channelid = msg.to.id, + get_cmd = 'channel_block', + sender = msg.from.id + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: @"..username) + resolve_username(username, callbackres, cbres_extra)]] + local get_cmd = 'channel_block' + local msg = msg + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) + end + end + + if matches[1] == 'id' then + if type(msg.reply_id) ~= "nil" and is_momod(msg) and not matches[2] then + local cbreply_extra = { + get_cmd = 'id', + msg = msg + } + get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif type(msg.reply_id) ~= "nil" and matches[2] == "from" and is_momod(msg) then + local cbreply_extra = { + get_cmd = 'idfrom', + msg = msg + } + get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif msg.text:match("@[%a%d]") then + local cbres_extra = { + channelid = msg.to.id, + get_cmd = 'id' + } + local username = matches[2] + local username = username:gsub("@","") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested ID for: @"..username) + resolve_username(username, callbackres, cbres_extra) + else + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup ID") + return "SuperGroup ID for " ..string.gsub(msg.to.print_name, "_", " ").. ":\n\n"..msg.to.id + end + end + + if matches[1] == 'kickme' then + if msg.to.type == 'channel' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] left via kickme") + channel_kick("channel#id"..msg.to.id, "user#id"..msg.from.id, ok_cb, false) + end + end + + if matches[1] == 'newlink' and is_momod(msg)then + local function callback_link (extra , success, result) + local receiver = get_receiver(msg) + if success == 0 then + send_large_msg(receiver, '*Error: Failed to retrieve link* \nReason: Not creator.\n\nIf you have the link, please use /setlink to set it') + data[tostring(msg.to.id)]['settings']['set_link'] = nil + save_data(_config.moderation.data, data) + else + send_large_msg(receiver, "Created a new link") + data[tostring(msg.to.id)]['settings']['set_link'] = result + save_data(_config.moderation.data, data) + end + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to create a new SuperGroup link") + export_channel_link(receiver, callback_link, false) + end + + if matches[1] == 'setlink' and is_owner(msg) then + data[tostring(msg.to.id)]['settings']['set_link'] = 'waiting' + save_data(_config.moderation.data, data) + return 'Please send the new group link now' + end + + if msg.text then + if msg.text:match("^(https://telegram.me/joinchat/%S+)$") and data[tostring(msg.to.id)]['settings']['set_link'] == 'waiting' and is_owner(msg) then + data[tostring(msg.to.id)]['settings']['set_link'] = msg.text + save_data(_config.moderation.data, data) + return "New link set" + end + end + + if matches[1] == 'link' then + if not is_momod(msg) then + return + end + local group_link = data[tostring(msg.to.id)]['settings']['set_link'] + if not group_link then + return "Create a link using /newlink first!\n\nOr if I am not creator use /setlink to set your link" + 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] == "invite" and is_sudo(msg) then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = "invite" + } + local username = matches[2] + local username = username:gsub("@","") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] invited @"..username) + resolve_username(username, callbackres, cbres_extra) + end + + if matches[1] == 'res' and is_owner(msg) then + local cbres_extra = { + channelid = msg.to.id, + get_cmd = 'res' + } + local username = matches[2] + local username = username:gsub("@","") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] resolved username: @"..username) + resolve_username(username, callbackres, cbres_extra) + end + + --[[if matches[1] == 'kick' and is_momod(msg) then + local receiver = channel..matches[3] + local user = "user#id"..matches[2] + chaannel_kick(receiver, user, ok_cb, false) + end]] + + if matches[1] == 'setadmin' then + if not is_support(msg.from.id) and not is_owner(msg) then + return + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'setadmin', + msg = msg + } + setadmin = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'setadmin' and string.match(matches[2], '^%d+$') then + --[[] local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'setadmin' + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd})]] + local get_cmd = 'setadmin' + local msg = msg + local user_id = matches[2] + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) + elseif matches[1] == 'setadmin' and not string.match(matches[2], '^%d+$') then + --[[local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'setadmin' + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin @"..username) + resolve_username(username, callbackres, cbres_extra)]] + local get_cmd = 'setadmin' + local msg = msg + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) + end + end + + if matches[1] == 'demoteadmin' then + if not is_support(msg.from.id) and not is_owner(msg) then + return + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'demoteadmin', + msg = msg + } + demoteadmin = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'demoteadmin' and string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'demoteadmin' + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) + elseif matches[1] == 'demoteadmin' and not string.match(matches[2], '^%d+$') then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'demoteadmin' + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted admin @"..username) + resolve_username(username, callbackres, cbres_extra) + end + end + + if matches[1] == 'setowner' and is_owner(msg) then + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'setowner', + msg = msg + } + setowner = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'setowner' and string.match(matches[2], '^%d+$') then + --[[ local group_owner = data[tostring(msg.to.id)]['set_owner'] + if group_owner then + local receiver = get_receiver(msg) + local user_id = "user#id"..group_owner + if not is_admin2(group_owner) and not is_support(group_owner) then + channel_demote(receiver, user_id, ok_cb, false) + end + local user = "user#id"..matches[2] + channel_set_admin(receiver, user, ok_cb, false) + data[tostring(msg.to.id)]['set_owner'] = tostring(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]] + local get_cmd = 'setowner' + local msg = msg + local user_id = matches[2] + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) + elseif matches[1] == 'setowner' and not string.match(matches[2], '^%d+$') then + local get_cmd = 'setowner' + local msg = msg + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) + end + end + + if matches[1] == 'promote' then + if not is_momod(msg) then + return + end + if not is_owner(msg) then + return "Only owner/admin can promote" + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'promote', + msg = msg + } + promote = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'promote' and string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'promote' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted user#id"..matches[2]) + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) + elseif matches[1] == 'promote' and not string.match(matches[2], '^%d+$') then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'promote', + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted @"..username) + return resolve_username(username, callbackres, cbres_extra) + end + end + + if matches[1] == 'mp' and is_sudo(msg) then + channel = get_receiver(msg) + user_id = 'user#id'..matches[2] + channel_set_mod(channel, user_id, ok_cb, false) + return "ok" + end + if matches[1] == 'md' and is_sudo(msg) then + channel = get_receiver(msg) + user_id = 'user#id'..matches[2] + channel_demote(channel, user_id, ok_cb, false) + return "ok" + end + + if matches[1] == 'demote' then + if not is_momod(msg) then + return + end + if not is_owner(msg) then + return "Only owner/support/admin can promote" + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'demote', + msg = msg + } + demote = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'demote' and string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'demote' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted user#id"..matches[2]) + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) + elseif not string.match(matches[2], '^%d+$') then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'demote' + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted @"..username) + return resolve_username(username, callbackres, cbres_extra) + end + end + + if matches[1] == "setname" and is_momod(msg) then + local receiver = get_receiver(msg) + local set_name = string.gsub(matches[2], '_', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] renamed SuperGroup to: "..matches[2]) + rename_channel(receiver, set_name, ok_cb, false) + end + + if msg.service and msg.action.type == 'chat_rename' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] renamed SuperGroup to: "..msg.to.title) + data[tostring(msg.to.id)]['settings']['set_name'] = msg.to.title + save_data(_config.moderation.data, data) + end + + if matches[1] == "setabout" and is_momod(msg) then + local receiver = get_receiver(msg) + local about_text = matches[2] + local data_cat = 'description' + local target = msg.to.id + data[tostring(target)][data_cat] = about_text + save_data(_config.moderation.data, data) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup description to: "..about_text) + channel_set_about(receiver, about_text, ok_cb, false) + return "Description has been set.\n\nSelect the chat again to see the changes." + end + + if matches[1] == "setusername" and is_admin1(msg) then + local function ok_username_cb (extra, success, result) + local receiver = extra.receiver + if success == 1 then + send_large_msg(receiver, "SuperGroup username Set.\n\nSelect the chat again to see the changes.") + elseif success == 0 then + send_large_msg(receiver, "Failed to set SuperGroup username.\nUsername may already be taken.\n\nNote: Username can use a-z, 0-9 and underscores.\nMinimum length is 5 characters.") + end + end + local username = string.gsub(matches[2], '@', '') + channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) + end + + if matches[1] == 'setrules' and is_momod(msg) then + rules = matches[2] + local target = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] has changed group rules to ["..matches[2].."]") + return set_rulesmod(msg, data, target) + end + + if msg.media then + if msg.media.type == 'photo' and data[tostring(msg.to.id)]['settings']['set_photo'] == 'waiting' and is_momod(msg) then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set new SuperGroup photo") + load_photo(msg.id, set_supergroup_photo, msg) + return + end + 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) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] started setting new SuperGroup photo") + return 'Please send the new group photo now' + end + + if matches[1] == 'clean' then + if not is_momod(msg) then + return + end + if not is_momod(msg) then + return "Only owner can clean" + end + if matches[2] == 'modlist' then + if next(data[tostring(msg.to.id)]['moderators']) == nil then + return 'No moderator(s) in this SuperGroup.' + end + 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") + return 'Modlist has been cleaned' + end + if matches[2] == 'rules' then + local data_cat = 'rules' + if data[tostring(msg.to.id)][data_cat] == nil then + return "Rules have not been set" + end + 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") + return 'Rules have been cleaned' + end + if matches[2] == 'about' then + local receiver = get_receiver(msg) + local about_text = ' ' + local data_cat = 'description' + if data[tostring(msg.to.id)][data_cat] == nil then + return 'About is not set' + end + 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") + channel_set_about(receiver, about_text, ok_cb, false) + return "About has been cleaned" + end + if matches[2] == 'mutelist' then + chat_id = msg.to.id + local hash = 'mute_user:'..chat_id + redis:del(hash) + return "Mutelist Cleaned" + end + if matches[2] == 'username' and is_admin1(msg) then + local function ok_username_cb (extra, success, result) + local receiver = extra.receiver + if success == 1 then + send_large_msg(receiver, "SuperGroup username cleaned.") + elseif success == 0 then + send_large_msg(receiver, "Failed to clean SuperGroup username.") + end + end + local username = "" + channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) + end + end + + if matches[1] == 'lock' and is_momod(msg) then + local target = msg.to.id + if matches[2] == 'links' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked link posting ") + return lock_group_links(msg, data, target) + end + if matches[2] == 'spam' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked spam ") + return lock_group_spam(msg, data, target) + end + if matches[2] == 'flood' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked flood ") + return lock_group_flood(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] == 'member' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked member ") + return lock_group_membermod(msg, data, target) + end + if matches[2]:lower() == 'rtl' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked rtl chars. in names") + return lock_group_rtl(msg, data, target) + end + if matches[2] == 'sticker' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked sticker posting") + return lock_group_sticker(msg, data, target) + end + if matches[2] == 'contacts' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked contact posting") + return lock_group_contacts(msg, data, target) + end + if matches[2] == 'strict' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked enabled strict settings") + return enable_strict_rules(msg, data, target) + end + end + + if matches[1] == 'unlock' and is_momod(msg) then + local target = msg.to.id + if matches[2] == 'links' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked link posting") + return unlock_group_links(msg, data, target) + end + if matches[2] == 'spam' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked spam") + return unlock_group_spam(msg, data, target) + end + if matches[2] == 'flood' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked flood") + return unlock_group_flood(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] == 'member' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked member ") + return unlock_group_membermod(msg, data, target) + end + if matches[2]:lower() == 'rtl' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked RTL chars. in names") + return unlock_group_rtl(msg, data, target) + end + if matches[2] == 'sticker' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked sticker posting") + return unlock_group_sticker(msg, data, target) + end + if matches[2] == 'contacts' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked contact posting") + return unlock_group_contacts(msg, data, target) + end + if matches[2] == 'strict' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked disabled strict settings") + return disable_strict_rules(msg, data, target) + end + end + + if matches[1] == 'setflood' then + if not is_momod(msg) then + return + 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 'Flood has been set to: '..matches[2] + end + if matches[1] == 'public' and is_momod(msg) 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 SuperGroup to: not public") + return unset_public_membermod(msg, data, target) + end + end + + if matches[1] == 'mute' and is_owner(msg) then + local chat_id = msg.to.id + if matches[2] == 'audio' then + local msg_type = 'Audio' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'photo' then + local msg_type = 'Photo' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'video' then + local msg_type = 'Video' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'gifs' then + local msg_type = 'Gifs' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." have been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'documents' then + local msg_type = 'Documents' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." have been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'text' then + local msg_type = 'Text' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "Mute "..msg_type.." is already on" + end + end + if matches[2] == 'all' then + local msg_type = 'All' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return "Mute "..msg_type.." has been enabled" + else + return "Mute "..msg_type.." is already on" + end + end + end + if matches[1] == 'unmute' and is_momod(msg) then + local chat_id = msg.to.id + if matches[2] == 'audio' then + local msg_type = 'Audio' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'photo' then + local msg_type = 'Photo' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'video' then + local msg_type = 'Video' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'gifs' then + local msg_type = 'Gifs' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." have been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'documents' then + local msg_type = 'Documents' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." have been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'text' then + local msg_type = 'Text' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute message") + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute text is already off" + end + end + if matches[2] == 'all' then + local msg_type = 'All' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return "Mute "..msg_type.." has been disabled" + else + return "Mute "..msg_type.." is already disabled" + end + end + end + + + if matches[1] == "muteuser" and is_momod(msg) then + local chat_id = msg.to.id + local hash = "mute_user"..chat_id + local user_id = "" + if type(msg.reply_id) ~= "nil" then + local receiver = get_receiver(msg) + local get_cmd = "mute_user" + muteuser = get_message(msg.reply_id, get_message_callback, {receiver = receiver, get_cmd = get_cmd, msg = msg}) + elseif matches[1] == "muteuser" and string.match(matches[2], '^%d+$') then + local user_id = matches[2] + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] removed ["..user_id.."] from the muted users list") + return "["..user_id.."] removed from the muted users list" + elseif is_owner(msg) then + mute_user(chat_id, user_id) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added ["..user_id.."] to the muted users list") + return "["..user_id.."] added to the muted user list" + end + elseif matches[1] == "muteuser" and not string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local get_cmd = "mute_user" + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + resolve_username(username, callbackres, {receiver = receiver, get_cmd = get_cmd, msg=msg}) + end + end + + if matches[1] == "muteslist" and is_momod(msg) then + local chat_id = msg.to.id + if not has_mutes(chat_id) then + set_mutes(chat_id) + return mutes_list(chat_id) + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup muteslist") + return mutes_list(chat_id) + end + if matches[1] == "mutelist" and is_momod(msg) then + local chat_id = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup mutelist") + return muted_user_list(chat_id) + end + + if matches[1] == 'settings' and is_momod(msg) then + local target = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup settings ") + return show_supergroup_settingsmod(msg, target) + 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] == 'help' and not is_owner(msg) then + text = "Message /superhelp to @Teleseed in private for SuperGroup help" + reply_msg(msg.id, text, ok_cb, false) + elseif matches[1] == 'help' and is_owner(msg) then + local name_log = user_print_name(msg.from) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /superhelp") + return super_help() + end + + if matches[1] == 'peer_id' and is_admin1(msg)then + text = msg.to.peer_id + reply_msg(msg.id, text, ok_cb, false) + post_large_msg(receiver, text) + end + + if matches[1] == 'msg.to.id' and is_admin1(msg) then + text = msg.to.id + reply_msg(msg.id, text, ok_cb, false) + post_large_msg(receiver, text) + end + + --Admin Join Service Message + if msg.service then + local action = msg.action.type + if action == 'chat_add_user_link' then + if is_owner2(msg.from.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.from.id + savelog(msg.to.id, name_log.." Admin ["..msg.from.id.."] joined the SuperGroup via link") + channel_set_admin(receiver, user, ok_cb, false) + end + if is_support(msg.from.id) and not is_owner2(msg.from.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.from.id + savelog(msg.to.id, name_log.." Support member ["..msg.from.id.."] joined the SuperGroup") + channel_set_mod(receiver, user, ok_cb, false) + end + end + if action == 'chat_add_user' then + if is_owner2(msg.action.user.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.action.user.id + savelog(msg.to.id, name_log.." Admin ["..msg.action.user.id.."] added to the SuperGroup by [ "..msg.from.id.." ]") + channel_set_admin(receiver, user, ok_cb, false) + end + if is_support(msg.action.user.id) and not is_owner2(msg.action.user.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.action.user.id + savelog(msg.to.id, name_log.." Support member ["..msg.action.user.id.."] added to the SuperGroup by [ "..msg.from.id.." ]") + channel_set_mod(receiver, user, ok_cb, false) + end + end + end + if matches[1] == 'msg.to.peer_id' then + post_large_msg(receiver, msg.to.peer_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 { + patterns = { + "^[#!/]([Aa]dd)$", + "^[#!/]([Rr]em)$", + "^[#!/]([Mm]ove) (.*)$", + "^[#!/]([Ii]nfo)$", + "^[#!/]([Aa]dmins)$", + "^[#!/]([Oo]wner)$", + "^[#!/]([Mm]odlist)$", + "^[#!/]([Bb]ots)$", + "^[#!/]([Ww]ho)$", + "^[#!/]([Kk]icked)$", + "^[#!/]([Bb]lock) (.*)", + "^[#!/]([Bb]lock)", + "^[#!/]([Tt]osuper)$", + "^[#!/]([Ii][Dd])$", + "^[#!/]([Ii][Dd]) (.*)$", + "^[#!/]([Kk]ickme)$", + "^[#!/]([Kk]ick) (.*)$", + "^[#!/]([Nn]ewlink)$", + "^[#!/]([Ss]etlink)$", + "^[#!/]([Ll]ink)$", + "^[#!/]([Rr]es) (.*)$", + "^[#!/]([Ss]etadmin) (.*)$", + "^[#!/]([Ss]etadmin)", + "^[#!/]([Dd]emoteadmin) (.*)$", + "^[#!/]([Dd]emoteadmin)", + "^[#!/]([Ss]etowner) (.*)$", + "^[#!/]([Ss]etowner)$", + "^[#!/]([Pp]romote) (.*)$", + "^[#!/]([Pp]romote)", + "^[#!/]([Dd]emote) (.*)$", + "^[#!/]([Dd]emote)", + "^[#!/]([Ss]etname) (.*)$", + "^[#!/]([Ss]etabout) (.*)$", + "^[#!/]([Ss]etrules) (.*)$", + "^[#!/]([Ss]etphoto)$", + "^[#!/]([Ss]etusername) (.*)$", + "^[#!/]([Dd]el)$", + "^[#!/]([Ll]ock) (.*)$", + "^[#!/]([Uu]nlock) (.*)$", + "^[#!/]([Mm]ute) ([^%s]+)$", + "^[#!/]([Uu]nmute) ([^%s]+)$", + "^[#!/]([Mm]uteuser)$", + "^[#!/]([Mm]uteuser) (.*)$", + "^[#!/]([Pp]ublic) (.*)$", + "^[#!/]([Ss]ettings)$", + "^[#!/]([Rr]ules)$", + "^[#!/]([Ss]etflood) (%d+)$", + "^[#!/]([Cc]lean) (.*)$", + "^[#!/]([Hh]elp)$", + "^[#!/]([Mm]uteslist)$", + "^[#!/]([Mm]utelist)$", + "[#!/](mp) (.*)", + "[#!/](md) (.*)", + "^(https://telegram.me/joinchat/%S+)$", + "msg.to.peer_id", + "%[(document)%]", + "%[(photo)%]", + "%[(video)%]", + "%[(audio)%]", + "%[(contact)%]", + "^!!tgservice (.+)$", + }, + run = run, + pre_process = pre_process +} +--End supergrpup.lua +--By @Rondoozle diff --git a/plugins/whitelist.lua b/plugins/whitelist.lua new file mode 100644 index 0000000..f9a354f --- /dev/null +++ b/plugins/whitelist.lua @@ -0,0 +1,81 @@ +do + +local function get_message_callback (extra , success, result) + if result.service then + local action = result.action.type + if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then + if result.action.user then + user_id = result.action.user.peer_id + end + end + else + user_id = result.from.peer_id + end + local receiver = extra.receiver + local hash = "whitelist" + local is_whitelisted = redis:sismember(hash, user_id) + if is_whitelisted then + redis:srem(hash, user_id) + send_large_msg(receiver, "User/Bot ["..user_id.."] removed from whitelist") + else + redis:sadd(hash, user_id) + send_large_msg(receiver, "User/Bot ["..user_id.."] added to whitelist") + end + +end + +local function whitelist_res (extra, success, result) + local user_id = result.peer_id + local receiver = extra.receiver + local hash = "whitelist" + local is_whitelisted = redis:sismember(hash, user_id) + if is_whitelisted then + redis:srem(hash, user_id) + send_large_msg(receiver, "User/Bot ["..user_id.."] removed from whitelist") + else + redis:sadd(hash, user_id) + send_large_msg(receiver, "User/Bot ["..user_id.."] added to whitelist") + end +end + +local function run (msg, matches) +if matches[1] == "whitelist" and is_admin1(msg) then + local hash = "whitelist" + local user_id = "" + if type(msg.reply_id) ~= "nil" then + local receiver = get_receiver(msg) + get_message(msg.reply_id, get_message_callback, {receiver = receiver}) + elseif string.match(matches[2], '^%d+$') then + local user_id = matches[2] + local is_whitelisted = redis:sismember(hash, user_id) + if is_whitelisted then + redis:srem(hash, user_id) + return "User/Bot ["..user_id.."] removed from whitelist" + else + redis:sadd(hash, user_id) + return "User/Bot ["..user_id.."] added to whitelist" + end + elseif not string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + resolve_username(username, whitelist_res, {receiver = receiver}) + end +end + + if matches[1] == "clean" and matches[2] == 'whitelist' and is_admin1(msg) then + local hash = 'whitelist' + redis:del(hash) + return "Whitelist Cleaned" + end +end + +return { + patterns = { + "^[#!/](whitelist)$", + "^[#!/](whitelist) (.*)$", + "^[#!/](clean) (.*)$" + }, + run = run +} +end From cdd930460ea7ec97c4ef57b9b05bc886b89a50f3 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 03:19:28 +0000 Subject: [PATCH 04/58] Corrections :^) --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 411fb56..d9ed894 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # [TeleSeed](https://telegram.me/TeleSeed) -[![Join the chat at https://gitter.im/SEEDTEAM/TeleSeed](https://badges.gitter.im/SEEDTEAM/TeleSeed.svg)](https://gitter.im/SEEDTEAM/TeleSeed?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![https://gitter.im/SEEDTEAM/TeleSeed](https://badges.gitter.im/SEEDTEAM/TeleSeed.svg)](https://gitter.im/SEEDTEAM/TeleSeed?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **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 @@ -62,7 +62,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]unban | Unbans user from group/SuperGroup. | Y | Y | | [#!/]id [username|reply] | For userID's: !id @username (**ONLY IN SuperSroups**) or reply `!id` in any group. | Y | Y | | [#!/]id from | Returns ID of user a message is forwarded from. | N | Y | -| [#!/]kickme | Kicks user from SuperGroup \nIn SuperGroup: **Must be unblocked by owner or use `#join` by pm to return** | Y | Y | +| [#!/]kickme | Kicks user from SuperGroup / In SuperGroup: **Must be unblocked by owner or use `#join` by pm to return** | Y | Y | | [#!/]setowner | Sets group/SuperGroup owner. | Y | Y | | [#!/]promote | Promote a group/SuperGroup moderator. | Y | Y | | [#!/]demote | Demote a group/SuperGroup moderator. | Y | Y | @@ -82,7 +82,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]mute [mute](#mutes) | mute group message types. | Y | Y | | [#!/]unmute [mute](#mutes) | unmute group message types. | Y | Y | | [#!/]setflood [value](#settings) | Set [value] as flood sensitivity.| Y | Y | -| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat.\n_If a muted user posts a message, the message is deleted automaically_\n_only owners can mute | mods and owners can unmute_ | Y | Y | +| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat. ***If a muted user posts a message, the message is deleted automaically only owners can mute | mods and owners can unmute*** | Y | Y | | [#!/]mutelist | Returns list of muted users in group/SuperGroup. | Y | Y | | [#!/]muteslist | Returns mutes for group/SuperGroup. | Y | Y | | [#!/]settings | Returns a list of group/SuperGroup settings. | Y | Y | @@ -92,13 +92,13 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]clean [rules|about|modlist|mutelist] | Clears rules, about, modlist, or mutelist | Y | Y | | [#!/]del | Deletes a message by reply. | N | Y | | [#!/]res [username] | Returns users name and id by username. | Y | Y | -| [#!/]log | Returns group logs.\n_In SuperGroups:_Search for kick reasons using [#RTL|#spam|#lockmember] | Y | Y | +| [#!/]log | Returns group logs.***In SuperGroups:*** Search for kick reasons using [#RTL|#spam|#lockmember] | Y | Y | ##Owner commands {#moderator_commands} -| Command | Description | In group/SuperGroup? | In private? | +| Command | Description | groups/SuperGroups? | In private? | |:--------|:------------|:----------------------|:-------------| -| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat.\n_If a muted user posts a message, the message is deleted automaically_\n_only owners can mute | mods and owners can unmute_ | | N | +| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat.***If a muted user posts a message, the message is deleted automaically / only owners can mute / mods and owners can unmute*** | | N | | [#!/]all | Returns all available information about current group. | Y | N | | [#!/]all [GroupID] | Returns all available information about group by GroupID. | Y | N | | [#!/]owners [GroupID] [kick|ban|unban] [UserID] | Kick, ban, or unban a user from a group by GroupID and UserID. | N | Y | @@ -149,8 +149,8 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]pmunblock [UserID] | Unblock a user from bot private message and bot photo. | Y | Y | Y | | [#!/]markread [on|off] | Toggle bot to doubble check or not doubble check messages. | Y | Y | Y | | [#!/]setbotphoto | Set bot photo. | Y | Y | Y | -| [#!/]contactlist | Bot will generate a list of all it's contacts\nand send it by private message of command sender | Y | Y | Y | -| [#!/]dialoglist | Bot will generate a list of all it's private message users\nand send it by private message of command sender | Y | Y | Y | +| [#!/]contactlist | Bot will generate a list of all it's contacts***and send it by private message of command sender | Y | Y | Y | +| [#!/]dialoglist | Bot will generate a list of all it's private message users***and send it by private message of command sender | Y | Y | Y | | [#!/]delcontact | Delete bot contact. | Y | Y | Y | | [#!/]reload | Reloads all bot plugins | Y | Y | Y | | [#!/]updateid | Adds long_id to moderation data for groups. | Y | Y | Y | @@ -201,9 +201,9 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]mute gifs | | [#!/]mute all | -**Groups: _If "muted" message type: user is kicked if message type is posted_** +**Groups: If "muted" message type: user is kicked if message type is posted** -**SuperGroups: _A "muted" message type is auto-deleted if posted_ ** +**SuperGroups: A "muted" message type is auto-deleted if posted ** ### Ranks {#ranks} @@ -232,7 +232,7 @@ sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-d # Let's install the bot. cd $HOME -git clone https://github.com/SEEDTEAM/TeleSeed.git -b test +git clone https://github.com/SEEDTEAM/TeleSeed.git -b supergroups cd TeleSeed chmod +x launch.sh ./launch.sh install @@ -242,7 +242,7 @@ chmod +x launch.sh 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 -b test && cd TeleSeed && chmod +x launch.sh && ./launch.sh install && ./launch.sh +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 -b supergroups && cd TeleSeed && chmod +x launch.sh && ./launch.sh install && ./launch.sh ``` * * * From 8e654f8fd5b97f6eeda774bc791b4244a5fb5c75 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 04:22:35 +0000 Subject: [PATCH 05/58] Update .gitmodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 0362730..ae724f5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "tg"] path = tg - url = https://github.com/Rondoozle/tg + url = https://github.com/Rondoozle/tg.git \ No newline at end of file From 28703b17ca94055dfab4550106830041761bf2df Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 06:35:22 +0000 Subject: [PATCH 06/58] Fixed submodule --- tg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tg b/tg index c841f19..af70511 160000 --- a/tg +++ b/tg @@ -1 +1 @@ -Subproject commit c841f197b7eb9ef829e499a3e8b283a2d45ae023 +Subproject commit af705113254272b59eaab2c22a8290659d3cc690 From f8b8c2241c0770f63864165612c500a607f411ef Mon Sep 17 00:00:00 2001 From: iman daneshi Date: Wed, 9 Mar 2016 13:04:54 +0330 Subject: [PATCH 07/58] Prevent tg-cli from crash --- launch.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launch.sh b/launch.sh index b5b74dd..7a52ff7 100755 --- a/launch.sh +++ b/launch.sh @@ -110,6 +110,6 @@ else echo "Run $0 install" exit 1 fi - + rm -r ../.telegram-cli/state #Prevent tg from crash ./tg/bin/telegram-cli -k ./tg/tg-server.pub -s ./bot/seedbot.lua -l 1 -E $@ -fi \ No newline at end of file +fi From 946425d16c5f09e5e6dbf693c2594ba7c76228af Mon Sep 17 00:00:00 2001 From: iman daneshi Date: Wed, 9 Mar 2016 13:48:16 +0330 Subject: [PATCH 08/58] Bug fix --- bot/utils.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/utils.lua b/bot/utils.lua index 4c5866a..cc30bc6 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -1227,3 +1227,4 @@ function banall_by_reply(extra, success, result) return end end +end From b09a9403b919de328b8069a9d7a76931c6c18483 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 17:58:50 +0000 Subject: [PATCH 09/58] Update .gitmodules --- .gitmodules | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index ae724f5..d6bcde3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "tg"] - path = tg - url = https://github.com/Rondoozle/tg.git \ No newline at end of file +[submodule "tgl"] + path = tgl + url = https://github.com/Rondoozle/tgl.git \ No newline at end of file From c16f2ce7f8a7af8b8359bed9c90df13606dc1a5c Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 18:03:00 +0000 Subject: [PATCH 10/58] Update .gitmodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index d6bcde3..3a33b66 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "tgl"] path = tgl - url = https://github.com/Rondoozle/tgl.git \ No newline at end of file + url = https://github.com/Rondoozle/tg.git \ No newline at end of file From fad8880586e687051eb1e8371f7672dc2693acf7 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 18:12:08 +0000 Subject: [PATCH 11/58] Fix .gitmodules --- .gitmodules | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3a33b66..acc684d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "tgl"] - path = tgl - url = https://github.com/Rondoozle/tg.git \ No newline at end of file +[submodule "tg"] + path = tg + url = https://github.com/Rondoozle/tg \ No newline at end of file From c979d30ea2304f5ccaa817cf5669f2f10622fdb6 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 21:38:20 +0000 Subject: [PATCH 12/58] Updated tg --- tg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tg b/tg index af70511..dda173f 160000 --- a/tg +++ b/tg @@ -1 +1 @@ -Subproject commit af705113254272b59eaab2c22a8290659d3cc690 +Subproject commit dda173f522da0bd8ccf0a9805bec0728fc88cf48 From f232b16e94dbacfa545f56977f25cde34d9b0f0b Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 21:41:27 +0000 Subject: [PATCH 13/58] Update tg --- tg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tg b/tg index dda173f..2498545 160000 --- a/tg +++ b/tg @@ -1 +1 @@ -Subproject commit dda173f522da0bd8ccf0a9805bec0728fc88cf48 +Subproject commit 24985457b93f26b811496e08dece1e55afb8de14 From cf5c6071559cb719a96cfa489d148449db4275fa Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Wed, 9 Mar 2016 21:58:18 +0000 Subject: [PATCH 14/58] Update README.md and rm block_user.lua --- README.md | 5 +++-- bot/seedbot.lua | 1 - plugins/block_user.lua | 18 ------------------ 3 files changed, 3 insertions(+), 21 deletions(-) delete mode 100644 plugins/block_user.lua diff --git a/README.md b/README.md index d9ed894..f549fe0 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ * **Group administration via private messages** * **Only mods, owner and admin can add bots in groups** * **Arabic lock** -* **Chat list +* **Chat list** * **And more!** @@ -156,7 +156,8 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]updateid | Adds long_id to moderation data for groups. | Y | Y | Y | | [#!/]!bc [group_id] [text] | This command will send text to [group_id]| Y | Y | Y | | [#!/]leave | Bot will leave that group and can only be re-invited by an admin with bot phone number | Y | Y | Y | - +| [#!/]mp | (Mod Promote) Set user as a mod of supergroup. **TESTING** | N | Y | N | +| [#!/]md | (Mod demote) Removes user from mod of supergroup. **TESTING**| N | Y | N | ## Sudo Commands {#sudo_commands} diff --git a/bot/seedbot.lua b/bot/seedbot.lua index bd6c2b2..b038f17 100644 --- a/bot/seedbot.lua +++ b/bot/seedbot.lua @@ -223,7 +223,6 @@ function create_config( ) "invite", "all", "leave_ban", - "block_user", "supergroup", "whitelist", "msg_checks" diff --git a/plugins/block_user.lua b/plugins/block_user.lua deleted file mode 100644 index 837cba1..0000000 --- a/plugins/block_user.lua +++ /dev/null @@ -1,18 +0,0 @@ -local function run(msg, matches) - if matches[1] == "block" then - local user_id = "user#id"..matches[2] - block_user(user_id, ok_cb, false) - end - if matches[1] == "unblock" then - local user_id = "user#id"..matches[2] - unblock_user(user_id, ok_cb, false) - end -end - -return { - patterns = { - "^[!/](block) (.*)$", - "^[!/](unblock) (.*)$" - }, - run = run -} From 0a3b677434ff16f2f17d94ec7d92509794075867 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Thu, 10 Mar 2016 17:12:03 +0000 Subject: [PATCH 15/58] Fix Log SuperGroup error --- plugins/admin.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index 2b46412..46e3aa4 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -5,7 +5,7 @@ local function check_member_logadd(cb_extra, success, result) local msg = cb_extra.msg for k,v in pairs(result) do local member_id = v.peer_id - if member_id == our_id then + if member_id ~= our_id then local GBan_log = 'GBan_log' if not data[tostring(GBan_log)] then data[tostring(GBan_log)] = {} @@ -30,7 +30,7 @@ local function check_member_logrem(cb_extra, success, result) local msg = cb_extra.msg for k,v in pairs(result) do local member_id = v.peer_id - if member_id == our_id then + if member_id ~= our_id then local GBan_log = 'GBan_log' if not data[tostring(GBan_log)] then data[tostring(GBan_log)] = nil @@ -68,7 +68,7 @@ end local function logadd(msg) local data = load_data(_config.moderation.data) local receiver = get_receiver(msg) - channel_get_admins(receiver, check_member_logadd,{receiver = receiver, data = data, msg = msg}) + channel_get_users(receiver, check_member_logadd,{receiver = receiver, data = data, msg = msg}) end --Function to remove log supergroup From ec64babdd1993a77677de5e28636d09200e341ff Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Thu, 10 Mar 2016 18:27:57 +0000 Subject: [PATCH 16/58] Fix Banhammer.lua --- plugins/banhammer.lua | 68 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/plugins/banhammer.lua b/plugins/banhammer.lua index f09f902..bad9d7a 100644 --- a/plugins/banhammer.lua +++ b/plugins/banhammer.lua @@ -1,6 +1,5 @@ local function pre_process(msg) - local data = load_data(_config.moderation.data) -- SERVICE MESSAGE if msg.action and msg.action.type then local action = msg.action.type @@ -63,7 +62,8 @@ local function pre_process(msg) return msg end -- banned user is talking ! - if msg.to.type == 'chat' or msg.to.type == 'channel' then + 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 @@ -103,18 +103,15 @@ local function kick_ban_res(extra, success, result) local get_cmd = extra.get_cmd if get_cmd == "kick" then if member_id == from_id then - send_large_msg(receiver, "You can't kick yourself") - return + return send_large_msg(receiver, "You can't kick yourself") end if is_momod2(member_id, chat_id) and not is_admin2(sender) then - send_large_msg(receiver, "You can't kick mods/owner/admins") - return + return send_large_msg(receiver, "You can't kick mods/owner/admins") end - kick_user(member_id, chat_id) + kick_user(member_id, chat_id) elseif get_cmd == 'ban' then if is_momod2(member_id, chat_id) and not is_admin2(sender) then - send_large_msg(receiver, "You can't ban mods/owner/admins") - return + send_large_msg(receiver, "You can't ban mods/owner/admins") end send_large_msg(receiver, 'User @'..member..' ['..member_id..'] banned') ban_user(member_id, chat_id) @@ -125,11 +122,11 @@ local function kick_ban_res(extra, success, result) return 'User '..user_id..' unbanned' elseif get_cmd == 'banall' then send_large_msg(receiver, 'User @'..member..' ['..member_id..'] globally banned') - banall_user(member_id) + banall_user(member_id) elseif get_cmd == 'unbanall' then send_large_msg(receiver, 'User @'..member..' ['..member_id..'] globally unbanned') - unbanall_user(member_id) - end + unbanall_user(member_id) + end end local function run(msg, matches) @@ -171,17 +168,16 @@ local support_id = msg.from.id return ban_list(chat_id) end if matches[1]:lower() == 'ban' then-- /ban - if type(msg.reply_id)~="nil" and is_momod(msg) then - print('ok1') + if msg.reply_id) and is_momod(msg) then if is_admin1(msg) then - print('ok2') - msgr = get_message(msg.reply_id,ban_by_reply_admins, false) + 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 - elseif string.match(matches[2], '^%d+$') then + if string.match(user_id, '^%d+$') then if tonumber(matches[2]) == tonumber(our_id) then return end @@ -194,7 +190,7 @@ local support_id = msg.from.id local print_name = user_print_name(msg.from):gsub("‮", "") local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] baned user ".. matches[2]) - ban_user(matches[2], msg.to.id) + ban_user(user_id, chat_id) else local cbres_extra = { chat_id = msg.to.id, @@ -202,9 +198,10 @@ local support_id = msg.from.id from_id = msg.from.id, chat_type = msg.to.type } + local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) - end + end end @@ -230,6 +227,7 @@ local support_id = msg.from.id from_id = msg.from.id, chat_type = msg.to.type } + local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -242,7 +240,9 @@ if matches[1]:lower() == 'kick' then else msgr = get_message(msg.reply_id,Kick_by_reply, false) end - elseif string.match(matches[2], '^%d+$') then + end + + if string.match(matches[2], '^%d+$') then if tonumber(matches[2]) == tonumber(our_id) then return end @@ -252,9 +252,8 @@ if matches[1]:lower() == 'kick' then 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 - print("sexy") + local user_id = matches[2] + local chat_id = msg.to.id local print_name = user_print_name(msg.from):gsub("‮", "") local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] kicked user ".. matches[2]) @@ -266,6 +265,7 @@ if matches[1]:lower() == 'kick' then from_id = msg.from.id, chat_type = msg.to.type } + local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -289,13 +289,14 @@ end end banall_user(targetuser) return 'User ['..user_id..' ] globally banned' - else + else local cbres_extra = { chat_id = msg.to.id, get_cmd = 'banall', from_id = msg.from.id, chat_type = msg.to.type } + local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -310,12 +311,13 @@ end unbanall_user(user_id) return 'User ['..user_id..' ] globally unbanned' else - local cbres_extra = { - chat_id = msg.to.id, - get_cmd = 'unbanall', - from_id = msg.from.id, - chat_type = msg.to.type - } + local cbres_extra = { + chat_id = msg.to.id, + get_cmd = 'unbanall', + from_id = msg.from.id, + chat_type = msg.to.type + } + local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -332,14 +334,14 @@ return { "^[#!/]([Bb]anlist) (.*)$", "^[#!/]([Bb]anlist)$", "^[#!/]([Gg]banlist)$", - "^[#!/]([Kk]ickme)", - "^[#!/]([Kk]ick)$", - "^[#!/]([Bb]an)$", "^[#!/]([Bb]an) (.*)$", "^[#!/]([Uu]nban) (.*)$", "^[#!/]([Uu]nbanall) (.*)$", "^[#!/]([Uu]nbanall)$", "^[#!/]([Kk]ick) (.*)$", + "^[#!/]([Kk]ickme)$", + "^[#!/]([Kk]ick)$", + "^[#!/]([Bb]an)$", "^[#!/]([Uu]nban)$", "^[#!/]([Ii]d)$", "^!!tgservice (.+)$" From 9f7c7982c3dad0843ad3b5ca5fd6de19e9b42e5e Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Thu, 10 Mar 2016 23:24:16 +0000 Subject: [PATCH 17/58] Added missing directories and fixed mehtods --- .../supergroups/[SuperGroup_id]memberlist.txt | 1 + .../kicked/[SuperGroup_id]kickedlist.txt | 1 + plugins/admin.lua | 72 ++++++------------- plugins/supergroup.lua | 4 +- 4 files changed, 24 insertions(+), 54 deletions(-) create mode 100644 groups/lists/supergroups/[SuperGroup_id]memberlist.txt create mode 100644 groups/lists/supergroups/kicked/[SuperGroup_id]kickedlist.txt diff --git a/groups/lists/supergroups/[SuperGroup_id]memberlist.txt b/groups/lists/supergroups/[SuperGroup_id]memberlist.txt new file mode 100644 index 0000000..8c8627f --- /dev/null +++ b/groups/lists/supergroups/[SuperGroup_id]memberlist.txt @@ -0,0 +1 @@ +[SuperGroup_id]memberlist! \ No newline at end of file diff --git a/groups/lists/supergroups/kicked/[SuperGroup_id]kickedlist.txt b/groups/lists/supergroups/kicked/[SuperGroup_id]kickedlist.txt new file mode 100644 index 0000000..0309afc --- /dev/null +++ b/groups/lists/supergroups/kicked/[SuperGroup_id]kickedlist.txt @@ -0,0 +1 @@ +[SuperGroup_id]kickedlist! \ No newline at end of file diff --git a/plugins/admin.lua b/plugins/admin.lua index 46e3aa4..b9d8450 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -1,53 +1,3 @@ ---check member add log SuperGroup -local function check_member_logadd(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) do - local member_id = v.peer_id - if member_id ~= our_id then - local GBan_log = 'GBan_log' - if not data[tostring(GBan_log)] then - data[tostring(GBan_log)] = {} - save_data(_config.moderation.data, data) - end - data[tostring(GBan_log)][tostring(msg.to.id)] = msg.to.peer_id - save_data(_config.moderation.data, data) - local text = 'Log_SuperGroup has has been set!' - reply_msg(msg.id,text,ok_cb,false) - return - else - reply_msg(msg.id,"Failed to set log SuperGroup",ok_cb, false) - return - end - end -end - ---Check Members rem log SuperGroup -local function check_member_logrem(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) do - local member_id = v.peer_id - if member_id ~= our_id then - local GBan_log = 'GBan_log' - if not data[tostring(GBan_log)] then - data[tostring(GBan_log)] = nil - save_data(_config.moderation.data, data) - end - data[tostring(GBan_log)][tostring(msg.to.id)] = nil - save_data(_config.moderation.data, data) - local text = 'Log_SuperGroup has has been removed!' - reply_msg(msg.id,text,ok_cb,false) - return - else - reply_msg(msg.id,"Failed to remove log SuperGroup",ok_cb,false) - return - end - end -end - local function set_bot_photo(msg, success, result) local receiver = get_receiver(msg) if success then @@ -68,14 +18,32 @@ end local function logadd(msg) local data = load_data(_config.moderation.data) local receiver = get_receiver(msg) - channel_get_users(receiver, check_member_logadd,{receiver = receiver, data = data, msg = msg}) + local GBan_log = 'GBan_log' + if not data[tostring(GBan_log)] then + data[tostring(GBan_log)] = {} + save_data(_config.moderation.data, data) + end + data[tostring(GBan_log)][tostring(msg.to.id)] = msg.to.peer_id + save_data(_config.moderation.data, data) + local text = 'Log_SuperGroup has has been set!' + reply_msg(msg.id,text,ok_cb,false) + return end --Function to remove log supergroup local function logrem(msg) local data = load_data(_config.moderation.data) local receiver = get_receiver(msg) - channel_get_users(receiver, check_member_logrem,{receiver = receiver, data = data, msg = msg}) + local GBan_log = 'GBan_log' + if not data[tostring(GBan_log)] then + data[tostring(GBan_log)] = nil + save_data(_config.moderation.data, data) + end + data[tostring(GBan_log)][tostring(msg.to.id)] = nil + save_data(_config.moderation.data, data) + local text = 'Log_SuperGroup has has been removed!' + reply_msg(msg.id,text,ok_cb,false) + return end diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index 8f021b9..226a2f1 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -686,9 +686,9 @@ function get_message_callback(extra, success, result) elseif get_cmd == "setowner" then local group_owner = data[tostring(result.to.peer_id)]['set_owner'] if group_owner then + local channel_id = 'channel#id'..result.to.peer_id if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then - local channel_id = 'channel#id'..result.to.peer_id - local user = "user#id"..group_owner + local user = "user#id"..group_owner channel_demote(channel_id, user, ok_cb, false) end local user_id = "user#id"..result.from.peer_id From a056bd199ed00d33e59c8a383a1b09624ba1f658 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Fri, 11 Mar 2016 10:14:36 +0000 Subject: [PATCH 18/58] Fixed banhammer --- plugins/banhammer.lua | 68 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/plugins/banhammer.lua b/plugins/banhammer.lua index bad9d7a..5624939 100644 --- a/plugins/banhammer.lua +++ b/plugins/banhammer.lua @@ -1,5 +1,6 @@ local function pre_process(msg) + local data = load_data(_config.moderation.data) -- SERVICE MESSAGE if msg.action and msg.action.type then local action = msg.action.type @@ -62,8 +63,7 @@ local function pre_process(msg) return msg end -- banned user is talking ! - if msg.to.type == 'chat' then - local data = load_data(_config.moderation.data) + if msg.to.type == 'chat' or msg.to.type == 'channel' then 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 @@ -103,15 +103,18 @@ local function kick_ban_res(extra, success, result) local get_cmd = extra.get_cmd if get_cmd == "kick" then if member_id == from_id then - return send_large_msg(receiver, "You can't kick yourself") + send_large_msg(receiver, "You can't kick yourself") + return 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") + send_large_msg(receiver, "You can't kick mods/owner/admins") + return end - kick_user(member_id, chat_id) + kick_user(member_id, chat_id) elseif get_cmd == 'ban' then if is_momod2(member_id, chat_id) and not is_admin2(sender) then - send_large_msg(receiver, "You can't ban mods/owner/admins") + send_large_msg(receiver, "You can't ban mods/owner/admins") + return end send_large_msg(receiver, 'User @'..member..' ['..member_id..'] banned') ban_user(member_id, chat_id) @@ -122,11 +125,11 @@ local function kick_ban_res(extra, success, result) return 'User '..user_id..' unbanned' elseif get_cmd == 'banall' then send_large_msg(receiver, 'User @'..member..' ['..member_id..'] globally banned') - banall_user(member_id) + banall_user(member_id) elseif get_cmd == 'unbanall' then send_large_msg(receiver, 'User @'..member..' ['..member_id..'] globally unbanned') - unbanall_user(member_id) - end + unbanall_user(member_id) + end end local function run(msg, matches) @@ -168,16 +171,15 @@ local support_id = msg.from.id return ban_list(chat_id) end if matches[1]:lower() == 'ban' then-- /ban - if msg.reply_id) and is_momod(msg) then + if type(msg.reply_id)~="nil" and is_momod(msg) then if is_admin1(msg) then - local msgr = get_message(msg.reply_id,ban_by_reply_admins, false) + 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(user_id, '^%d+$') then + elseif string.match(matches[2], '^%d+$') then if tonumber(matches[2]) == tonumber(our_id) then return end @@ -189,8 +191,10 @@ local support_id = msg.from.id end local print_name = user_print_name(msg.from):gsub("‮", "") local name = print_name:gsub("_", "") + local receiver = get_receiver(msg) savelog(msg.to.id, name.." ["..msg.from.id.."] baned user ".. matches[2]) - ban_user(user_id, chat_id) + ban_user(matches[2], msg.to.id) + send_large_msg(receiver, 'User ['..matches[2]..'] banned') else local cbres_extra = { chat_id = msg.to.id, @@ -198,10 +202,9 @@ local support_id = msg.from.id from_id = msg.from.id, chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) - end + end end @@ -227,7 +230,6 @@ local support_id = msg.from.id from_id = msg.from.id, chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -240,9 +242,7 @@ if matches[1]:lower() == 'kick' then else msgr = get_message(msg.reply_id,Kick_by_reply, false) end - end - - if string.match(matches[2], '^%d+$') then + elseif string.match(matches[2], '^%d+$') then if tonumber(matches[2]) == tonumber(our_id) then return end @@ -252,8 +252,9 @@ if matches[1]:lower() == 'kick' then 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 + local user_id = matches[2] + local chat_id = msg.to.id + print("sexy") local print_name = user_print_name(msg.from):gsub("‮", "") local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] kicked user ".. matches[2]) @@ -265,7 +266,6 @@ if matches[1]:lower() == 'kick' then from_id = msg.from.id, chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -289,14 +289,13 @@ end end banall_user(targetuser) return 'User ['..user_id..' ] globally banned' - else + else local cbres_extra = { chat_id = msg.to.id, get_cmd = 'banall', from_id = msg.from.id, chat_type = msg.to.type } - local username = matches[2] local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -311,13 +310,12 @@ end unbanall_user(user_id) return 'User ['..user_id..' ] globally unbanned' else - local cbres_extra = { - chat_id = msg.to.id, - get_cmd = 'unbanall', - from_id = msg.from.id, - chat_type = msg.to.type - } - local username = matches[2] + local cbres_extra = { + chat_id = msg.to.id, + get_cmd = 'unbanall', + from_id = msg.from.id, + chat_type = msg.to.type + } local username = string.gsub(matches[2], '@', '') resolve_username(username, kick_ban_res, cbres_extra) end @@ -334,14 +332,14 @@ return { "^[#!/]([Bb]anlist) (.*)$", "^[#!/]([Bb]anlist)$", "^[#!/]([Gg]banlist)$", + "^[#!/]([Kk]ickme)", + "^[#!/]([Kk]ick)$", + "^[#!/]([Bb]an)$", "^[#!/]([Bb]an) (.*)$", "^[#!/]([Uu]nban) (.*)$", "^[#!/]([Uu]nbanall) (.*)$", "^[#!/]([Uu]nbanall)$", "^[#!/]([Kk]ick) (.*)$", - "^[#!/]([Kk]ickme)$", - "^[#!/]([Kk]ick)$", - "^[#!/]([Bb]an)$", "^[#!/]([Uu]nban)$", "^[#!/]([Ii]d)$", "^!!tgservice (.+)$" From 48cae219d975d4ac09a90e25ce25ba8d828713c0 Mon Sep 17 00:00:00 2001 From: Arman Date: Fri, 11 Mar 2016 19:20:48 +0330 Subject: [PATCH 19/58] fixed markread part --- bot/seedbot.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bot/seedbot.lua b/bot/seedbot.lua index b038f17..d442671 100644 --- a/bot/seedbot.lua +++ b/bot/seedbot.lua @@ -19,12 +19,17 @@ function on_msg_receive (msg) local receiver = get_receiver(msg) print(receiver) --vardump(msg) + --vardump(msg) msg = pre_process_service_msg(msg) if msg_valid(msg) then msg = pre_process_msg(msg) if msg then match_plugins(msg) - -- mark_read(receiver, ok_cb, false) + if redis:get("bot:markread") then + if redis:get("bot:markread") == "on" then + mark_read(receiver, ok_cb, false) + end + end end end end From 9f083d3a57a3ae46b216139435c9d685d272524d Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Fri, 11 Mar 2016 19:41:10 +0000 Subject: [PATCH 20/58] Update anti_spam.lua --- plugins/anti_spam.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/anti_spam.lua b/plugins/anti_spam.lua index 8f0f9fe..a2bfff1 100644 --- a/plugins/anti_spam.lua +++ b/plugins/anti_spam.lua @@ -55,8 +55,8 @@ local function pre_process(msg) --Load moderation data local data = load_data(_config.moderation.data) - if data[tostring(msg.to.id)] and not data[tostring(msg.to.id)]['group_type'] == 'GBan_log' then - --Check if flood is one or off + if data[tostring(msg.to.id)] then + --Check if flood is on or off if data[tostring(msg.to.id)]['settings']['flood'] == 'no' then return msg end From 0e9a14c92dafc47c5e52dcc4ed22955c751e7cbc Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Fri, 11 Mar 2016 20:04:05 +0000 Subject: [PATCH 21/58] Update tg --- tg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tg b/tg index 2498545..33cf197 160000 --- a/tg +++ b/tg @@ -1 +1 @@ -Subproject commit 24985457b93f26b811496e08dece1e55afb8de14 +Subproject commit 33cf197fe2e0b2ef8cbadb9d71ea5ff5454ef488 From 5ff11ac3a338313091b602964d13d33419a30630 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Fri, 11 Mar 2016 23:49:41 +0000 Subject: [PATCH 22/58] MAJOR SECURITY UPDATE! --- plugins/admin.lua | 6 ++++ plugins/ingroup.lua | 75 ++++++++++++++++++++++++++++++--------------- plugins/inrealm.lua | 6 ++++ 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index b9d8450..2be0389 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -200,10 +200,16 @@ local function run(msg,matches) import_chat_link(hash,ok_cb,false) end if matches[1] == "contactlist" then + if not is_sudo(msg) then-- Sudo only + return + end 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] == "delcontact" then + if not is_sudo(msg) then-- Sudo only + return + end del_contact("user#id"..matches[2],ok_cb,false) return "User "..matches[2].." removed from contact list" end diff --git a/plugins/ingroup.lua b/plugins/ingroup.lua index 58238a1..e38ea4b 100644 --- a/plugins/ingroup.lua +++ b/plugins/ingroup.lua @@ -832,7 +832,6 @@ local function modlist(msg) end local function callbackres(extra, success, result) ---vardump(result) local user = result.peer_id local name = string.gsub(result.print_name, "_", " ") local chat = 'chat#id'..extra.chatid @@ -948,32 +947,59 @@ local function run(msg, matches) end end if msg.to.type == 'chat' then - 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 is_admin1(msg) or not is_support(msg.from.id) then-- Admin only + if matches[1] == 'add' and not matches[2] then + if not is_admin1(msg) or not is_support(msg.from.id) then-- Admin only + savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to add group [ "..msg.to.id.." ]") + return + end + if is_realm(msg) then + return 'Error: Already a realm.' + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added group [ "..msg.to.id.." ]") + print("group "..msg.to.print_name.."("..msg.to.id..") added") + return modadd(msg) + end + if matches[1] == 'add' and matches[2] == 'realm' then + if not is_sudo(msg) then-- Admin only + savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to add realm [ "..msg.to.id.." ]") + return + end + if is_group(msg) then + return 'Error: Already a group.' + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added realm [ "..msg.to.id.." ]") + 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 + if not is_admin1(msg) or not is_support(msg.from.id) then-- Admin only + savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to remove group [ "..msg.to.id.." ]") + return + end + if not is_group(msg) then + return 'Error: Not a group.' + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] removed group [ "..msg.to.id.." ]") + print("group "..msg.to.print_name.."("..msg.to.id..") removed") + return modrem(msg) + end + if matches[1] == 'rem' and matches[2] == 'realm' then + if not is_sudo(msg) then-- Sudo only + savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to remove realm [ "..msg.to.id.." ]") + return + end + if not is_realm(msg) then + return 'Error: Not a realm.' + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] removed realm [ "..msg.to.id.." ]") + print("group "..msg.to.print_name.."("..msg.to.id..") removed as a realm") + return realmrem(msg) + end + end if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "group" then return automodadd(msg) end - --[[Experimental if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "super_group" then local chat_id = get_receiver(msg) @@ -983,7 +1009,6 @@ if msg.to.type == 'chat' then end --chat_upgrade(chat_id, ok_cb, false) end ]] - if matches[1] == 'chat_created' and msg.from.id == 0 and group_type == "realm" then return autorealmadd(msg) end diff --git a/plugins/inrealm.lua b/plugins/inrealm.lua index 177fd1a..ef17bac 100644 --- a/plugins/inrealm.lua +++ b/plugins/inrealm.lua @@ -944,6 +944,9 @@ function run(msg, matches) end end if matches[1] == 'addadmin' then + if not is_sudo(msg) then-- Sudo only + return + end if string.match(matches[2], '^%d+$') then local admin_id = matches[2] print("user "..admin_id.." has been promoted as admin") @@ -955,6 +958,9 @@ function run(msg, matches) end end if matches[1] == 'removeadmin' then + if not is_sudo(msg) then-- Sudo only + return + end if string.match(matches[2], '^%d+$') then local admin_id = matches[2] print("user "..admin_id.." has been demoted") From 669101c8c984ec1f3025c925392aaeb224c2530f Mon Sep 17 00:00:00 2001 From: amir-sereen Date: Mon, 14 Mar 2016 14:01:35 +0330 Subject: [PATCH 23/58] Update seedbot.lua --- bot/seedbot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/seedbot.lua b/bot/seedbot.lua index d442671..c6a0b70 100644 --- a/bot/seedbot.lua +++ b/bot/seedbot.lua @@ -240,7 +240,7 @@ An advanced administration bot based on TG-CLI written in Lua https://github.com/SEEDTEAM/TeleSeed Admins -@Empero [Founder] +@iwals [Founder] @imandaneshi [Developer] @POTUS [Developer] @seyedan25 [Manager] From 891b01291ad750a2d16270cd3716c2505be6ee93 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Thu, 17 Mar 2016 01:54:19 +0000 Subject: [PATCH 24/58] Update tg --- tg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tg b/tg index 33cf197..ad44d65 160000 --- a/tg +++ b/tg @@ -1 +1 @@ -Subproject commit 33cf197fe2e0b2ef8cbadb9d71ea5ff5454ef488 +Subproject commit ad44d65cd29b3aca58ee37439aa04a97d4cd59e7 From 9a2de933f3903081205d9ccf4eeb5dceed69ca2a Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Thu, 17 Mar 2016 02:02:52 +0000 Subject: [PATCH 25/58] Fixed duplication of mutes --- bot/utils.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/utils.lua b/bot/utils.lua index cc30bc6..485cea8 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -1026,6 +1026,7 @@ function has_mutes(chat_id) mutes = {[1]= "Audio: no",[2]= "Photo: no",[3]= "All: no",[4]="Documents: no",[5]="Text: no",[6]= "Video: no",[7]= "Gifs: no"} local hash = 'mute:'..chat_id for k,v in pairsByKeys(mutes) do + setting = v local has_mutes = redis:sismember(hash, mutes) return has_mutes or false end From c11e0c1cdfbc3ce6d7183763aa2de4923625a6ce Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Thu, 17 Mar 2016 02:57:13 +0000 Subject: [PATCH 26/58] Update mutes fix --- bot/utils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/utils.lua b/bot/utils.lua index 485cea8..a70e539 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -1027,7 +1027,7 @@ function has_mutes(chat_id) local hash = 'mute:'..chat_id for k,v in pairsByKeys(mutes) do setting = v - local has_mutes = redis:sismember(hash, mutes) + local has_mutes = redis:sismember(hash, settings) return has_mutes or false end end From c3a15ce163175ec8fb0bfc54e606d13233016ad2 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Thu, 17 Mar 2016 17:11:01 +0200 Subject: [PATCH 27/58] Fix msg_checks --- plugins/msg_checks.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/msg_checks.lua b/plugins/msg_checks.lua index 17639db..5bd1054 100644 --- a/plugins/msg_checks.lua +++ b/plugins/msg_checks.lua @@ -10,6 +10,8 @@ if is_chat_msg(msg) or is_super_group(msg) then local to_chat = msg.to.type == 'chat' if data[tostring(msg.to.id)] and data[tostring(msg.to.id)]['settings'] then settings = data[tostring(msg.to.id)]['settings'] + else + return end if settings.lock_arabic then lock_arabic = settings.lock_arabic @@ -280,4 +282,4 @@ return { pre_process = pre_process } --End msg_checks.lua ---By @Rondoozle \ No newline at end of file +--By @Rondoozle From d3a0ab708bb6d868d29b1487f1266f9e52b5c4a0 Mon Sep 17 00:00:00 2001 From: Rondoozle Date: Thu, 17 Mar 2016 19:44:05 -0400 Subject: [PATCH 28/58] Update utils.lua --- bot/utils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/utils.lua b/bot/utils.lua index a70e539..6837d1f 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -1027,7 +1027,7 @@ function has_mutes(chat_id) local hash = 'mute:'..chat_id for k,v in pairsByKeys(mutes) do setting = v - local has_mutes = redis:sismember(hash, settings) + local has_mutes = redis:sismember(hash, setting) return has_mutes or false end end From 5bd5a05f8b1189cddd641ad06a5ada58202a5b7b Mon Sep 17 00:00:00 2001 From: Shahab Date: Fri, 18 Mar 2016 17:13:26 +0330 Subject: [PATCH 29/58] Update seedbot.lua --- bot/seedbot.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bot/seedbot.lua b/bot/seedbot.lua index c6a0b70..6363c54 100644 --- a/bot/seedbot.lua +++ b/bot/seedbot.lua @@ -255,6 +255,9 @@ Vamptacus Our channels @teleseedch [English] @iranseed [persian] + +Our website : +http://teleseed.seedteam.org/ ]], help_text_realm = [[ Realm Commands: From 1be4922919698cc3648655d24357bab9f97d5c5d Mon Sep 17 00:00:00 2001 From: Shahab Date: Fri, 18 Mar 2016 17:17:36 +0330 Subject: [PATCH 30/58] Update seedbot.lua --- bot/seedbot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/seedbot.lua b/bot/seedbot.lua index 6363c54..09e98d4 100644 --- a/bot/seedbot.lua +++ b/bot/seedbot.lua @@ -256,7 +256,7 @@ Our channels @teleseedch [English] @iranseed [persian] -Our website : +Our website http://teleseed.seedteam.org/ ]], help_text_realm = [[ From 497b2a22db9c616795864028412c8ea1d8f7b91a Mon Sep 17 00:00:00 2001 From: iman daneshi Date: Fri, 18 Mar 2016 19:30:35 +0330 Subject: [PATCH 31/58] Bug fix --- plugins/supergroup.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index 226a2f1..15819a3 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -955,6 +955,7 @@ if get_cmd == "channel_block" then savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..v.peer_id.."]") end kick_user(user_id, channel_id) + return end end elseif get_cmd == "setadmin" then @@ -980,8 +981,10 @@ elseif get_cmd == "setadmin" then local receiver = channel_id local user_id = v.peer_id promote_admin(receiver, member_username, user_id) + end send_large_msg(channel_id, text) + return end elseif get_cmd == 'setowner' then for k,v in pairs(result) do From 9591157a79471310d5afd8c2f5540d0f231b389c Mon Sep 17 00:00:00 2001 From: iman daneshi Date: Sat, 19 Mar 2016 14:09:53 +0330 Subject: [PATCH 32/58] Update inrealm.lua --- plugins/inrealm.lua | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/plugins/inrealm.lua b/plugins/inrealm.lua index ef17bac..9c8b050 100644 --- a/plugins/inrealm.lua +++ b/plugins/inrealm.lua @@ -722,17 +722,15 @@ function run(msg, matches) user_info(user_id, cb_user_info, {receiver = receiver}) end - if not is_sudo(msg) and not is_realm(msg) and is_admin1(msg) then - return + if not is_sudo(msg) then + if is_realm(msg) and is_admin1(msg) then + print("Admin detected") + else + return + end end if matches[1] == 'creategroup' and matches[2] then - if not is_momod(msg) then - return - end - if not is_sudo(msg) or is_admin1(msg) and is_realm(msg) then - return "You cant create groups!" - end group_name = matches[2] group_type = 'group' return create_group(msg) @@ -749,9 +747,9 @@ function run(msg, matches) end]] if matches[1] == 'createrealm' and matches[2] then - if not is_sudo(msg) or not is_admin1(msg) and is_realm(msg) then - return "You cant create groups!" - end + if not is_sudo(msg) then + return "Sudo users only !" + end group_name = matches[2] group_type = 'realm' return create_realm(msg) From f7db2c7fd0f3e737da6576c71b19f4a94c46f40c Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Sat, 19 Mar 2016 21:17:38 +0200 Subject: [PATCH 33/58] Fix README --- README.md | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index f549fe0..20aa5d3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ * * * -##Commands +## Commands TeleSeed has several commands that are only usable at certain ranks. @@ -40,12 +40,12 @@ TeleSeed has several commands that are only usable at certain ranks. |:--------|:------------| | [#!/]help | Returns help text. | | [#!/]superhelp | Returns SuperGroup help text. | -| [#!/]Chats | Returns public chats in a message(s). | -| [#!/]Chatlist | Returns public chats in a .txt document. | +| [#!/]chats | Returns public chats in a message(s). | +| [#!/]chatlist | Returns public chats in a .txt document. | | [#!/]join [GroupID] | Join a public chat by id | -#Moderator commands {#moderator_commands} +## Moderator commands {#moderator_commands} | Command | Description | Groups? | SuperGroups? | |:--------|:------------|:--------|:-------------| @@ -60,7 +60,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]kick | kicks user from group. | Y | N | | [#!/]ban | Bans user from the group/SuperGroup. | Y | Y | | [#!/]unban | Unbans user from group/SuperGroup. | Y | Y | -| [#!/]id [username|reply] | For userID's: !id @username (**ONLY IN SuperSroups**) or reply `!id` in any group. | Y | Y | +| [#!/]id [username|reply] | For userID's: !id @username (**ONLY IN SuperSroups**) or reply `!id` in any group. | Y | Y | | [#!/]id from | Returns ID of user a message is forwarded from. | N | Y | | [#!/]kickme | Kicks user from SuperGroup / In SuperGroup: **Must be unblocked by owner or use `#join` by pm to return** | Y | Y | | [#!/]setowner | Sets group/SuperGroup owner. | Y | Y | @@ -82,27 +82,27 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]mute [mute](#mutes) | mute group message types. | Y | Y | | [#!/]unmute [mute](#mutes) | unmute group message types. | Y | Y | | [#!/]setflood [value](#settings) | Set [value] as flood sensitivity.| Y | Y | -| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat. ***If a muted user posts a message, the message is deleted automaically only owners can mute | mods and owners can unmute*** | Y | Y | +| [#!/]muteuser [username|id|reply] | Mute and unmute a user in chat. ***If a muted user posts a message, the message is deleted automaically only owners can mute | mods and owners can unmute*** | Y | Y | | [#!/]mutelist | Returns list of muted users in group/SuperGroup. | Y | Y | | [#!/]muteslist | Returns mutes for group/SuperGroup. | Y | Y | | [#!/]settings | Returns a list of group/SuperGroup settings. | Y | Y | | [#!/]stats | Returns simple message statistics in a .txt document. | Y | Y | | [#!/]statslist | Returns simple message statistics in a message. | Y | Y | | [#!/]banlist | Returns group/SuperGroup banlist. | Y | Y | -| [#!/]clean [rules|about|modlist|mutelist] | Clears rules, about, modlist, or mutelist | Y | Y | +| [#!/]clean [rules|about|modlist|mutelist] | Clears rules, about, modlist, or mutelist | Y | Y | | [#!/]del | Deletes a message by reply. | N | Y | | [#!/]res [username] | Returns users name and id by username. | Y | Y | -| [#!/]log | Returns group logs.***In SuperGroups:*** Search for kick reasons using [#RTL|#spam|#lockmember] | Y | Y | +| [#!/]log | Returns group logs.***In SuperGroups:*** Search for kick reasons using [#RTL|#spam|#lockmember] | Y | Y | -##Owner commands {#moderator_commands} +## Owner commands {#moderator_commands} | Command | Description | groups/SuperGroups? | In private? | |:--------|:------------|:----------------------|:-------------| -| [#!/]muteuser [username/id/reply] | Mute and unmute a user in chat.***If a muted user posts a message, the message is deleted automaically / only owners can mute / mods and owners can unmute*** | | N | +| [#!/]muteuser [username|id|reply] | Mute and unmute a user in chat.***If a muted user posts a message, the message is deleted automaically / only owners can mute / mods and owners can unmute*** | | N | | [#!/]all | Returns all available information about current group. | Y | N | | [#!/]all [GroupID] | Returns all available information about group by GroupID. | Y | N | -| [#!/]owners [GroupID] [kick|ban|unban] [UserID] | Kick, ban, or unban a user from a group by GroupID and UserID. | N | Y | -| [#!/]owners [GroupID] clean [modlist|rules|about] | Clear options by GroupID. | N | Y | +| [#!/]owners [GroupID] [kick|ban|unban] [UserID] | Kick, ban, or unban a user from a group by GroupID and UserID. | N | Y | +| [#!/]owners [GroupID] clean [modlist|rules|about] | Clear options by GroupID. | N | Y | | [#!/]owners [GroupID] setflood [value] | Set flood for a group by GroupID and a value [1-5]. | N | Y | | [#!/]owners [GroupID] lock [setting] | Lock settings for a group by GroupID. | N | Y | | [#!/]owner [GroupID] unlock [setting] | Unlock settings for a group by GroupID. | N | Y | @@ -112,8 +112,8 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]changrules [GroupID] [rules] | Change a group's rules by GroupID. | N | Y | | [#!/]changeabout [GroupID] [about] | Change a group's about by GroupID. | N | Y | | [#!/]loggroup [GroupID] | get group logs by GroupID. | N | Y | - -##Admin commands + +## Admin commands | Command | Description | Groups? | SuperGroups? | Realms? | |:--------|:------------|:--------|:-------------|:--------| @@ -123,8 +123,8 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]rem | Remove a group from moderation.json. | Y | Y | Y | | [#!/]rem [GroupID] | Remove a group from moderation by GroupID. | Y | Y | Y | | [#!/]setname [Name] | Set realm name. | N | -- | Y | -| [#!/]setabout [group|sgroup] [GroupID] [Text] | Set a group's about text. | Y | Y | Y | -| [#!/]setrules [group|sgroup] [GroupID] [Text] | Set a group's rules. | Y | Y | Y | +| [#!/]setabout [group|sgroup] [GroupID] [Text] | Set a group's about text. | Y | Y | Y | +| [#!/]setrules [group|sgroup] [GroupID] [Text] | Set a group's rules. | Y | Y | Y | | [#!/]lock [GroupID] [setting] | Lock a group's setting. | Y | Y | Y | | [#!/]lock [GroupID] [setting] | Lock a group's setting. | Y | Y | Y | | [#!/]unlock [GroupID] [setting] | Unlock a group's setting. | Y | Y | Y | @@ -135,9 +135,9 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]remlog | Remove a Log_SuperGroup for GBan log. | N | Y | N | | [#!/]kill chat [GroupID] | Kick all users and remove a group from moderation. | Y | Y | Y | | [#!/]kill realm [RealmID] | Kick all users and remove a realm from moderation. | Y | Y | Y | -| [#!/]banall [id|usename] | Ban a user from all moderated groups where bot is an admin (#global_ban) | Y | Y | Y | -| [#!/]unbanall [id|usename] | Unban a user from all moderated groups where bot is an admin (#global_ban) | Y | Y | Y | -| [#!/]gbanlist [id|usename] | Returns a list of all globally banned user | Y | Y | Y | +| [#!/]banall [id|usename] | Ban a user from all moderated groups where bot is an admin (#global_ban) | Y | Y | Y | +| [#!/]unbanall [id|usename] | Unban a user from all moderated groups where bot is an admin (#global_ban) | Y | Y | Y | +| [#!/]gbanlist [id|usename] | Returns a list of all globally banned user | Y | Y | Y | | [#!/]list groups | Returns a list of all groups. | Y | Y | Y | | [#!/]list realms | Returns a list of all realms. | Y | Y | Y | | [#!/]whitelist | User/Bot will not be subject to message checks. | Y | Y | Y | @@ -147,14 +147,14 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]import | Bot joins a group by GroupLink. | Y | Y | Y | | [#!/]pmblock [UserID] | Block a user from bot private message and bot photo. | Y | Y | Y | | [#!/]pmunblock [UserID] | Unblock a user from bot private message and bot photo. | Y | Y | Y | -| [#!/]markread [on|off] | Toggle bot to doubble check or not doubble check messages. | Y | Y | Y | +| [#!/]markread [on|off] | Toggle bot to doubble check or not doubble check messages. | Y | Y | Y | | [#!/]setbotphoto | Set bot photo. | Y | Y | Y | | [#!/]contactlist | Bot will generate a list of all it's contacts***and send it by private message of command sender | Y | Y | Y | | [#!/]dialoglist | Bot will generate a list of all it's private message users***and send it by private message of command sender | Y | Y | Y | | [#!/]delcontact | Delete bot contact. | Y | Y | Y | | [#!/]reload | Reloads all bot plugins | Y | Y | Y | | [#!/]updateid | Adds long_id to moderation data for groups. | Y | Y | Y | -| [#!/]!bc [group_id] [text] | This command will send text to [group_id]| Y | Y | Y | +| [#!/]!bc [GroupID] [text] | This command will send text to [GroupID]| Y | Y | Y | | [#!/]leave | Bot will leave that group and can only be re-invited by an admin with bot phone number | Y | Y | Y | | [#!/]mp | (Mod Promote) Set user as a mod of supergroup. **TESTING** | N | Y | N | | [#!/]md | (Mod demote) Removes user from mod of supergroup. **TESTING**| N | Y | N | @@ -163,8 +163,8 @@ TeleSeed has several commands that are only usable at certain ranks. | Command | Groups? | SuperGroups? | Realms? | |:--------|:--------|:-------------|---------| -| [#!/]addadmin [id|username] | Set a user as bot admin. | Y | Y | Y | -| [#!/]removeadmin [id|username] | Remove a user from bot admin. | Y | Y | Y | +| [#!/]addadmin [id|username] | Set a user as bot admin. | Y | Y | Y | +| [#!/]removeadmin [id|username] | Remove a user from bot admin. | Y | Y | Y | | [#!/]sync_gbans | Sync your GBans with official @TeleSeed | Y | Y | Y | @@ -172,18 +172,18 @@ TeleSeed has several commands that are only usable at certain ranks. | Command | Groups? | SuperGroups? | |:--------|:--------|:-------------| -| [#!/](un)lock links | Y | Y | -| [#!/](un)lock flood | Y | Y | -| [#!/]setflood [5-20] | Y | Y | -| [#!/](un)lock bots | Y | N | -| [#!/](un)lock spam | Y | Y | -| [#!/](un)lock arabic | Y | Y | -| [#!/](un)lock member | Y | Y | -| [#!/](un)lock leave | Y | N | -| [#!/](un)lock RTL | Y | Y | -| [#!/](un)lock sticker | Y| Y | -| [#!/]public [yes|no] | Y | Y | -| [#!/](un)lock strict | N | Y | +| [#!/](un)lock links | Y | Y | +| [#!/](un)lock flood | Y | Y | +| [#!/]setflood [5-20] | Y | Y | +| [#!/](un)lock bots | Y | N | +| [#!/](un)lock spam | Y | Y | +| [#!/](un)lock arabic | Y | Y | +| [#!/](un)lock member | Y | Y | +| [#!/](un)lock leave | Y | N | +| [#!/](un)lock RTL | Y | Y | +| [#!/](un)lock sticker | Y| Y | +| [#!/]public [yes|no] | Y | Y | +| [#!/](un)lock strict | N | Y | /lock [setting] and /unlock [setting]: sets allowed actions and content for groups/SuperGroups ***/lock strict*** in a supergroup, if strict is locked users will be kicked for violations of settings or mutes @@ -198,7 +198,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]mute audio | | [#!/]mute video | | [#!/]mute photo | -| [#!/]mute documents | +| [#!/]mute documents | | [#!/]mute gifs | | [#!/]mute all | @@ -211,10 +211,10 @@ TeleSeed has several commands that are only usable at certain ranks. | Rank | Description | |:------|:------------| | Banned | Cannot enter the group(s). | -| User | Default rank. | +| User | Default rank. | | Moderator | Can set settings and kick/ban/unban users from a group. Can unmute users. | | Owner | Can mute users. Can promote/demote moderators. Can set SuperGroup admins. | -| Support | Can globally unban users. Acts as owner of all groups. | +| Support | Can globally unban users. Acts as owner of all groups. | | Administrator | Can globally ban/unban users. Can promote/demote owners. | | Sudo | Can add[#!/]remove groups. Can broadcast. Can promote/demote administrators. | @@ -270,11 +270,11 @@ Create a realm using the `!createrealm` command. **Creating a LOG SuperGroup** -For GBan Log - + 1. Create a group using the `!creategroup` command. 2. Add two members or bots, then use `#Tosuper` to convert to a SuperSroup. 3. Use the `#addlog` command and your ***LOG SuperGroup(s)*** will be set. - Note: you can set multiple Log SuperGroups + Note: you can set multiple Log SuperGroups * * * @@ -310,7 +310,7 @@ For graphic designs. [Rondoozle](https://github.com/Rondoozle) ([Telegram](https://telegram.me/POTUS)) -###Our Telegram channels: +### Our Telegram channels: English: [@TeleSeedCH](https://telegram.me/teleseedch) From 54a97844fce71d61ce810c5ca3a0c492d50af2f4 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Mon, 21 Mar 2016 16:10:22 -0300 Subject: [PATCH 34/58] Goodbye Luarocks --- README.md | 4 +- bot/utils.lua | 24 +- launch.sh | 70 +- libs/XMLElement.lua | 151 ++++ libs/dateparser.lua | 192 +++++ libs/fakeredis.lua | 1708 +++++++++++++++++++++++++++++++++++++++++++ libs/feedparser.lua | 369 ++++++++++ libs/lua-redis.lua | 1140 +++++++++++++++++++++++++++++ libs/redis.lua | 6 +- libs/serpent.lua | 124 ++++ libs/url.lua | 269 +++++++ 11 files changed, 3971 insertions(+), 86 deletions(-) create mode 100644 libs/XMLElement.lua create mode 100644 libs/dateparser.lua create mode 100644 libs/fakeredis.lua create mode 100644 libs/feedparser.lua create mode 100644 libs/lua-redis.lua create mode 100644 libs/serpent.lua create mode 100644 libs/url.lua diff --git a/README.md b/README.md index 20aa5d3..3902e1d 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ Each higher status inherits the privileges of the lower status. ```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 +sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev lua-socket lua-sec lua-expat libevent-dev make unzip git redis-server autoconf g++ libjansson-dev libpython-dev expat libexpat1-dev # Let's install the bot. cd $HOME @@ -243,7 +243,7 @@ chmod +x launch.sh 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 -b supergroups && cd TeleSeed && chmod +x launch.sh && ./launch.sh install && ./launch.sh +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 lua-socket lua-sec lua-expat libevent-dev libjansson* libpython-dev make unzip git redis-server g++ autoconf -y --force-yes && git clone https://github.com/SEEDTEAM/TeleSeed.git -b supergroups && cd TeleSeed && chmod +x launch.sh && ./launch.sh install && ./launch.sh ``` * * * diff --git a/bot/utils.lua b/bot/utils.lua index 6837d1f..095b945 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -2,9 +2,9 @@ URL = require "socket.url" http = require "socket.http" https = require "ssl.https" ltn12 = require "ltn12" -serpent = require "serpent" -feedparser = require "feedparser" +serpent = (loadfile "./libs/serpent.lua")() +feedparser = (loadfile "./libs/feedparser.lua")() json = (loadfile "./libs/JSON.lua")() mimetype = (loadfile "./libs/mimetype.lua")() redis = (loadfile "./libs/redis.lua")() @@ -702,7 +702,7 @@ function is_owner(msg) end end end - + local hash = 'support' local support = redis:sismember(hash, user) if support then @@ -734,7 +734,7 @@ function is_owner2(user_id, group_id) end end end - + local hash = 'support' local support = redis:sismember(hash, user) if support then @@ -746,7 +746,7 @@ function is_owner2(user_id, group_id) var = true end end - + for v,user in pairs(_config.sudo_users) do if user == user_id then var = true @@ -812,7 +812,7 @@ function is_momod(msg) end end end - + local hash = 'support' local support = redis:sismember(hash, user) if support then @@ -852,7 +852,7 @@ function is_momod2(user_id, group_id) end end end - + local hash = 'support' local support = redis:sismember(hash, user_id) if support then @@ -1163,7 +1163,7 @@ function ban_by_reply(extra, success, result) local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot - return + return end if is_momod2(result.from.peer_id, result.to.peer_id) then -- Ignore mods,owner,admin return "you can't kick mods,owner and admins" @@ -1171,7 +1171,7 @@ function ban_by_reply(extra, success, result) ban_user(result.from.peer_id, result.to.peer_id) send_large_msg(chat, "User "..result.from.peer_id.." Banned") else - return + return end end @@ -1207,7 +1207,7 @@ function unban_by_reply(extra, success, result) local hash = 'banned:'..result.to.peer_id redis:srem(hash, result.from.peer_id) else - return + return end end function banall_by_reply(extra, success, result) @@ -1215,7 +1215,7 @@ function banall_by_reply(extra, success, result) local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot - return + return end if is_admin2(result.from.peer_id) then -- Ignore admins return @@ -1225,7 +1225,7 @@ function banall_by_reply(extra, success, result) chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) send_large_msg(chat, "User "..name.."["..result.from.peer_id.."] globally banned") else - return + return end end end diff --git a/launch.sh b/launch.sh index 7a52ff7..83447eb 100755 --- a/launch.sh +++ b/launch.sh @@ -6,72 +6,6 @@ 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() { @@ -90,8 +24,6 @@ install() { echo "Error. Exiting."; exit $RET; fi cd .. - install_luarocks - install_rocks } if [ "$1" = "install" ]; then @@ -110,6 +42,6 @@ else echo "Run $0 install" exit 1 fi - rm -r ../.telegram-cli/state #Prevent tg from crash + rm -r ../.telegram-cli/state #Prevent tg from crash ./tg/bin/telegram-cli -k ./tg/tg-server.pub -s ./bot/seedbot.lua -l 1 -E $@ fi diff --git a/libs/XMLElement.lua b/libs/XMLElement.lua new file mode 100644 index 0000000..0b9cb67 --- /dev/null +++ b/libs/XMLElement.lua @@ -0,0 +1,151 @@ +-- Copyright 2009 Leo Ponomarev. Distributed under the BSD Licence. +-- updated for module-free world of lua 5.3 on April 2 2015 +-- Not documented at all, but not interesting enough to warrant documentation anyway. +local setmetatable, pairs, ipairs, type, getmetatable, tostring, error = setmetatable, pairs, ipairs, type, getmetatable, tostring, error +local table, string = table, string + +local XMLElement={} + +local mt + +XMLElement.new = function(lom) + return setmetatable({lom=lom or {}}, mt) +end + +local function filter(filtery_thing, lom) + filtery_thing=filtery_thing or '*' + for i, thing in ipairs(type(filtery_thing)=='table' and filtery_thing or {filtery_thing}) do + if thing == "text()" then + if type(lom)=='string' then return true end + elseif thing == '*' then + if type(lom)=='table' then return true end + else + if type(lom)=='table' and string.lower(lom.tag)==string.lower(thing) then return true end + end + end + return nil +end + + +mt ={ __index = { + getAttr = function(self, attribute) + if type(attribute) ~= "string" then return nil, "attribute name must be a string." end + return self.lom.attr[attribute] + end, + + setAttr = function(self, attribute, value) + if type(attribute) ~= "string" then return nil, "attribute name must be a string." end + if value == nil then return self:removeAttr(attribute) end + self.lom.attr[attribute]=tostring(value) + return self + end, + + removeAttr = function(self, attribute) + local lom = self.lom + if type(attribute) ~= "string" then return nil, "attribute name must be a string." end + if not lom.attr[attribute] then return self end + for i,v in ipairs(lom.attr) do + if v == attribute then + table.remove(lom.attr, i) + break + end + end + lom.attr[attribute]=nil + end, + + removeAllAttributes = function(self) + local attr = self.lom.attr + for i, v in pairs(self.lom.attr) do + attr[i]=nil + end + return self + end, + + getAttributes = function(self) + local attr = {} + for i, v in ipairs(self.lom.attr) do + table.insert(attr,v) + end + return attr + end, + + getXML = function(self) + local function getXML(lom) + local attr, inner = {}, {} + for i, attribute in ipairs(lom.attr) do + table.insert(attr, string.format('%s=%q', attribute, lom.attr[attribute])) + end + for i, v in ipairs(lom) do + local t = type(v) + if t == "string" then table.insert(inner, v) + elseif t == "table" then + table.insert(inner, getXML(v)) + else + error("oh shit") + end + end + local tagcontents = table.concat(inner) + local attrstring = #attr>0 and (" " .. table.concat(attr, " ")) or "" + if #tagcontents>0 then + return string.format("<%s%s>%s", lom.tag, attrstring, tagcontents, lom.tag) + else + return string.format("<%s%s />", lom.tag, attrstring) + end + end + return getXML(self.lom) + end, + + getText = function(self) + local function getText(lom) + local inner = {} + for i, v in ipairs(lom) do + local t = type(v) + if t == "string" then table.insert(inner, v) + elseif t == "table" then + table.insert(inner, getText(v)) + end + end + return table.concat(inner) + end + return getText(self.lom) + end, + + getChildren = function(self, filter_thing) + local res = {} + for i, node in ipairs(self.lom) do + if filter(filter_thing, node) then + table.insert(res, type(node)=='table' and XMLElement.new(node) or node) + end + end + return res + end, + + getDescendants = function(self, filter_thing) + local res = {} + local function descendants(lom) + for i, child in ipairs(lom) do + if filter(filter_thing, child) then + table.insert(res, type(child)=='table' and XMLElement.new(child) or child) + if type(child)=='table' then descendants(child) end + end + end + end + descendants(self.lom) + return res + end, + + + getChild = function(self, filter_thing) + for i, node in ipairs(self.lom) do + if filter(filter_thing, node) then + return type(node)=='table' and XMLElement.new(node) or node + end + end + end, + + getTag = function(self) + return self.lom.tag + end +}} + +return XMLElement \ No newline at end of file diff --git a/libs/dateparser.lua b/libs/dateparser.lua new file mode 100644 index 0000000..abd6f09 --- /dev/null +++ b/libs/dateparser.lua @@ -0,0 +1,192 @@ +local difftime, time, date = os.difftime, os.time, os.date +local format = string.format +local tremove, tinsert = table.remove, table.insert +local pcall, pairs, ipairs, tostring, tonumber, type, setmetatable = pcall, pairs, ipairs, tostring, tonumber, type, setmetatable + +local dateparser={} + +--we shall use the host OS's time conversion facilities. Dealing with all those leap seconds by hand can be such a bore. +local unix_timestamp +do + local now = time() + local local_UTC_offset_sec = difftime(time(date("!*t", now)), time(date("*t", now))) + unix_timestamp = function(t, offset_sec) + local success, improper_time = pcall(time, t) + if not success or not improper_time then return nil, "invalid date. os.time says: " .. (improper_time or "nothing") end + return improper_time - local_UTC_offset_sec - offset_sec + end +end + +local formats = {} -- format names +local format_func = setmetatable({}, {__mode='v'}) --format functions + +---register a date format parsing function +function dateparser.register_format(format_name, format_function) + if type(format_name)~="string" or type(format_function)~='function' then return nil, "improper arguments, can't register format handler" end + + local found + for i, f in ipairs(format_func) do --for ordering + if f==format_function then + found=true + break + end + end + if not found then + tinsert(format_func, format_function) + end + formats[format_name] = format_function + return true +end + +---register a date format parsing function +function dateparser.unregister_format(format_name) + if type(format_name)~="string" then return nil, "format name must be a string" end + formats[format_name]=nil +end + +---return the function responsible for handling format_name date strings +function dateparser.get_format_function(format_name) + return formats[format_name] or nil, ("format %s not registered"):format(format_name) +end + +---try to parse date string +--@param str date string +--@param date_format optional date format name, if known +--@return unix timestamp if str can be parsed; nil, error otherwise. +function dateparser.parse(str, date_format) + local success, res, err + if date_format then + if not formats[date_format] then return 'unknown date format: ' .. tostring(date_format) end + success, res = pcall(formats[date_format], str) + else + for i, func in ipairs(format_func) do + success, res = pcall(func, str) + if success and res then return res end + end + end + return success and res +end + +dateparser.register_format('W3CDTF', function(rest) + + local year, day_of_year, month, day, week + local hour, minute, second, second_fraction, offset_hours + + local alt_rest + + year, rest = rest:match("^(%d%d%d%d)%-?(.*)$") + + day_of_year, alt_rest = rest:match("^(%d%d%d)%-?(.*)$") + + if day_of_year then rest=alt_rest end + + month, rest = rest:match("^(%d%d)%-?(.*)$") + + day, rest = rest:match("^(%d%d)(.*)$") + if #rest>0 then + rest = rest:match("^T(.*)$") + hour, rest = rest:match("^([0-2][0-9]):?(.*)$") + minute, rest = rest:match("^([0-6][0-9]):?(.*)$") + second, rest = rest:match("^([0-6][0-9])(.*)$") + second_fraction, alt_rest = rest:match("^%.(%d+)(.*)$") + if second_fraction then + rest=alt_rest + end + if rest=="Z" then + rest="" + offset_hours=0 + else + local sign, offset_h, offset_m + sign, offset_h, rest = rest:match("^([+-])(%d%d)%:?(.*)$") + local offset_m, alt_rest = rest:match("^(%d%d)(.*)$") + if offset_m then rest=alt_rest end + offset_hours = tonumber(sign .. offset_h) + (tonumber(offset_m) or 0)/60 + end + if #rest>0 then return nil end + end + + year = tonumber(year) + local d = { + year = year and (year > 100 and year or (year < 50 and (year + 2000) or (year + 1900))), + month = tonumber(month) or 1, + day = tonumber(day) or 1, + hour = tonumber(hour) or 0, + min = tonumber(minute) or 0, + sec = tonumber(second) or 0, + isdst = false + } + local t = unix_timestamp(d, (offset_hours or 0) * 3600) + if second_fraction then + return t + tonumber("0."..second_fraction) + else + return t + end +end) + + +do + local tz_table = { --taken from http://www.timeanddate.com/library/abbreviations/timezones/ + A = 1, B = 2, C = 3, D = 4, E=5, F = 6, G = 7, H = 8, I = 9, + K = 10, L = 11, M = 12, N = -1, O = -2, P = -3, Q = -4, R = -5, + S = -6, T = -7, U = -8, V = -9, W = -10, X = -11, Y = -12, + Z = 0, + + EST = -5, EDT = -4, CST = -6, CDT = -5, + MST = -7, MDT = -6, PST = -8, PDT = -7, + + GMT = 0, UT = 0, UTC = 0 + } + + local month_val = {Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8, Sep=9, Oct=10, Nov=11, Dec=12} + + dateparser.register_format('RFC2822', function(rest) + + local year, month, day, day_of_year, week_of_year, weekday + local hour, minute, second, second_fraction, offset_hours + + local alt_rest + + weekday, alt_rest = rest:match("^(%w%w%w),%s+(.*)$") + if weekday then rest=alt_rest end + day, rest=rest:match("^(%d%d?)%s+(.*)$") + month, rest=rest:match("^(%w%w%w)%s+(.*)$") + month = month_val[month] + year, rest = rest:match("^(%d%d%d?%d?)%s+(.*)$") + hour, rest = rest:match("^(%d%d?):(.*)$") + minute, rest = rest:match("^(%d%d?)(.*)$") + second, alt_rest = rest:match("^:(%d%d)(.*)$") + if second then rest = alt_rest end + local tz, offset_sign, offset_h, offset_m + tz, alt_rest = rest:match("^%s+(%u+)(.*)$") + if tz then + rest = alt_rest + offset_hours = tz_table[tz] + else + offset_sign, offset_h, offset_m, rest = rest:match("^%s+([+-])(%d%d)(%d%d)%s*(.*)$") + offset_hours = tonumber(offset_sign .. offset_h) + (tonumber(offset_m) or 0)/60 + end + + if #rest>0 or not (year and day and month and hour and minute) then + return nil + end + + year = tonumber(year) + local d = { + year = year and ((year > 100) and year or (year < 50 and (year + 2000) or (year + 1900))), + month = month, + day = tonumber(day), + + hour= tonumber(hour) or 0, + min = tonumber(minute) or 0, + sec = tonumber(second) or 0, + isdst = false + } + return unix_timestamp(d, offset_hours * 3600) + end) +end + +dateparser.register_format('RFC822', formats.RFC2822) --2822 supercedes 822, but is not a strict superset. For our intents and purposes though, it's perfectly good enough +dateparser.register_format('RFC3339', formats.W3CDTF) --RFC3339 is a subset of W3CDTF + + +return dateparser \ No newline at end of file diff --git a/libs/fakeredis.lua b/libs/fakeredis.lua new file mode 100644 index 0000000..ac6181e --- /dev/null +++ b/libs/fakeredis.lua @@ -0,0 +1,1708 @@ +local unpack = table.unpack or unpack + +--- Bit operations + +local ok,bit +if _VERSION == "Lua 5.3" then + bit = (load [[ return { + band = function(x, y) return x & y end, + bor = function(x, y) return x | y end, + bxor = function(x, y) return x ~ y end, + bnot = function(x) return ~x end, + rshift = function(x, n) return x >> n end, + lshift = function(x, n) return x << n end, + } ]])() +else + ok,bit = pcall(require,"bit") + if not ok then bit = bit32 end +end + +assert(type(bit) == "table", "module for bitops not found") + +--- default sleep + +local default_sleep +do + local ok, mod = pcall(require, "socket") + if ok and type(mod) == "table" then + default_sleep = mod.sleep + else + default_sleep = function(n) + local t0 = os.clock() + while true do + local delta = os.clock() - t0 + if (delta < 0) or (delta > n) then break end + end + end + end +end + +--- Helpers + +local xdefv = function(ktype) + if ktype == "list" then + return {head = 0, tail = 0} + elseif ktype == "zset" then + return { + list = {}, + set = {}, + } + else return {} end +end + +local xgetr = function(self, k, ktype) + if self.data[k] then + assert( + (self.data[k].ktype == ktype), + "ERR Operation against a key holding the wrong kind of value" + ) + assert(self.data[k].value) + return self.data[k].value + else return xdefv(ktype) end +end + +local xgetw = function(self, k, ktype) + if self.data[k] and self.data[k].value then + assert( + (self.data[k].ktype == ktype), + "ERR Operation against a key holding the wrong kind of value" + ) + else + self.data[k] = {ktype = ktype, value = xdefv(ktype)} + end + return self.data[k].value +end + +local empty = function(self, k) + local v, t = self.data[k].value, self.data[k].ktype + if t == nil then + return true + elseif t == "string" then + return not v[1] + elseif (t == "hash") or (t == "set") then + for _,_ in pairs(v) do return false end + return true + elseif t == "list" then + return v.head == v.tail + elseif t == "zset" then + if #v.list == 0 then + for _,_ in pairs(v.set) do error("incoherent") end + return true + else + for _,_ in pairs(v.set) do return(false) end + error("incoherent") + end + else error("unsupported") end +end + +local cleanup = function(self, k) + if empty(self, k) then self.data[k] = nil end +end + +local is_integer = function(x) + return (type(x) == "number") and (math.floor(x) == x) +end + +local overflows = function(n) + return (n > 2^53-1) or (n < -2^53+1) +end + +local is_bounded_integer = function(x) + return (is_integer(x) and (not overflows(x))) +end + +local is_finite_number = function(x) + return (type(x) == "number") and (x > -math.huge) and (x < math.huge) +end + +local toint = function(x) + if type(x) == "string" then x = tonumber(x) end + return is_bounded_integer(x) and x or nil +end + +local tofloat = function(x) + if type(x) == "number" then return x end + if type(x) ~= "string" then return nil end + local r = tonumber(x) + if r then return r end + if x == "inf" or x == "+inf" then + return math.huge + elseif x == "-inf" then + return -math.huge + else return nil end +end + +local tostr = function(x) + if is_bounded_integer(x) then + return string.format("%d", x) + else return tostring(x) end +end + +local char_bitcount = function(x) + assert( + (type(x) == "number") and + (math.floor(x) == x) and + (x >= 0) and (x < 256) + ) + local n = 0 + while x ~= 0 do + x = bit.band(x, x-1) + n = n+1 + end + return n +end + +local chkarg = function(x) + if type(x) == "number" then x = tostr(x) end + assert(type(x) == "string") + return x +end + +local chkargs = function(n, ...) + local arg = {...} + assert(#arg == n) + for i=1,n do arg[i] = chkarg(arg[i]) end + return unpack(arg) +end + +local getargs = function(...) + local arg = {...} + local n = #arg; assert(n > 0) + for i=1,n do arg[i] = chkarg(arg[i]) end + return arg +end + +local getargs_as_map = function(...) + local arg, r = getargs(...), {} + assert(#arg%2 == 0) + for i=1,#arg,2 do r[arg[i]] = arg[i+1] end + return r +end + +local chkargs_wrap = function(f, n) + assert( (type(f) == "function") and (type(n) == "number") ) + return function(self, ...) return f(self, chkargs(n, ...)) end +end + +local lset_to_list = function(s) + local r = {} + for v,_ in pairs(s) do r[#r+1] = v end + return r +end + +local nkeys = function(x) + local r = 0 + for _,_ in pairs(x) do r = r + 1 end + return r +end + +--- Commands + +-- keys + +local del = function(self, ...) + local arg = getargs(...) + local r = 0 + for i=1,#arg do + if self.data[arg[i]] then r = r + 1 end + self.data[arg[i]] = nil + end + return r +end + +local exists = function(self, k) + return not not self.data[k] +end + +local keys = function(self, pattern) + assert(type(pattern) == "string") + -- We want to convert the Redis pattern to a Lua pattern. + -- Start by escaping dashes *outside* character classes. + -- We also need to escape percents here. + local t, p, n = {}, 1, #pattern + local p1, p2 + while true do + p1, p2 = pattern:find("%[.+%]", p) + if p1 then + if p1 > p then + t[#t+1] = {true, pattern:sub(p, p1-1)} + end + t[#t+1] = {false, pattern:sub(p1, p2)} + p = p2+1 + if p > n then break end + else + t[#t+1] = {true, pattern:sub(p, n)} + break + end + end + for i=1,#t do + if t[i][1] then + t[i] = t[i][2]:gsub("[%%%-]", "%%%0") + else t[i] = t[i][2]:gsub("%%", "%%%%") end + end + -- Remaining Lua magic chars are: '^$().[]*+?' ; escape them except '*?[]' + -- Then convert '\' to '%', '*' to '.*' and '?' to '.'. Leave '[]' as is. + -- Wrap in '^$' to enforce bounds. + local lp = "^" .. table.concat(t):gsub("[%^%$%(%)%.%+]", "%%%0") + :gsub("\\", "%%"):gsub("%*", ".*"):gsub("%?", ".") .. "$" + local r = {} + for k,_ in pairs(self.data) do + if k:match(lp) then r[#r+1] = k end + end + return r +end + +local _type = function(self, k) + return self.data[k] and self.data[k].ktype or "none" +end + +local randomkey = function(self) + local ks = lset_to_list(self.data) + local n = #ks + if n > 0 then + return ks[math.random(1, n)] + else return nil end +end + +local rename = function(self, k, k2) + assert((k ~= k2) and self.data[k]) + self.data[k2] = self.data[k] + self.data[k] = nil + return true +end + +local renamenx = function(self, k, k2) + if self.data[k2] then + return false + else + return rename(self, k, k2) + end +end + +-- strings + +local getrange, incrby, set + +local append = function(self, k, v) + local x = xgetw(self, k, "string") + x[1] = (x[1] or "") .. v + return #x[1] +end + +local bitcount = function(self, k, i1, i2) + k = chkarg(k) + local s + if i1 or i2 then + assert(i1 and i2, "ERR syntax error") + s = getrange(self, k, i1, i2) + else + s = xgetr(self, k, "string")[1] or "" + end + local r, bytes = 0,{s:byte(1, -1)} + for i=1,#bytes do + r = r + char_bitcount(bytes[i]) + end + return r +end + +local bitop = function(self, op, k, ...) + assert(type(op) == "string") + op = op:lower() + assert( + (op == "and") or + (op == "or") or + (op == "xor") or + (op == "not"), + "ERR syntax error" + ) + k = chkarg(k) + local arg = {...} + local good_arity = (op == "not") and (#arg == 1) or (#arg > 0) + assert(good_arity, "ERR wrong number of arguments for 'bitop' command") + local l, vals = 0, {} + local s + for i=1,#arg do + s = xgetr(self, arg[i], "string")[1] or "" + if #s > l then l = #s end + vals[i] = s + end + if l == 0 then + del(self, k) + return 0 + end + local vector_mt = {__index=function() return 0 end} + for i=1,#vals do + vals[i] = setmetatable({vals[i]:byte(1, -1)}, vector_mt) + end + local r = {} + if op == "not" then + assert(#vals[1] == l) + for i=1,l do + r[i] = bit.band(bit.bnot(vals[1][i]), 0xff) + end + else + local _op = bit["b" .. op] + for i=1,l do + local t = {} + for j=1,#vals do t[j] = vals[j][i] end + r[i] = _op(unpack(t)) + end + end + set(self, k, string.char(unpack(r))) + return l +end + +local decr = function(self, k) + return incrby(self, k, -1) +end + +local decrby = function(self, k, n) + n = toint(n) + assert(n, "ERR value is not an integer or out of range") + return incrby(self, k, -n) +end + +local get = function(self, k) + local x = xgetr(self, k, "string") + return x[1] +end + +local getbit = function(self, k, offset) + k = chkarg(k) + offset = toint(offset) + assert( + (offset >= 0), + "ERR bit offset is not an integer or out of range" + ) + local bitpos = offset % 8 -- starts at 0 + local bytepos = (offset - bitpos) / 8 -- starts at 0 + local s = xgetr(self, k, "string")[1] or "" + if bytepos >= #s then return 0 end + local char = s:sub(bytepos+1, bytepos+1):byte() + return bit.band(bit.rshift(char, 7-bitpos), 1) +end + +getrange = function(self, k, i1, i2) + k = chkarg(k) + i1, i2 = toint(i1), toint(i2) + assert(i1 and i2) + local x = xgetr(self, k, "string") + x = x[1] or "" + if i1 >= 0 then i1 = i1 + 1 end + if i2 >= 0 then i2 = i2 + 1 end + return x:sub(i1, i2) +end + +local getset = function(self, k, v) + local r = get(self, k) + set(self, k, v) + return r +end + +local incr = function(self, k) + return incrby(self, k, 1) +end + +incrby = function(self, k, n) + k, n = chkarg(k), toint(n) + assert(n, "ERR value is not an integer or out of range") + local x = xgetw(self, k, "string") + local i = toint(x[1] or 0) + assert(i, "ERR value is not an integer or out of range") + i = i+n + assert( + (not overflows(i)), + "ERR increment or decrement would overflow" + ) + x[1] = tostr(i) + return i +end + +local incrbyfloat = function(self, k, n) + k, n = chkarg(k), tofloat(n) + assert(n, "ERR value is not a valid float") + local x = xgetw(self, k, "string") + local i = tofloat(x[1] or 0) + assert(i, "ERR value is not a valid float") + i = i+n + assert( + is_finite_number(i), + "ERR increment would produce NaN or Infinity" + ) + x[1] = tostr(i) + return i +end + +local mget = function(self, ...) + local arg, r = getargs(...), {} + for i=1,#arg do r[i] = get(self, arg[i]) end + return r +end + +local mset = function(self, ...) + local argmap = getargs_as_map(...) + for k,v in pairs(argmap) do set(self, k, v) end + return true +end + +local msetnx = function(self, ...) + local argmap = getargs_as_map(...) + for k,_ in pairs(argmap) do + if self.data[k] then return false end + end + for k,v in pairs(argmap) do set(self, k, v) end + return true +end + +set = function(self, k, v) + self.data[k] = {ktype = "string", value = {v}} + return true +end + +local setbit = function(self, k, offset, b) + k = chkarg(k) + offset, b = toint(offset), toint(b) + assert( + (offset >= 0), + "ERR bit offset is not an integer or out of range" + ) + assert( + (b == 0) or (b == 1), + "ERR bit is not an integer or out of range" + ) + local bitpos = offset % 8 -- starts at 0 + local bytepos = (offset - bitpos) / 8 -- starts at 0 + local s = xgetr(self, k, "string")[1] or "" + local pad = {s} + for i=2,bytepos+2-#s do pad[i] = "\0" end + s = table.concat(pad) + assert(#s >= bytepos+1) + local before = s:sub(1, bytepos) + local char = s:sub(bytepos+1, bytepos+1):byte() + local after = s:sub(bytepos+2, -1) + local old = bit.band(bit.rshift(char, 7-bitpos), 1) + if b == 1 then + char = bit.bor(bit.lshift(1, 7-bitpos), char) + else + char = bit.band(bit.bnot(bit.lshift(1, 7-bitpos)), char) + end + local r = before .. string.char(char) .. after + set(self, k, r) + return old +end + +local setnx = function(self, k, v) + if self.data[k] then + return false + else + return set(self, k, v) + end +end + +local setrange = function(self, k, i, s) + local k, s = chkargs(2, k, s) + i = toint(i) + assert(i and (i >= 0)) + local x = xgetw(self, k, "string") + local y = x[1] or "" + local ly, ls = #y, #s + if i > ly then -- zero padding + local t = {} + for i=1, i-ly do t[i] = "\0" end + y = y .. table.concat(t) .. s + else + y = y:sub(1, i) .. s .. y:sub(i+ls+1, ly) + end + x[1] = y + return #y +end + +local strlen = function(self, k) + local x = xgetr(self, k, "string") + return x[1] and #x[1] or 0 +end + +-- hashes + +local hdel = function(self, k, ...) + k = chkarg(k) + local arg = getargs(...) + local r = 0 + local x = xgetw(self, k, "hash") + for i=1,#arg do + if x[arg[i]] then r = r + 1 end + x[arg[i]] = nil + end + cleanup(self, k) + return r +end + +local hget +local hexists = function(self, k, k2) + return not not hget(self, k, k2) +end + +hget = function(self, k, k2) + local x = xgetr(self, k, "hash") + return x[k2] +end + +local hgetall = function(self, k) + local x = xgetr(self, k, "hash") + local r = {} + for _k,v in pairs(x) do r[_k] = v end + return r +end + +local hincrby = function(self, k, k2, n) + k, k2, n = chkarg(k), chkarg(k2), toint(n) + assert(n, "ERR value is not an integer or out of range") + assert(type(n) == "number") + local x = xgetw(self, k, "hash") + local i = toint(x[k2] or 0) + assert(i, "ERR value is not an integer or out of range") + i = i+n + assert( + (not overflows(i)), + "ERR increment or decrement would overflow" + ) + x[k2] = tostr(i) + return i +end + +local hincrbyfloat = function(self, k, k2, n) + k, k2, n = chkarg(k), chkarg(k2), tofloat(n) + assert(n, "ERR value is not a valid float") + local x = xgetw(self, k, "hash") + local i = tofloat(x[k2] or 0) + assert(i, "ERR value is not a valid float") + i = i+n + assert( + is_finite_number(i), + "ERR increment would produce NaN or Infinity" + ) + x[k2] = tostr(i) + return i +end + +local hkeys = function(self, k) + local x = xgetr(self, k, "hash") + local r = {} + for _k,_ in pairs(x) do r[#r+1] = _k end + return r +end + +local hlen = function(self, k) + local x = xgetr(self, k, "hash") + return nkeys(x) +end + +local hmget = function(self, k, k2s) + k = chkarg(k) + assert((type(k2s) == "table")) + local r = {} + local x = xgetr(self, k, "hash") + for i=1,#k2s do r[i] = x[chkarg(k2s[i])] end + return r +end + +local hmset = function(self, k, ...) + k = chkarg(k) + local arg = {...} + if type(arg[1]) == "table" then + assert(#arg == 1) + local x = xgetw(self, k, "hash") + for _k,v in pairs(arg[1]) do x[chkarg(_k)] = chkarg(v) end + else + assert(#arg % 2 == 0) + local x = xgetw(self, k, "hash") + local t = getargs(...) + for i=1,#t,2 do x[t[i]] = t[i+1] end + end + return true +end + +local hset = function(self, k, k2, v) + local x = xgetw(self, k, "hash") + local r = not x[k2] + x[k2] = v + return r +end + +local hsetnx = function(self, k, k2, v) + local x = xgetw(self, k, "hash") + if x[k2] == nil then + x[k2] = v + return true + else + return false + end +end + +local hvals = function(self, k) + local x = xgetr(self, k, "hash") + local r = {} + for _,v in pairs(x) do r[#r+1] = v end + return r +end + +-- lists (head = left, tail = right) + +local _l_real_i = function(x, i) + if i < 0 then + return x.tail+i+1 + else + return x.head+i+1 + end +end + +local _l_len = function(x) + return x.tail - x.head +end + +local _block_for = function(self, timeout) + if timeout > 0 then + local sleep = self.sleep or default_sleep + if type(sleep) == "function" then + sleep(timeout) + else + error("sleep function unavailable", 0) + end + else + error("operation would block", 0) + end +end + +local rpoplpush + +local blpop = function(self, ...) + local arg = {...} + local timeout = toint(arg[#arg]) + arg[#arg] = nil + local vs = getargs(...) + local x, l, k, v + for i=1,#vs do + k = vs[i] + x = xgetw(self, k, "list") + l = _l_len(x) + if l > 0 then + v = x[x.head+1] + if l > 1 then + x.head = x.head + 1 + x[x.head] = nil + else self.data[k] = nil end + return {k, v} + else self.data[k] = nil end + end + _block_for(self, timeout) +end + +local brpop = function(self, ...) + local arg = {...} + local timeout = toint(arg[#arg]) + arg[#arg] = nil + local vs = getargs(...) + local x, l, k, v + for i=1,#vs do + k = vs[i] + x = xgetw(self, k, "list") + l = _l_len(x) + if l > 0 then + v = x[x.tail] + if l > 1 then + x[x.tail] = nil + x.tail = x.tail - 1 + else self.data[k] = nil end + return {k, v} + else self.data[k] = nil end + end + _block_for(self, timeout) +end + +local brpoplpush = function(self, k1, k2, timeout) + k1, k2 = chkargs(2, k1, k2) + timeout = toint(timeout) + if not self.data[k1] then _block_for(self, timeout) end + return rpoplpush(self, k1, k2) +end + +local lindex = function(self, k, i) + k = chkarg(k) + i = assert(toint(i)) + local x = xgetr(self, k, "list") + return x[_l_real_i(x, i)] +end + +local linsert = function(self, k, mode, pivot, v) + mode = mode:lower() + assert((mode == "before") or (mode == "after")) + if not self.data[k] then return 0 end + local x = xgetw(self, k, "list") + local p = nil + for i=x.head+1, x.tail do + if x[i] == pivot then + p = i + break + end + end + if not p then return -1 end + if mode == "after" then + for i=x.head+1, p do x[i-1] = x[i] end + x.head = x.head - 1 + else + for i=x.tail, p, -1 do x[i+1] = x[i] end + x.tail = x.tail + 1 + end + x[p] = v + return _l_len(x) +end + +local llen = function(self, k) + local x = xgetr(self, k, "list") + return _l_len(x) +end + +local lpop = function(self, k) + local x = xgetw(self, k, "list") + local l, r = _l_len(x), x[x.head+1] + if l > 1 then + x.head = x.head + 1 + x[x.head] = nil + else self.data[k] = nil end + return r +end + +local lpush = function(self, k, ...) + local vs = getargs(...) + local x = xgetw(self, k, "list") + for i=1,#vs do + x[x.head] = vs[i] + x.head = x.head - 1 + end + return _l_len(x) +end + +local lpushx = function(self, k, v) + if not self.data[k] then return 0 end + local x = xgetw(self, k, "list") + x[x.head] = v + x.head = x.head - 1 + return _l_len(x) +end + +local lrange = function(self, k, i1, i2) + k = chkarg(k) + i1, i2 = toint(i1), toint(i2) + assert(i1 and i2) + local x, r = xgetr(self, k, "list"), {} + i1 = math.max(_l_real_i(x, i1), x.head+1) + i2 = math.min(_l_real_i(x, i2), x.tail) + for i=i1,i2 do r[#r+1] = x[i] end + return r +end + +local _lrem_i = function(x, p) + for i=p,x.tail do + x[i] = x[i+1] + end + x.tail = x.tail - 1 +end + +local _lrem_l = function(x, v, s) + assert(v) + if not s then s = x.head+1 end + for i=s,x.tail do + if x[i] == v then + _lrem_i(x, i) + return i + end + end + return false +end + +local _lrem_r = function(x, v, s) + assert(v) + if not s then s = x.tail end + for i=s,x.head+1,-1 do + if x[i] == v then + _lrem_i(x, i) + return i + end + end + return false +end + +local lrem = function(self, k, count, v) + k, v = chkarg(k), chkarg(v) + count = assert(toint(count)) + if not self.data[k] then return 0 end + local x = xgetw(self, k, "list") + local n, last = 0, nil + local op = (count < 0) and _lrem_r or _lrem_l + local limited = (count ~= 0) + count = math.abs(count) + while true do + last = op(x, v, last) + if last then + n = n+1 + if limited then + count = count - 1 + if count == 0 then break end + end + else break end + end + return n +end + +local lset = function(self, k, i, v) + k, v = chkarg(k), chkarg(v) + i = assert(toint(i)) + if not self.data[k] then + error("ERR no such key") + end + local x = xgetw(self, k, "list") + local l = _l_len(x) + if i >= l or i < -l then + error("ERR index out of range") + end + x[_l_real_i(x, i)] = v + return true +end + +local ltrim = function(self, k, i1, i2) + k = chkarg(k) + i1, i2 = toint(i1), toint(i2) + assert(i1 and i2) + local x = xgetw(self, k, "list") + i1, i2 = _l_real_i(x, i1), _l_real_i(x, i2) + for i=x.head+1,i1-1 do x[i] = nil end + for i=i2+1,x.tail do x[i] = nil end + x.head = math.max(i1-1, x.head) + x.tail = math.min(i2, x.tail) + assert( + (x[x.head] == nil) and + (x[x.tail+1] == nil) + ) + cleanup(self, k) + return true +end + +local rpop = function(self, k) + local x = xgetw(self, k, "list") + local l, r = _l_len(x), x[x.tail] + if l > 1 then + x[x.tail] = nil + x.tail = x.tail - 1 + else self.data[k] = nil end + return r +end + +rpoplpush = function(self, k1, k2) + local v = rpop(self, k1) + if not v then return nil end + lpush(self, k2, v) + return v +end + +local rpush = function(self, k, ...) + local vs = getargs(...) + local x = xgetw(self, k, "list") + for i=1,#vs do + x.tail = x.tail + 1 + x[x.tail] = vs[i] + end + return _l_len(x) +end + +local rpushx = function(self, k, v) + if not self.data[k] then return 0 end + local x = xgetw(self, k, "list") + x.tail = x.tail + 1 + x[x.tail] = v + return _l_len(x) +end + +-- sets + +local sadd = function(self, k, ...) + k = chkarg(k) + local arg = getargs(...) + local x, r = xgetw(self, k, "set"), 0 + for i=1,#arg do + if not x[arg[i]] then + x[arg[i]] = true + r = r + 1 + end + end + return r +end + +local scard = function(self, k) + local x = xgetr(self, k, "set") + return nkeys(x) +end + +local _sdiff = function(self, k, ...) + k = chkarg(k) + local arg = getargs(...) + local x = xgetr(self, k, "set") + local r = {} + for v,_ in pairs(x) do r[v] = true end + for i=1,#arg do + x = xgetr(self, arg[i], "set") + for v,_ in pairs(x) do r[v] = nil end + end + return r +end + +local sdiff = function(self, k, ...) + return lset_to_list(_sdiff(self, k, ...)) +end + +local sdiffstore = function(self, k2, k, ...) + k2 = chkarg(k2) + local x = _sdiff(self, k, ...) + self.data[k2] = {ktype = "set", value = x} + return nkeys(x) +end + +local _sinter = function(self, k, ...) + k = chkarg(k) + local arg = getargs(...) + local x = xgetr(self, k, "set") + local r = {} + local y + for v,_ in pairs(x) do + r[v] = true + for i=1,#arg do + y = xgetr(self, arg[i], "set") + if not y[v] then r[v] = nil; break end + end + end + return r +end + +local sinter = function(self, k, ...) + return lset_to_list(_sinter(self, k, ...)) +end + +local sinterstore = function(self, k2, k, ...) + k2 = chkarg(k2) + local x = _sinter(self, k, ...) + self.data[k2] = {ktype = "set", value = x} + return nkeys(x) +end + +local sismember = function(self, k, v) + local x = xgetr(self, k, "set") + return not not x[v] +end + +local smembers = function(self, k) + local x = xgetr(self, k, "set") + return lset_to_list(x) +end + +local smove = function(self, k, k2, v) + local x = xgetr(self, k, "set") + if x[v] then + local y = xgetw(self, k2, "set") + x[v] = nil + y[v] = true + return true + else return false end +end + +local spop = function(self, k) + local x, r = xgetw(self, k, "set"), nil + local l = lset_to_list(x) + local n = #l + if n > 0 then + r = l[math.random(1, n)] + x[r] = nil + end + cleanup(self, k) + return r +end + +local srandmember = function(self, k, count) + k = chkarg(k) + local x = xgetr(self, k, "set") + local l = lset_to_list(x) + local n = #l + if not count then + if n > 0 then + return l[math.random(1, n)] + else return nil end + end + count = toint(count) + if (count == 0) or (n == 0) then return {} end + if count >= n then return l end + local r = {} + if count > 0 then -- distinct elements + for i=0,count-1 do + r[#r+1] = table.remove(l, math.random(1, n-i)) + end + else -- allow repetition + for i=1,-count do + r[#r+1] = l[math.random(1, n)] + end + end + return r +end + +local srem = function(self, k, ...) + k = chkarg(k) + local arg = getargs(...) + local x, r = xgetw(self, k, "set"), 0 + for i=1,#arg do + if x[arg[i]] then + x[arg[i]] = nil + r = r + 1 + end + end + cleanup(self, k) + return r +end + +local _sunion = function(self, ...) + local arg = getargs(...) + local r = {} + local x + for i=1,#arg do + x = xgetr(self, arg[i], "set") + for v,_ in pairs(x) do r[v] = true end + end + return r +end + +local sunion = function(self, k, ...) + return lset_to_list(_sunion(self, k, ...)) +end + +local sunionstore = function(self, k2, k, ...) + k2 = chkarg(k2) + local x = _sunion(self, k, ...) + self.data[k2] = {ktype = "set", value = x} + return nkeys(x) +end + +-- zsets + +local _z_p_mt = { + __eq = function(a, b) + if a.v == b.v then + assert(a.s == b.s) + return true + else return false end + end, + __lt = function(a, b) + if a.s == b.s then + return (a.v < b.v) + else + return (a.s < b.s) + end + end, +} + +local _z_pair = function(s, v) + assert( + (type(s) == "number") and + (type(v) == "string") + ) + local r = {s = s, v = v} + return setmetatable(r, _z_p_mt) +end + +local _z_pairs = function(...) + local arg = {...} + assert((#arg > 0) and (#arg % 2 == 0)) + local ps = {} + for i=1,#arg,2 do + ps[#ps+1] = _z_pair( + assert(tofloat(arg[i])), + chkarg(arg[i+1]) + ) + end + return ps +end + +local _z_insert = function(x, ix, p) + assert( + (type(x) == "table") and + (type(ix) == "number") and + (type(p) == "table") + ) + local l = x.list + table.insert(l, ix, p) + for i=ix+1,#l do + x.set[l[i].v] = x.set[l[i].v] + 1 + end + x.set[p.v] = ix +end + +local _z_remove = function(x, v) + if not x.set[v] then return false end + local l, ix = x.list, x.set[v] + assert(l[ix].v == v) + table.remove(l, ix) + for i=ix,#l do + x.set[l[i].v] = x.set[l[i].v] - 1 + end + x.set[v] = nil + return true +end + +local _z_remove_range = function(x, i1, i2) + local l = x.list + i2 = i2 or i1 + assert( + (i1 > 0) and + (i2 >= i1) and + (i2 <= #l) + ) + local ix, n = i1, i2-i1+1 + for i=1,n do + x.set[l[ix].v] = nil + table.remove(l, ix) + end + for i=ix,#l do + x.set[l[i].v] = x.set[l[i].v] - n + end + return n +end + +local _z_update = function(x, p) + local l = x.list + local found = _z_remove(x, p.v) + local ix = nil + for i=1,#l do + if l[i] > p then + ix = i; break + end + end + if not ix then ix = #l+1 end + _z_insert(x, ix, p) + return found +end + +local _z_coherence = function(x) + local l, s = x.list, x.set + local found, n = {}, 0 + for val,pos in pairs(s) do + if found[pos] then return false end + found[pos] = true + n = n + 1 + if not (l[pos] and (l[pos].v == val)) then + return false + end + end + if #l ~= n then return false end + for i=1, n-1 do + if l[i].s > l[i+1].s then return false end + end + return true +end + +local _z_normrange = function(l, i1, i2) + i1, i2 = assert(toint(i1)), assert(toint(i2)) + if i1 < 0 then i1 = #l+i1 end + if i2 < 0 then i2 = #l+i2 end + i1, i2 = math.max(i1+1, 1), i2+1 + if (i2 < i1) or (i1 > #l) then return nil end + i2 = math.min(i2, #l) + return i1, i2 +end + +local _zrbs_opts = function(...) + local arg = {...} + if #arg == 0 then return {} end + local ix, opts = 1, {} + while type(arg[ix]) == "string" do + if arg[ix] == "withscores" then + opts.withscores = true + ix = ix + 1 + elseif arg[ix] == "limit" then + opts.limit = { + offset = assert(toint(arg[ix+1])), + count = assert(toint(arg[ix+2])), + } + ix = ix + 3 + else error("input") end + end + if type(arg[ix]) == "table" then + local _o = arg[ix] + opts.withscores = opts.withscores or _o.withscores + if _o.limit then + opts.limit = { + offset = assert(toint(_o.limit.offset or _o.limit[1])), + count = assert(toint(_o.limit.count or _o.limit[2])), + } + end + ix = ix + 1 + end + assert(arg[ix] == nil) + if opts.limit then + assert( + (opts.limit.count >= 0) and + (opts.limit.offset >= 0) + ) + end + return opts +end + +local _z_store_params = function(dest, numkeys, ...) + dest = chkarg(dest) + numkeys = assert(toint(numkeys)) + assert(numkeys > 0) + local arg = {...} + assert(#arg >= numkeys) + local ks = {} + for i=1, numkeys do ks[i] = chkarg(arg[i]) end + local ix, opts = numkeys+1,{} + while type(arg[ix]) == "string" do + if arg[ix] == "weights" then + opts.weights = {} + ix = ix + 1 + for i=1, numkeys do + opts.weights[i] = assert(toint(arg[ix])) + ix = ix + 1 + end + elseif arg[ix] == "aggregate" then + opts.aggregate = assert(chkarg(arg[ix+1])) + ix = ix + 2 + else error("input") end + end + if type(arg[ix]) == "table" then + local _o = arg[ix] + opts.weights = opts.weights or _o.weights + opts.aggregate = opts.aggregate or _o.aggregate + ix = ix + 1 + end + assert(arg[ix] == nil) + if opts.aggregate then + assert( + (opts.aggregate == "sum") or + (opts.aggregate == "min") or + (opts.aggregate == "max") + ) + else opts.aggregate = "sum" end + if opts.weights then + assert(#opts.weights == numkeys) + for i=1,#opts.weights do + assert(type(opts.weights[i]) == "number") + end + else + opts.weights = {} + for i=1, numkeys do opts.weights[i] = 1 end + end + opts.keys = ks + opts.dest = dest + return opts +end + +local _zrbs_limits = function(x, s1, s2, descending) + local s1_incl, s2_incl = true, true + if s1:sub(1, 1) == "(" then + s1, s1_incl = s1:sub(2, -1), false + end + s1 = assert(tofloat(s1)) + if s2:sub(1, 1) == "(" then + s2, s2_incl = s2:sub(2, -1), false + end + s2 = assert(tofloat(s2)) + if descending then + s1, s2 = s2, s1 + s1_incl, s2_incl = s2_incl, s1_incl + end + if s2 < s1 then return nil end + local l = x.list + local i1, i2 + local fst, lst = l[1].s, l[#l].s + if (fst > s2) or ((not s2_incl) and (fst == s2)) then return nil end + if (lst < s1) or ((not s1_incl) and (lst == s1)) then return nil end + if (fst > s1) or (s1_incl and (fst == s1)) then i1 = 1 end + if (lst < s2) or (s2_incl and (lst == s2)) then i2 = #l end + for i=1,#l do + if (i1 and i2) then break end + if (not i1) then + if l[i].s > s1 then i1 = i end + if s1_incl and l[i].s == s1 then i1 = i end + end + if (not i2) then + if l[i].s > s2 then i2 = i-1 end + if (not s2_incl) and l[i].s == s2 then i2 = i-1 end + end + end + assert(i1 and i2) + if descending then + return #l-i2, #l-i1 + else + return i1-1, i2-1 + end +end + +local dbg_zcoherence = function(self, k) + local x = xgetr(self, k, "zset") + return _z_coherence(x) +end + +local zadd = function(self, k, ...) + k = chkarg(k) + local ps = _z_pairs(...) + local x = xgetw(self, k, "zset") + local n = 0 + for i=1,#ps do + if not _z_update(x, ps[i]) then n = n+1 end + end + return n +end + +local zcard = function(self, k) + local x = xgetr(self, k, "zset") + return #x.list +end + +local zcount = function(self, k, s1, s2) + local x = xgetr(self, k, "zset") + local i1, i2 = _zrbs_limits(x, s1, s2, false) + if not (i1 and i2) then return 0 end + assert(i2 >= i1) + return i2 - i1 + 1 +end + +local zincrby = function(self, k, n, v) + k,v = chkargs(2, k, v) + n = assert(tofloat(n)) + local x = xgetw(self, k, "zset") + local p = x.list[x.set[v]] + local s = p and (p.s + n) or n + _z_update(x, _z_pair(s, v)) + return s +end + +local zinterstore = function(self, ...) + local params = _z_store_params(...) + local x = xdefv("zset") + local aggregate + if params.aggregate == "sum" then + aggregate = function(x, y) return x+y end + elseif params.aggregate == "min" then + aggregate = math.min + elseif params.aggregate == "max" then + aggregate = math.max + else error() end + local y = xgetr(self, params.keys[1], "zset") + local p1, p2 + for j=1,#y.list do + p1 = _z_pair(y.list[j].s, y.list[j].v) + _z_update(x, p1) + end + for i=2,#params.keys do + y = xgetr(self, params.keys[i], "zset") + local to_remove, to_update = {}, {} + for j=1,#x.list do + p1 = x.list[j] + if y.set[p1.v] then + p2 = _z_pair( + aggregate( + p1.s, + params.weights[i] * y.list[y.set[p1.v]].s + ), + p1.v + ) + to_update[#to_update+1] = p2 + else + to_remove[#to_remove+1] = p1.v + end + end + for j=1,#to_remove do _z_remove(x, to_remove[j]) end + for j=1,#to_update do _z_update(x, to_update[j]) end + end + local r = #x.list + if r > 0 then + self.data[params.dest] = {ktype = "zset", value = x} + end + return r +end + +local _zranger = function(descending) + return function(self, k, i1, i2, opts) + k = chkarg(k) + local withscores = false + if type(opts) == "table" then + withscores = opts.withscores + elseif type(opts) == "string" then + assert(opts:lower() == "withscores") + withscores = true + else assert(opts == nil) end + local x = xgetr(self, k, "zset") + local l = x.list + i1, i2 = _z_normrange(l, i1, i2) + if not i1 then return {} end + local inc = 1 + if descending then + i1 = #l - i1 + 1 + i2 = #l - i2 + 1 + inc = -1 + end + local r = {} + if withscores then + for i=i1, i2, inc do r[#r+1] = {l[i].v, l[i].s} end + else + for i=i1, i2, inc do r[#r+1] = l[i].v end + end + return r + end +end + +local zrange = _zranger(false) +local zrevrange = _zranger(true) + +local _zrangerbyscore = function(descending) + return function(self, k, s1, s2, ...) + k, s1, s2 = chkargs(3, k, s1, s2) + local opts = _zrbs_opts(...) + local x = xgetr(self, k, "zset") + local i1, i2 = _zrbs_limits(x, s1, s2, descending) + if not (i1 and i2) then return {} end + if opts.limit then + if opts.limit.count == 0 then return {} end + i1 = i1 + opts.limit.offset + if i1 > i2 then return {} end + i2 = math.min(i2, i1+opts.limit.count-1) + end + if descending then + return zrevrange(self, k, i1, i2, opts) + else + return zrange(self, k, i1, i2, opts) + end + end +end + +local zrangebyscore = _zrangerbyscore(false) +local zrevrangebyscore = _zrangerbyscore(true) + +local zrank = function(self, k, v) + local x = xgetr(self, k, "zset") + local r = x.set[v] + if r then + return r-1 + else return nil end +end + +local zrem = function(self, k, ...) + k = chkarg(k) + local arg = getargs(...) + local x, r = xgetw(self, k, "zset"), 0 + for i=1,#arg do + if _z_remove(x, arg[i]) then r = r + 1 end + end + cleanup(self, k) + return r +end + +local zremrangebyrank = function(self, k, i1, i2) + k = chkarg(k) + local x = xgetw(self, k, "zset") + i1, i2 = _z_normrange(x.list, i1, i2) + if not i1 then + cleanup(self, k) + return 0 + end + local n = _z_remove_range(x, i1, i2) + cleanup(self, k) + return n +end + +local zremrangebyscore = function(self, k, s1, s2) + local x = xgetr(self, k, "zset") + local i1, i2 = _zrbs_limits(x, s1, s2, false) + if not (i1 and i2) then return 0 end + assert(i2 >= i1) + return zremrangebyrank(self, k, i1, i2) +end + +local zrevrank = function(self, k, v) + local x = xgetr(self, k, "zset") + local r = x.set[v] + if r then + return #x.list-r + else return nil end +end + +local zscore = function(self, k, v) + local x = xgetr(self, k, "zset") + local p = x.list[x.set[v]] + if p then + return p.s + else return nil end +end + +local zunionstore = function(self, ...) + local params = _z_store_params(...) + local x = xdefv("zset") + local default_score, aggregate + if params.aggregate == "sum" then + default_score = 0 + aggregate = function(x, y) return x+y end + elseif params.aggregate == "min" then + default_score = math.huge + aggregate = math.min + elseif params.aggregate == "max" then + default_score = -math.huge + aggregate = math.max + else error() end + local y, p1, p2 + for i=1,#params.keys do + y = xgetr(self, params.keys[i], "zset") + for j=1,#y.list do + p1 = y.list[j] + p2 = _z_pair( + aggregate( + params.weights[i] * p1.s, + x.set[p1.v] and x.list[x.set[p1.v]].s or default_score + ), + p1.v + ) + _z_update(x, p2) + end + end + local r = #x.list + if r > 0 then + self.data[params.dest] = {ktype = "zset", value = x} + end + return r +end + +-- connection + +local echo = function(self, v) + return v +end + +local ping = function(self) + return true +end + +-- server + +local flushdb = function(self) + self.data = {} + return true +end + +--- Class + +local methods = { + -- keys + del = del, -- (...) -> #removed + exists = chkargs_wrap(exists, 1), -- (k) -> exists? + keys = keys, -- (pattern) -> list of keys + ["type"] = chkargs_wrap(_type, 1), -- (k) -> [string|list|set|zset|hash|none] + randomkey = randomkey, -- () -> [k|nil] + rename = chkargs_wrap(rename, 2), -- (k,k2) -> true + renamenx = chkargs_wrap(renamenx, 2), -- (k,k2) -> ! existed? k2 + -- strings + append = chkargs_wrap(append, 2), -- (k,v) -> #new + bitcount = bitcount, -- (k,[start,end]) -> n + bitop = bitop, -- ([and|or|xor|not],k,...) + decr = chkargs_wrap(decr, 1), -- (k) -> new + decrby = decrby, -- (k,n) -> new + get = chkargs_wrap(get, 1), -- (k) -> [v|nil] + getbit = getbit, -- (k,offset) -> b + getrange = getrange, -- (k,start,end) -> string + getset = chkargs_wrap(getset, 2), -- (k,v) -> [oldv|nil] + incr = chkargs_wrap(incr, 1), -- (k) -> new + incrby = incrby, -- (k,n) -> new + incrbyfloat = incrbyfloat, -- (k,n) -> new + mget = mget, -- (k1,...) -> {v1,...} + mset = mset, -- (k1,v1,...) -> true + msetnx = msetnx, -- (k1,v1,...) -> worked? (i.e. !existed? any k) + set = chkargs_wrap(set, 2), -- (k,v) -> true + setbit = setbit, -- (k,offset,b) -> old + setnx = chkargs_wrap(setnx, 2), -- (k,v) -> worked? (i.e. !existed?) + setrange = setrange, -- (k,offset,val) -> #new + strlen = chkargs_wrap(strlen, 1), -- (k) -> [#v|0] + -- hashes + hdel = hdel, -- (k,sk1,...) -> #removed + hexists = chkargs_wrap(hexists, 2), -- (k,sk) -> exists? + hget = chkargs_wrap(hget,2), -- (k,sk) -> v + hgetall = chkargs_wrap(hgetall, 1), -- (k) -> map + hincrby = hincrby, -- (k,sk,n) -> new + hincrbyfloat = hincrbyfloat, -- (k,sk,n) -> new + hkeys = chkargs_wrap(hkeys, 1), -- (k) -> keys + hlen = chkargs_wrap(hlen, 1), -- (k) -> [#sk|0] + hmget = hmget, -- (k,{sk1,...}) -> {v1,...} + hmset = hmset, -- (k,{sk1=v1,...}) -> true + hset = chkargs_wrap(hset, 3), -- (k,sk1,v1) -> !existed? + hsetnx = chkargs_wrap(hsetnx, 3), -- (k,sk1,v1) -> worked? (i.e. !existed?) + hvals = chkargs_wrap(hvals, 1), -- (k) -> values + -- lists + blpop = blpop, -- (k1,...) -> k,v + brpop = brpop, -- (k1,...) -> k,v + brpoplpush = brpoplpush, -- (k1,k2,timeout) -> v + lindex = lindex, -- (k,i) -> v + linsert = chkargs_wrap(linsert, 4), -- (k,mode,pivot,v) -> #list (after) + llen = chkargs_wrap(llen, 1), -- (k) -> #list + lpop = chkargs_wrap(lpop, 1), -- (k) -> v + lpush = lpush, -- (k,v1,...) -> #list (after) + lpushx = chkargs_wrap(lpushx, 2), -- (k,v) -> #list (after) + lrange = lrange, -- (k,start,stop) -> list + lrem = lrem, -- (k,count,v) -> #removed + lset = lset, -- (k,i,v) -> true + ltrim = ltrim, -- (k,start,stop) -> true + rpop = chkargs_wrap(rpop, 1), -- (k) -> v + rpoplpush = chkargs_wrap(rpoplpush, 2), -- (k1,k2) -> v + rpush = rpush, -- (k,v1,...) -> #list (after) + rpushx = chkargs_wrap(rpushx, 2), -- (k,v) -> #list (after) + -- sets + sadd = sadd, -- (k,v1,...) -> #added + scard = chkargs_wrap(scard, 1), -- (k) -> [n|0] + sdiff = sdiff, -- (k1,...) -> set (of elements in k1 & not in any of ...) + sdiffstore = sdiffstore, -- (k0,k1,...) -> #set at k0 + sinter = sinter, -- (k1,...) -> set + sinterstore = sinterstore, -- (k0,k1,...) -> #set at k0 + sismember = chkargs_wrap(sismember, 2), -- (k,v) -> member? + smembers = chkargs_wrap(smembers, 1), -- (k) -> set + smove = chkargs_wrap(smove, 3), -- (k1,k2,v) -> moved? (i.e. !member? k1) + spop = chkargs_wrap(spop, 1), -- (k) -> [v|nil] + srandmember = srandmember, -- (k,[count]) -> v|[v1,v2,...] + srem = srem, -- (k,v1,...) -> #removed + sunion = sunion, -- (k1,...) -> set + sunionstore = sunionstore, -- (k0,k1,...) -> #set at k0 + -- zsets + zadd = zadd, -- (k,score,member,[score,member,...]) + zcard = chkargs_wrap(zcard, 1), -- (k) -> n + zcount = chkargs_wrap(zcount, 3), -- (k,min,max) -> count + zincrby = zincrby, -- (k,score,v) -> score + zinterstore = zinterstore, -- (k,numkeys,k1,...,[opts]) -> card + zrange = zrange, -- (k,start,stop,[opts]) -> depends on opts + zrangebyscore = zrangebyscore, -- (k,min,max,[opts]) -> depends on opts + zrank = chkargs_wrap(zrank, 2), -- (k,v) -> rank + zrem = zrem, -- (k,v1,...) -> #removed + zremrangebyrank = zremrangebyrank, -- (k,start,stop) -> #removed + zremrangebyscore = chkargs_wrap(zremrangebyscore, 3), -- (k,min,max) -> #removed + zrevrange = zrevrange, -- (k,start,stop,[opts]) -> depends on opts + zrevrangebyscore = zrevrangebyscore, -- (k,min,max,[opts]) -> depends on opts + zrevrank = chkargs_wrap(zrevrank, 2), -- (k,v) -> rank + zscore = chkargs_wrap(zscore, 2), -- (k,v) -> score + zunionstore = zunionstore, -- (k,numkeys,k1,...,[opts]) -> card + -- connection + echo = chkargs_wrap(echo, 1), -- (v) -> v + ping = ping, -- () -> true + -- server + flushall = flushdb, -- () -> true + flushdb = flushdb, -- () -> true + -- debug + dbg_zcoherence = dbg_zcoherence, +} + +local new = function() + local r = {data = {}} + return setmetatable(r,{__index = methods}) +end + +return { + new = new, +} diff --git a/libs/feedparser.lua b/libs/feedparser.lua new file mode 100644 index 0000000..2beb695 --- /dev/null +++ b/libs/feedparser.lua @@ -0,0 +1,369 @@ +local LOM = assert(require("lxp.lom"), "LuaExpat doesn't seem to be installed. feedparser kind of needs it to work...") +local XMLElement = (loadfile "./libs/XMLElement.lua")() +local dateparser = (loadfile "./libs/dateparser.lua")() +local URL = (loadfile "./libs/url.lua")() +local tinsert, tremove, tconcat = table.insert, table.remove, table.concat +local pairs, ipairs = pairs, ipairs + +--- feedparser, similar to the Universal Feed Parser for python, but a good deal weaker. +-- see http://feedparser.org for details about the Universal Feed Parser +local feedparser= { + _DESCRIPTION = "RSS and Atom feed parser", + _VERSION = "feedparser 0.71" +} + +local blanky = XMLElement.new() --useful in a whole bunch of places + +local function resolve(url, base_url) + return URL.absolute(base_url, url) +end + +local function rebase(el, base_uri) + local xml_base = el:getAttr('xml:base') + if not xml_base then return base_uri end + return resolve(xml_base, base_uri) +end + +local function parse_entries(entries_el, format_str, base) + local entries = {} + for i, entry_el in ipairs(entries_el) do + local entry = {enclosures={}, links={}, contributors={}} + local entry_base = rebase(entry_el, base) + for i, el in ipairs(entry_el:getChildren('*')) do + local tag = el:getTag() + local el_base = rebase(el, entry_base) + --title + if tag == 'title' or tag == 'dc:title' or tag =='rdf:title' then --'dc:title' doesn't occur in atom feeds, but whatever. + entry.title=el:getText() + + --link(s) + elseif format_str == 'rss' and tag=='link' then + entry.link=resolve(el:getText(), el_base) + tinsert(entry.links, {href=entry.link}) + + elseif (format_str=='atom' and tag == 'link') or + (format_str == 'rss' and tag=='atom:link') then + local link = {} + for i, attr in ipairs{'rel','type', 'href','title'} do + link[attr]= (attr=='href') and resolve(el:getAttr(attr), el_base) or el:getAttr(attr) --uri + end + tinsert(entry.links, link) + if link.rel=='enclosure' then + tinsert(entry.enclosures, { + href=link.href, + length=el:getAttr('length'), + type=el:getAttr('type') + }) + end + + --rss enclosures + elseif format_str == 'rss' and tag=='enclosure' then + tinsert(entry.enclosures, { + url=el:getAttr('url'), + length=el:getAttr('length'), + type=el:getAttr('type') + }) + + --summary + elseif (format_str=='atom' and tag=='summary') or + (format_str=='rss' and(tag=='description' or tag=='dc:description' or tag=='rdf:description')) then + entry.summary=el:getText() + --TODO: summary_detail + + --content + elseif (format_str=='atom' and tag=='content') or + (format_str=='rss' and (tag=='body' or tag=='xhtml:body' or tag == 'fullitem' or tag=='content:encoded')) then + entry.content=el:getText() + --TODO: content_detail + + --published + elseif (format_str == 'atom' and (tag=='published' or tag=='issued')) or + (format_str == 'rss' and (tag=='dcterms:issued' or tag=='atom:published' or tag=='atom:issued')) then + entry.published = el:getText() + entry.published_parsed=dateparser.parse(entry.published) + + --updated + elseif (format_str=='atom' and (tag=='updated' or tag=='modified')) or + (format_str=='rss' and (tag=='dc:date' or tag=='pubDate' or tag=='dcterms:modified')) then + entry.updated=el:getText() + entry.updated_parsed=dateparser.parse(entry.updated) + + elseif tag=='created' or tag=='atom:created' or tag=='dcterms:created' then + entry.created=el:getText() + entry.created_parsed=dateparser.parse(entry.created) + + --id + elseif (format_str =='atom' and tag=='id') or + (format_str=='rss' and tag=='guid') then + entry.id=resolve(el:getText(), el_base) -- this is a uri, right?... + + --author + elseif format_str=='rss' and (tag=='author' or tag=='dc:creator') then --author tag should give the author's email. should I respect this? + entry.author=(el:getChild('name') or el):getText() + entry.author_detail={ + name=entry.author + } + elseif format_str=='atom' and tag=='author' then + entry.author=(el:getChild('name') or el):getText() + entry.author_detail = { + name=entry.author, + email=(el:getChild('email') or blanky):getText() + } + local author_url = (el:getChild('url') or blanky):getText() + if author_url and author_url ~= "" then entry.author_detail.href=resolve(author_url, rebase(el:getChild('url'), el_base)) end + + elseif tag=='category' or tag=='dc:subject' then + --todo + + elseif tag=='source' then + --todo + end + end + + --wrap up rss guid + if format_str == 'rss' and (not entry.id) and entry_el:getAttr('rdf:about') then + entry.id=resolve(entry_el:getAttr('rdf:about'), entry_base) --uri + end + + --wrap up entry.link + for i, link in pairs(entry.links) do + if link.rel=="alternate" or (not link.rel) or link.rel=="" then + entry.link=link.href --already resolved. + break + end + end + if not entry.link and format_str=='rss' then + entry.link=entry.id + end + tinsert(entries, entry) + end + return entries +end + +local function atom_person_construct(person_el, base_uri) + local dude ={ + name= (person_el:getChild('name') or blanky):getText(), + email=(person_el:getChild('email') or blanky):getText() + } + local url_el = person_el:getChild('url') + if url_el then dude.href=resolve(url_el:getText(), rebase(url_el, base_uri)) end + return dude +end + +local function parse_atom(root, base_uri) + local res = {} + local feed = { + links = {}, + contributors={}, + language = root:getAttr('lang') or root:getAttr('xml:lang') + } + local root_base = rebase(root, base_uri) + res.feed=feed + res.format='atom' + local version=(root:getAttr('version') or ''):lower() + if version=="1.0" or root:getAttr('xmlns')=='http://www.w3.org/2005/Atom' then res.version='atom10' + elseif version=="0.3" then res.version='atom03' + else res.version='atom' end + + for i, el in ipairs(root:getChildren('*')) do + local tag = el:getTag() + local el_base=rebase(el, root_base) + if tag == 'title' or tag == 'dc:title' or tag == 'atom10:title' or tag == 'atom03:title' then + feed.title=el:getText() --sanitize! + --todo: feed.title_detail + + --link stuff + elseif tag=='link' then + local link = {} + for i, attr in ipairs{'rel','type', 'href','title'} do + link[attr]= (attr=='href') and resolve(el:getAttr(attr), el_base) or el:getAttr(attr) + end + tinsert(feed.links, link) + + --subtitle + elseif tag == 'subtitle' then + feed.subtitle=el:getText() --sanitize! + elseif not feed.subtitle and (tag == 'tagline' or tag =='atom03:tagline' or tag=='dc:description') then + feed.subtitle=el:getText() --sanitize! + + --rights + elseif tag == 'copyright' or tag == 'rights' then + feed.rights=el:getText() --sanitize! + + --generator + elseif tag == 'generator' then + feed.generator=el:getText() --sanitize! + elseif tag == 'admin:generatorAgent' then + feed.generator = feed.generator or el:getAttr('rdf:resource') + + --info + elseif tag == 'info' then --whatever, nobody cared, anyway. + feed.info = el:getText() + + --id + elseif tag=='id' then + feed.id=resolve(el:getText(), el_base) --this is a url, right?.,, + + --updated + elseif tag == 'updated' or tag == 'dc:date' or tag == 'modified' or tag=='rss:pubDate' then + feed.updated = el:getText() + feed.updated_parsed=dateparser.parse(feed.updated) + + --author + elseif tag=='author' or tag=='atom:author' then + feed.author_detail=atom_person_construct(el, el_base) + feed.author=feed.author_detail.name + + --contributors + elseif tag=='contributor' or tag=='atom:contributor' then + tinsert(feed.contributors, atom_person_construct(el, el_base)) + + --icon + elseif tag=='icon' then + feed.icon=resolve(el:getText(), el_base) + + --logo + elseif tag=='logo' then + feed.logo=resolve(el:getText(), el_base) + + --language + elseif tag=='language' or tag=='dc:language' then + feed.language=feed.language or el:getText() + + --licence + end + end + --feed.link (already resolved) + for i, link in pairs(feed.links) do + if link.rel=='alternate' or not link.rel or link.rel=='' then + feed.link=link.href + break + end + end + + res.entries=parse_entries(root:getChildren('entry'),'atom', root_base) + return res +end + +local function parse_rss(root, base_uri) + + local channel = root:getChild({'channel', 'rdf:channel'}) + local channel_base = rebase(channel, base_uri) + if not channel then return nil, "can't parse that." end + + local feed = {links = {}, contributors={}} + local res = { + feed=feed, + format='rss', + entries={} + } + + --this isn't quite right at all. + if root:getTag():lower()=='rdf:rdf' then + res.version='rss10' + else + res.version='rss20' + end + + for i, el in ipairs(channel:getChildren('*')) do + local el_base=rebase(el, channel_base) + local tag = el:getTag() + + if tag=='link' then + feed.link=resolve(el:getText(), el_base) + tinsert(feed.links, {href=feed.link}) + + --title + elseif tag == 'title' or tag == 'dc:title' then + feed.title=el:getText() --sanitize! + + --subtitle + elseif tag == 'description' or tag =='dc:description' or tag=='itunes:subtitle' then + feed.subtitle=el:getText() --sanitize! + + --rights + elseif tag == 'copyright' or tag == 'dc:rights' then + feed.rights=el:getText() --sanitize! + + --generator + elseif tag == 'generator' then + feed.generator=el:getText() + elseif tag == 'admin:generatorAgent' then + feed.generator = feed.generator or el:getAttr('rdf:resource') + + --info (nobody cares...) + elseif tag == 'feedburner:browserFriendly' then + feed.info = el:getText() + + --updated + elseif tag == 'pubDate' or tag == 'dc:date' or tag == 'dcterms:modified' then + feed.updated = el:getText() + feed.updated_parsed = dateparser.parse(feed.updated) + + --author + elseif tag=='managingEditor' or tag =='dc:creator' or tag=='itunes:author' or tag =='dc:creator' or tag=='dc:author' then + feed.author=tconcat(el:getChildren('text()')) + feed.author_details={name=feed.author} + elseif tag=='atom:author' then + feed.author_details = atom_person_construct(el, el_base) + feed.author = feed.author_details.name + + --contributors + elseif tag == 'dc:contributor' then + tinsert(feed.contributors, {name=el:getText()}) + elseif tag == 'atom:contributor' then + tinsert(feed.contributors, atom_person_construct(el, el_base)) + + --image + elseif tag=='image' or tag=='rdf:image' then + feed.image={ + title=el:getChild('title'):getText(), + link=(el:getChild('link') or blanky):getText(), + width=(el:getChild('width') or blanky):getText(), + height=(el:getChild('height') or blanky):getText() + } + local url_el = el:getChild('url') + if url_el then feed.image.href = resolve(url_el:getText(), rebase(url_el, el_base)) end + + --language + elseif tag=='language' or tag=='dc:language' then + feed.language=el:getText() + + --licence + --publisher + --tags + end + end + + res.entries=parse_entries(channel:getChildren('item'),'rss', channel_base) + return res +end + + +--- parse feed xml +-- @param xml_string feed xml, as a string +-- @param base_url (optional) source url of the feed. useful when resolving relative links found in feed contents +-- @return table with parsed feed info, or nil, error_message on error. +-- the format of the returned table is much like that on http://feedparser.org, with the major difference that +-- dates are parsed into unixtime. Most other fields are very much the same. +function feedparser.parse(xml_string, base_url) + local lom, err = LOM.parse(xml_string) + if not lom then return nil, "couldn't parse xml. lxp says: " .. err or "nothing" end + local rootElement = XMLElement.new(lom) + local root_tag = rootElement:getTag():lower() + if root_tag=='rdf:rdf' or root_tag=='rss' then + return parse_rss(rootElement, base_url) + elseif root_tag=='feed' then + return parse_atom(rootElement, base_url) + else + return nil, "unknown feed format" + end +end + +--for the sake of backwards-compatibility, feedparser will export a global reference for lua < 5.3 +if _VERSION:sub(-3) < "5.3" then + _G.feedparser=feedparser +end + + +return feedparser diff --git a/libs/lua-redis.lua b/libs/lua-redis.lua new file mode 100644 index 0000000..77aea79 --- /dev/null +++ b/libs/lua-redis.lua @@ -0,0 +1,1140 @@ +local redis = { + _VERSION = 'redis-lua 2.0.4', + _DESCRIPTION = 'A Lua client library for the redis key value storage system.', + _COPYRIGHT = 'Copyright (C) 2009-2012 Daniele Alessandri', +} + +-- The following line is used for backwards compatibility in order to keep the `Redis` +-- global module name. Using `Redis` is now deprecated so you should explicitly assign +-- the module to a local variable when requiring it: `local redis = require('redis')`. +Redis = redis + +local unpack = _G.unpack or table.unpack +local network, request, response = {}, {}, {} + +local defaults = { + host = '127.0.0.1', + port = 6379, + tcp_nodelay = true, + path = nil +} + +local function merge_defaults(parameters) + if parameters == nil then + parameters = {} + end + for k, v in pairs(defaults) do + if parameters[k] == nil then + parameters[k] = defaults[k] + end + end + return parameters +end + +local function parse_boolean(v) + if v == '1' or v == 'true' or v == 'TRUE' then + return true + elseif v == '0' or v == 'false' or v == 'FALSE' then + return false + else + return nil + end +end + +local function toboolean(value) return value == 1 end + +local function sort_request(client, command, key, params) + --[[ params = { + by = 'weight_*', + get = 'object_*', + limit = { 0, 10 }, + sort = 'desc', + alpha = true, + } ]] + local query = { key } + + if params then + if params.by then + table.insert(query, 'BY') + table.insert(query, params.by) + end + + if type(params.limit) == 'table' then + -- TODO: check for lower and upper limits + table.insert(query, 'LIMIT') + table.insert(query, params.limit[1]) + table.insert(query, params.limit[2]) + end + + if params.get then + if (type(params.get) == 'table') then + for _, getarg in pairs(params.get) do + table.insert(query, 'GET') + table.insert(query, getarg) + end + else + table.insert(query, 'GET') + table.insert(query, params.get) + end + end + + if params.sort then + table.insert(query, params.sort) + end + + if params.alpha == true then + table.insert(query, 'ALPHA') + end + + if params.store then + table.insert(query, 'STORE') + table.insert(query, params.store) + end + end + + request.multibulk(client, command, query) +end + +local function zset_range_request(client, command, ...) + local args, opts = {...}, { } + + if #args >= 1 and type(args[#args]) == 'table' then + local options = table.remove(args, #args) + if options.withscores then + table.insert(opts, 'WITHSCORES') + end + end + + for _, v in pairs(opts) do table.insert(args, v) end + request.multibulk(client, command, args) +end + +local function zset_range_byscore_request(client, command, ...) + local args, opts = {...}, { } + + if #args >= 1 and type(args[#args]) == 'table' then + local options = table.remove(args, #args) + if options.limit then + table.insert(opts, 'LIMIT') + table.insert(opts, options.limit.offset or options.limit[1]) + table.insert(opts, options.limit.count or options.limit[2]) + end + if options.withscores then + table.insert(opts, 'WITHSCORES') + end + end + + for _, v in pairs(opts) do table.insert(args, v) end + request.multibulk(client, command, args) +end + +local function zset_range_reply(reply, command, ...) + local args = {...} + local opts = args[4] + if opts and (opts.withscores or string.lower(tostring(opts)) == 'withscores') then + local new_reply = { } + for i = 1, #reply, 2 do + table.insert(new_reply, { reply[i], reply[i + 1] }) + end + return new_reply + else + return reply + end +end + +local function zset_store_request(client, command, ...) + local args, opts = {...}, { } + + if #args >= 1 and type(args[#args]) == 'table' then + local options = table.remove(args, #args) + if options.weights and type(options.weights) == 'table' then + table.insert(opts, 'WEIGHTS') + for _, weight in ipairs(options.weights) do + table.insert(opts, weight) + end + end + if options.aggregate then + table.insert(opts, 'AGGREGATE') + table.insert(opts, options.aggregate) + end + end + + for _, v in pairs(opts) do table.insert(args, v) end + request.multibulk(client, command, args) +end + +local function mset_filter_args(client, command, ...) + local args, arguments = {...}, {} + if (#args == 1 and type(args[1]) == 'table') then + for k,v in pairs(args[1]) do + table.insert(arguments, k) + table.insert(arguments, v) + end + else + arguments = args + end + request.multibulk(client, command, arguments) +end + +local function hash_multi_request_builder(builder_callback) + return function(client, command, ...) + local args, arguments = {...}, { } + if #args == 2 then + table.insert(arguments, args[1]) + for k, v in pairs(args[2]) do + builder_callback(arguments, k, v) + end + else + arguments = args + end + request.multibulk(client, command, arguments) + end +end + +local function parse_info(response) + local info = {} + local current = info + + response:gsub('([^\r\n]*)\r\n', function(kv) + if kv == '' then return end + + local section = kv:match('^# (%w+)$') + if section then + current = {} + info[section:lower()] = current + return + end + + local k,v = kv:match(('([^:]*):([^:]*)'):rep(1)) + if k:match('db%d+') then + current[k] = {} + v:gsub(',', function(dbkv) + local dbk,dbv = kv:match('([^:]*)=([^:]*)') + current[k][dbk] = dbv + end) + else + current[k] = v + end + end) + + return info +end + +local function load_methods(proto, commands) + local client = setmetatable ({}, getmetatable(proto)) + + for cmd, fn in pairs(commands) do + if type(fn) ~= 'function' then + redis.error('invalid type for command ' .. cmd .. '(must be a function)') + end + client[cmd] = fn + end + + for i, v in pairs(proto) do + client[i] = v + end + + return client +end + +local function create_client(proto, client_socket, commands) + local client = load_methods(proto, commands) + client.error = redis.error + client.network = { + socket = client_socket, + read = network.read, + write = network.write, + } + client.requests = { + multibulk = request.multibulk, + } + return client +end + +-- ############################################################################ + +function network.write(client, buffer) + local _, err = client.network.socket:send(buffer) + if err then client.error(err) end +end + +function network.read(client, len) + if len == nil then len = '*l' end + local line, err = client.network.socket:receive(len) + if not err then return line else client.error('connection error: ' .. err) end +end + +-- ############################################################################ + +function response.read(client) + local payload = client.network.read(client) + local prefix, data = payload:sub(1, -#payload), payload:sub(2) + + -- status reply + if prefix == '+' then + if data == 'OK' then + return true + elseif data == 'QUEUED' then + return { queued = true } + else + return data + end + + -- error reply + elseif prefix == '-' then + return client.error('redis error: ' .. data) + + -- integer reply + elseif prefix == ':' then + local number = tonumber(data) + + if not number then + if res == 'nil' then + return nil + end + client.error('cannot parse '..res..' as a numeric response.') + end + + return number + + -- bulk reply + elseif prefix == '$' then + local length = tonumber(data) + + if not length then + client.error('cannot parse ' .. length .. ' as data length') + end + + if length == -1 then + return nil + end + + local nextchunk = client.network.read(client, length + 2) + + return nextchunk:sub(1, -3) + + -- multibulk reply + elseif prefix == '*' then + local count = tonumber(data) + + if count == -1 then + return nil + end + + local list = {} + if count > 0 then + local reader = response.read + for i = 1, count do + list[i] = reader(client) + end + end + return list + + -- unknown type of reply + else + return client.error('unknown response prefix: ' .. prefix) + end +end + +-- ############################################################################ + +function request.raw(client, buffer) + local bufferType = type(buffer) + + if bufferType == 'table' then + client.network.write(client, table.concat(buffer)) + elseif bufferType == 'string' then + client.network.write(client, buffer) + else + client.error('argument error: ' .. bufferType) + end +end + +function request.multibulk(client, command, ...) + local args = {...} + local argsn = #args + local buffer = { true, true } + + if argsn == 1 and type(args[1]) == 'table' then + argsn, args = #args[1], args[1] + end + + buffer[1] = '*' .. tostring(argsn + 1) .. "\r\n" + buffer[2] = '$' .. #command .. "\r\n" .. command .. "\r\n" + + local table_insert = table.insert + for _, argument in pairs(args) do + local s_argument = tostring(argument) + table_insert(buffer, '$' .. #s_argument .. "\r\n" .. s_argument .. "\r\n") + end + + client.network.write(client, table.concat(buffer)) +end + +-- ############################################################################ + +local function custom(command, send, parse) + command = string.upper(command) + return function(client, ...) + send(client, command, ...) + local reply = response.read(client) + + if type(reply) == 'table' and reply.queued then + reply.parser = parse + return reply + else + if parse then + return parse(reply, command, ...) + end + return reply + end + end +end + +local function command(command, opts) + if opts == nil or type(opts) == 'function' then + return custom(command, request.multibulk, opts) + else + return custom(command, opts.request or request.multibulk, opts.response) + end +end + +local define_command_impl = function(target, name, opts) + local opts = opts or {} + target[string.lower(name)] = custom( + opts.command or string.upper(name), + opts.request or request.multibulk, + opts.response or nil + ) +end + +local undefine_command_impl = function(target, name) + target[string.lower(name)] = nil +end + +-- ############################################################################ + +local client_prototype = {} + +client_prototype.raw_cmd = function(client, buffer) + request.raw(client, buffer .. "\r\n") + return response.read(client) +end + +-- obsolete +client_prototype.define_command = function(client, name, opts) + define_command_impl(client, name, opts) +end + +-- obsolete +client_prototype.undefine_command = function(client, name) + undefine_command_impl(client, name) +end + +client_prototype.quit = function(client) + request.multibulk(client, 'QUIT') + client.network.socket:shutdown() + return true +end + +client_prototype.shutdown = function(client) + request.multibulk(client, 'SHUTDOWN') + client.network.socket:shutdown() +end + +-- Command pipelining + +client_prototype.pipeline = function(client, block) + local requests, replies, parsers = {}, {}, {} + local table_insert = table.insert + local socket_write, socket_read = client.network.write, client.network.read + + client.network.write = function(_, buffer) + table_insert(requests, buffer) + end + + -- TODO: this hack is necessary to temporarily reuse the current + -- request -> response handling implementation of redis-lua + -- without further changes in the code, but it will surely + -- disappear when the new command-definition infrastructure + -- will finally be in place. + client.network.read = function() return '+QUEUED' end + + local pipeline = setmetatable({}, { + __index = function(env, name) + local cmd = client[name] + if not cmd then + client.error('unknown redis command: ' .. name, 2) + end + return function(self, ...) + local reply = cmd(client, ...) + table_insert(parsers, #requests, reply.parser) + return reply + end + end + }) + + local success, retval = pcall(block, pipeline) + + client.network.write, client.network.read = socket_write, socket_read + if not success then client.error(retval, 0) end + + client.network.write(client, table.concat(requests, '')) + + for i = 1, #requests do + local reply, parser = response.read(client), parsers[i] + if parser then + reply = parser(reply) + end + table_insert(replies, i, reply) + end + + return replies, #requests +end + +-- Publish/Subscribe + +do + local channels = function(channels) + if type(channels) == 'string' then + channels = { channels } + end + return channels + end + + local subscribe = function(client, ...) + request.multibulk(client, 'subscribe', ...) + end + local psubscribe = function(client, ...) + request.multibulk(client, 'psubscribe', ...) + end + local unsubscribe = function(client, ...) + request.multibulk(client, 'unsubscribe') + end + local punsubscribe = function(client, ...) + request.multibulk(client, 'punsubscribe') + end + + local consumer_loop = function(client) + local aborting, subscriptions = false, 0 + + local abort = function() + if not aborting then + unsubscribe(client) + punsubscribe(client) + aborting = true + end + end + + return coroutine.wrap(function() + while true do + local message + local response = response.read(client) + + if response[1] == 'pmessage' then + message = { + kind = response[1], + pattern = response[2], + channel = response[3], + payload = response[4], + } + else + message = { + kind = response[1], + channel = response[2], + payload = response[3], + } + end + + if string.match(message.kind, '^p?subscribe$') then + subscriptions = subscriptions + 1 + end + if string.match(message.kind, '^p?unsubscribe$') then + subscriptions = subscriptions - 1 + end + + if aborting and subscriptions == 0 then + break + end + coroutine.yield(message, abort) + end + end) + end + + client_prototype.pubsub = function(client, subscriptions) + if type(subscriptions) == 'table' then + if subscriptions.subscribe then + subscribe(client, channels(subscriptions.subscribe)) + end + if subscriptions.psubscribe then + psubscribe(client, channels(subscriptions.psubscribe)) + end + end + return consumer_loop(client) + end +end + +-- Redis transactions (MULTI/EXEC) + +do + local function identity(...) return ... end + local emptytable = {} + + local function initialize_transaction(client, options, block, queued_parsers) + local table_insert = table.insert + local coro = coroutine.create(block) + + if options.watch then + local watch_keys = {} + for _, key in pairs(options.watch) do + table_insert(watch_keys, key) + end + if #watch_keys > 0 then + client:watch(unpack(watch_keys)) + end + end + + local transaction_client = setmetatable({}, {__index=client}) + transaction_client.exec = function(...) + client.error('cannot use EXEC inside a transaction block') + end + transaction_client.multi = function(...) + coroutine.yield() + end + transaction_client.commands_queued = function() + return #queued_parsers + end + + assert(coroutine.resume(coro, transaction_client)) + + transaction_client.multi = nil + transaction_client.discard = function(...) + local reply = client:discard() + for i, v in pairs(queued_parsers) do + queued_parsers[i]=nil + end + coro = initialize_transaction(client, options, block, queued_parsers) + return reply + end + transaction_client.watch = function(...) + client.error('WATCH inside MULTI is not allowed') + end + setmetatable(transaction_client, { __index = function(t, k) + local cmd = client[k] + if type(cmd) == "function" then + local function queuey(self, ...) + local reply = cmd(client, ...) + assert((reply or emptytable).queued == true, 'a QUEUED reply was expected') + table_insert(queued_parsers, reply.parser or identity) + return reply + end + t[k]=queuey + return queuey + else + return cmd + end + end + }) + client:multi() + return coro + end + + local function transaction(client, options, coroutine_block, attempts) + local queued_parsers, replies = {}, {} + local retry = tonumber(attempts) or tonumber(options.retry) or 2 + local coro = initialize_transaction(client, options, coroutine_block, queued_parsers) + + local success, retval + if coroutine.status(coro) == 'suspended' then + success, retval = coroutine.resume(coro) + else + -- do not fail if the coroutine has not been resumed (missing t:multi() with CAS) + success, retval = true, 'empty transaction' + end + if #queued_parsers == 0 or not success then + client:discard() + assert(success, retval) + return replies, 0 + end + + local raw_replies = client:exec() + if not raw_replies then + if (retry or 0) <= 0 then + client.error("MULTI/EXEC transaction aborted by the server") + else + --we're not quite done yet + return transaction(client, options, coroutine_block, retry - 1) + end + end + + local table_insert = table.insert + for i, parser in pairs(queued_parsers) do + table_insert(replies, i, parser(raw_replies[i])) + end + + return replies, #queued_parsers + end + + client_prototype.transaction = function(client, arg1, arg2) + local options, block + if not arg2 then + options, block = {}, arg1 + elseif arg1 then --and arg2, implicitly + options, block = type(arg1)=="table" and arg1 or { arg1 }, arg2 + else + client.error("Invalid parameters for redis transaction.") + end + + if not options.watch then + watch_keys = { } + for i, v in pairs(options) do + if tonumber(i) then + table.insert(watch_keys, v) + options[i] = nil + end + end + options.watch = watch_keys + elseif not (type(options.watch) == 'table') then + options.watch = { options.watch } + end + + if not options.cas then + local tx_block = block + block = function(client, ...) + client:multi() + return tx_block(client, ...) --can't wrap this in pcall because we're in a coroutine. + end + end + + return transaction(client, options, block) + end +end + +-- MONITOR context + +do + local monitor_loop = function(client) + local monitoring = true + + -- Tricky since the payload format changed starting from Redis 2.6. + local pattern = '^(%d+%.%d+)( ?.- ?) ?"(%a+)" ?(.-)$' + + local abort = function() + monitoring = false + end + + return coroutine.wrap(function() + client:monitor() + + while monitoring do + local message, matched + local response = response.read(client) + + local ok = response:gsub(pattern, function(time, info, cmd, args) + message = { + timestamp = tonumber(time), + client = info:match('%d+.%d+.%d+.%d+:%d+'), + database = tonumber(info:match('%d+')) or 0, + command = cmd, + arguments = args:match('.+'), + } + matched = true + end) + + if not matched then + client.error('Unable to match MONITOR payload: '..response) + end + + coroutine.yield(message, abort) + end + end) + end + + client_prototype.monitor_messages = function(client) + return monitor_loop(client) + end +end + +-- ############################################################################ + +local function connect_tcp(socket, parameters) + local host, port = parameters.host, tonumber(parameters.port) + local ok, err = socket:connect(host, port) + if not ok then + redis.error('could not connect to '..host..':'..port..' ['..err..']') + end + socket:setoption('tcp-nodelay', parameters.tcp_nodelay) + return socket +end + +local function connect_unix(socket, parameters) + local ok, err = socket:connect(parameters.path) + if not ok then + redis.error('could not connect to '..parameters.path..' ['..err..']') + end + return socket +end + +local function create_connection(parameters) + if parameters.socket then + return parameters.socket + end + + local perform_connection, socket + + if parameters.scheme == 'unix' then + perform_connection, socket = connect_unix, require('socket.unix') + assert(socket, 'your build of LuaSocket does not support UNIX domain sockets') + else + if parameters.scheme then + local scheme = parameters.scheme + assert(scheme == 'redis' or scheme == 'tcp', 'invalid scheme: '..scheme) + end + perform_connection, socket = connect_tcp, require('socket').tcp + end + + return perform_connection(socket(), parameters) +end + +-- ############################################################################ + +function redis.error(message, level) + error(message, (level or 1) + 1) +end + +function redis.connect(...) + local args, parameters = {...}, nil + + if #args == 1 then + if type(args[1]) == 'table' then + parameters = args[1] + else + local uri = require('socket.url') + parameters = uri.parse(select(1, ...)) + if parameters.scheme then + if parameters.query then + for k, v in parameters.query:gmatch('([-_%w]+)=([-_%w]+)') do + if k == 'tcp_nodelay' or k == 'tcp-nodelay' then + parameters.tcp_nodelay = parse_boolean(v) + end + end + end + else + parameters.host = parameters.path + end + end + elseif #args > 1 then + local host, port = unpack(args) + parameters = { host = host, port = port } + end + + local commands = redis.commands or {} + if type(commands) ~= 'table' then + redis.error('invalid type for the commands table') + end + + local socket = create_connection(merge_defaults(parameters)) + local client = create_client(client_prototype, socket, commands) + + return client +end + +function redis.command(cmd, opts) + return command(cmd, opts) +end + +-- obsolete +function redis.define_command(name, opts) + define_command_impl(redis.commands, name, opts) +end + +-- obsolete +function redis.undefine_command(name) + undefine_command_impl(redis.commands, name) +end + +-- ############################################################################ + +-- Commands defined in this table do not take the precedence over +-- methods defined in the client prototype table. + +redis.commands = { + -- commands operating on the key space + exists = command('EXISTS', { + response = toboolean + }), + del = command('DEL'), + type = command('TYPE'), + rename = command('RENAME'), + renamenx = command('RENAMENX', { + response = toboolean + }), + expire = command('EXPIRE', { + response = toboolean + }), + pexpire = command('PEXPIRE', { -- >= 2.6 + response = toboolean + }), + expireat = command('EXPIREAT', { + response = toboolean + }), + pexpireat = command('PEXPIREAT', { -- >= 2.6 + response = toboolean + }), + ttl = command('TTL'), + pttl = command('PTTL'), -- >= 2.6 + move = command('MOVE', { + response = toboolean + }), + dbsize = command('DBSIZE'), + persist = command('PERSIST', { -- >= 2.2 + response = toboolean + }), + keys = command('KEYS', { + response = function(response) + if type(response) == 'string' then + -- backwards compatibility path for Redis < 2.0 + local keys = {} + response:gsub('[^%s]+', function(key) + table.insert(keys, key) + end) + response = keys + end + return response + end + }), + randomkey = command('RANDOMKEY', { + response = function(response) + if response == '' then + return nil + else + return response + end + end + }), + sort = command('SORT', { + request = sort_request, + }), + + -- commands operating on string values + set = command('SET'), + setnx = command('SETNX', { + response = toboolean + }), + setex = command('SETEX'), -- >= 2.0 + psetex = command('PSETEX'), -- >= 2.6 + mset = command('MSET', { + request = mset_filter_args + }), + msetnx = command('MSETNX', { + request = mset_filter_args, + response = toboolean + }), + get = command('GET'), + mget = command('MGET'), + getset = command('GETSET'), + incr = command('INCR'), + incrby = command('INCRBY'), + incrbyfloat = command('INCRBYFLOAT', { -- >= 2.6 + response = function(reply, command, ...) + return tonumber(reply) + end, + }), + decr = command('DECR'), + decrby = command('DECRBY'), + append = command('APPEND'), -- >= 2.0 + substr = command('SUBSTR'), -- >= 2.0 + strlen = command('STRLEN'), -- >= 2.2 + setrange = command('SETRANGE'), -- >= 2.2 + getrange = command('GETRANGE'), -- >= 2.2 + setbit = command('SETBIT'), -- >= 2.2 + getbit = command('GETBIT'), -- >= 2.2 + + -- commands operating on lists + rpush = command('RPUSH'), + lpush = command('LPUSH'), + llen = command('LLEN'), + lrange = command('LRANGE'), + ltrim = command('LTRIM'), + lindex = command('LINDEX'), + lset = command('LSET'), + lrem = command('LREM'), + lpop = command('LPOP'), + rpop = command('RPOP'), + rpoplpush = command('RPOPLPUSH'), + blpop = command('BLPOP'), -- >= 2.0 + brpop = command('BRPOP'), -- >= 2.0 + rpushx = command('RPUSHX'), -- >= 2.2 + lpushx = command('LPUSHX'), -- >= 2.2 + linsert = command('LINSERT'), -- >= 2.2 + brpoplpush = command('BRPOPLPUSH'), -- >= 2.2 + + -- commands operating on sets + sadd = command('SADD'), + srem = command('SREM'), + spop = command('SPOP'), + smove = command('SMOVE', { + response = toboolean + }), + scard = command('SCARD'), + sismember = command('SISMEMBER', { + response = toboolean + }), + sinter = command('SINTER'), + sinterstore = command('SINTERSTORE'), + sunion = command('SUNION'), + sunionstore = command('SUNIONSTORE'), + sdiff = command('SDIFF'), + sdiffstore = command('SDIFFSTORE'), + smembers = command('SMEMBERS'), + srandmember = command('SRANDMEMBER'), + + -- commands operating on sorted sets + zadd = command('ZADD'), + zincrby = command('ZINCRBY'), + zrem = command('ZREM'), + zrange = command('ZRANGE', { + request = zset_range_request, + response = zset_range_reply, + }), + zrevrange = command('ZREVRANGE', { + request = zset_range_request, + response = zset_range_reply, + }), + zrangebyscore = command('ZRANGEBYSCORE', { + request = zset_range_byscore_request, + response = zset_range_reply, + }), + zrevrangebyscore = command('ZREVRANGEBYSCORE', { -- >= 2.2 + request = zset_range_byscore_request, + response = zset_range_reply, + }), + zunionstore = command('ZUNIONSTORE', { -- >= 2.0 + request = zset_store_request + }), + zinterstore = command('ZINTERSTORE', { -- >= 2.0 + request = zset_store_request + }), + zcount = command('ZCOUNT'), + zcard = command('ZCARD'), + zscore = command('ZSCORE'), + zremrangebyscore = command('ZREMRANGEBYSCORE'), + zrank = command('ZRANK'), -- >= 2.0 + zrevrank = command('ZREVRANK'), -- >= 2.0 + zremrangebyrank = command('ZREMRANGEBYRANK'), -- >= 2.0 + + -- commands operating on hashes + hset = command('HSET', { -- >= 2.0 + response = toboolean + }), + hsetnx = command('HSETNX', { -- >= 2.0 + response = toboolean + }), + hmset = command('HMSET', { -- >= 2.0 + request = hash_multi_request_builder(function(args, k, v) + table.insert(args, k) + table.insert(args, v) + end), + }), + hincrby = command('HINCRBY'), -- >= 2.0 + hincrbyfloat = command('HINCRBYFLOAT', {-- >= 2.6 + response = function(reply, command, ...) + return tonumber(reply) + end, + }), + hget = command('HGET'), -- >= 2.0 + hmget = command('HMGET', { -- >= 2.0 + request = hash_multi_request_builder(function(args, k, v) + table.insert(args, v) + end), + }), + hdel = command('HDEL'), -- >= 2.0 + hexists = command('HEXISTS', { -- >= 2.0 + response = toboolean + }), + hlen = command('HLEN'), -- >= 2.0 + hkeys = command('HKEYS'), -- >= 2.0 + hvals = command('HVALS'), -- >= 2.0 + hgetall = command('HGETALL', { -- >= 2.0 + 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 + }), + + -- connection related commands + ping = command('PING', { + response = function(response) return response == 'PONG' end + }), + echo = command('ECHO'), + auth = command('AUTH'), + select = command('SELECT'), + + -- transactions + multi = command('MULTI'), -- >= 2.0 + exec = command('EXEC'), -- >= 2.0 + discard = command('DISCARD'), -- >= 2.0 + watch = command('WATCH'), -- >= 2.2 + unwatch = command('UNWATCH'), -- >= 2.2 + + -- publish - subscribe + subscribe = command('SUBSCRIBE'), -- >= 2.0 + unsubscribe = command('UNSUBSCRIBE'), -- >= 2.0 + psubscribe = command('PSUBSCRIBE'), -- >= 2.0 + punsubscribe = command('PUNSUBSCRIBE'), -- >= 2.0 + publish = command('PUBLISH'), -- >= 2.0 + + -- redis scripting + eval = command('EVAL'), -- >= 2.6 + evalsha = command('EVALSHA'), -- >= 2.6 + script = command('SCRIPT'), -- >= 2.6 + + -- remote server control commands + bgrewriteaof = command('BGREWRITEAOF'), + config = command('CONFIG', { -- >= 2.0 + response = function(reply, command, ...) + if (type(reply) == 'table') then + local new_reply = { } + for i = 1, #reply, 2 do new_reply[reply[i]] = reply[i + 1] end + return new_reply + end + + return reply + end + }), + client = command('CLIENT'), -- >= 2.4 + slaveof = command('SLAVEOF'), + save = command('SAVE'), + bgsave = command('BGSAVE'), + lastsave = command('LASTSAVE'), + flushdb = command('FLUSHDB'), + flushall = command('FLUSHALL'), + monitor = command('MONITOR'), + time = command('TIME'), -- >= 2.6 + slowlog = command('SLOWLOG', { -- >= 2.2.13 + response = function(reply, command, ...) + if (type(reply) == 'table') then + local structured = { } + for index, entry in ipairs(reply) do + structured[index] = { + id = tonumber(entry[1]), + timestamp = tonumber(entry[2]), + duration = tonumber(entry[3]), + command = entry[4], + } + end + return structured + end + + return reply + end + }), + info = command('INFO', { + response = parse_info, + }), +} + +-- ############################################################################ + +return redis diff --git a/libs/redis.lua b/libs/redis.lua index c09142b..419b684 100644 --- a/libs/redis.lua +++ b/libs/redis.lua @@ -1,5 +1,5 @@ -local Redis = require 'redis' -local FakeRedis = require 'fakeredis' +local Redis = (loadfile "./libs/lua-redis.lua")() +local FakeRedis = (loadfile "./libs/fakeredis.lua")() local params = { host = '127.0.0.1', @@ -44,4 +44,4 @@ if not ok then end -return redis \ No newline at end of file +return redis diff --git a/libs/serpent.lua b/libs/serpent.lua new file mode 100644 index 0000000..381db57 --- /dev/null +++ b/libs/serpent.lua @@ -0,0 +1,124 @@ +local n, v = "serpent", 0.28 -- (C) 2012-15 Paul Kulchenko; MIT License +local c, d = "Paul Kulchenko", "Lua serializer and pretty printer" +local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'} +local badtype = {thread = true, userdata = true, cdata = true} +local keyword, globals, G = {}, {}, (_G or _ENV) +for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false', + 'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat', + 'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end +for k,v in pairs(G) do globals[v] = k end -- build func to name mapping +for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do + for k,v in pairs(G[g] or {}) do globals[v] = g..'.'..k end end + +local function s(t, opts) + local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum + local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge + local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge) + local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge) + local seen, sref, syms, symn = {}, {'local '..iname..'={}'}, {}, 0 + local function gensym(val) return '_'..(tostring(tostring(val)):gsub("[^%w]",""):gsub("(%d%w+)", + -- tostring(val) is needed because __tostring may return a non-string value + function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return tostring(syms[s]) end)) end + local function safestr(s) return type(s) == "number" and tostring(huge and snum[tostring(s)] or s) + or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026 + or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end + local function comment(s,l) return comm and (l or 0) < comm and ' --[['..tostring(s)..']]' or '' end + local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal + and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end + local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r'] + local n = name == nil and '' or name + local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n] + local safe = plain and n or '['..safestr(n)..']' + return (path or '')..(plain and path and '.' or '')..safe, safe end + local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding + local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'} + local function padnum(d) return ("%0"..tostring(maxn).."d"):format(tonumber(d)) end + table.sort(k, function(a,b) + -- sort numeric keys first: k[key] is not nil for numerical keys + return (k[a] ~= nil and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum)) + < (k[b] ~= nil and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end + local function val2str(t, name, indent, insref, path, plainindex, level) + local ttype, level, mt = type(t), (level or 0), getmetatable(t) + local spath, sname = safename(path, name) + local tag = plainindex and + ((type(name) == "number") and '' or name..space..'='..space) or + (name ~= nil and sname..space..'='..space or '') + if seen[t] then -- already seen this element + sref[#sref+1] = spath..space..'='..space..seen[t] + return tag..'nil'..comment('ref', level) end + if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself + seen[t] = insref or spath + if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end + ttype = type(t) end -- new value falls through to be serialized + if ttype == "table" then + if level >= maxl then return tag..'{}'..comment('max', level) end + seen[t] = insref or spath + if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty + local maxn, o, out = math.min(#t, maxnum or #t), {}, {} + for key = 1, maxn do o[key] = key end + if not maxnum or #o < maxnum then + local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables + for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end end + if maxnum and #o > maxnum then o[maxnum+1] = nil end + if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end + local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output) + for n, key in ipairs(o) do + local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse + if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing + or opts.keyallow and not opts.keyallow[key] + or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types + or sparse and value == nil then -- skipping nils; do nothing + elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then + if not seen[key] and not globals[key] then + sref[#sref+1] = 'placeholder' + local sname = safename(iname, gensym(key)) -- iname is table for local variables + sref[#sref] = val2str(key,sname,indent,sname,iname,true) end + sref[#sref+1] = 'placeholder' + local path = seen[t]..'['..tostring(seen[key] or globals[key] or gensym(key))..']' + sref[#sref] = path..space..'='..space..tostring(seen[value] or val2str(value,nil,indent,path)) + else + out[#out+1] = val2str(value,key,indent,insref,seen[t],plainindex,level+1) + end + end + local prefix = string.rep(indent or '', level) + local head = indent and '{\n'..prefix..indent or '{' + local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space)) + local tail = indent and "\n"..prefix..'}' or '}' + return (custom and custom(tag,head,body,tail) or tag..head..body..tail)..comment(t, level) + elseif badtype[ttype] then + seen[t] = insref or spath + return tag..globerr(t, level) + elseif ttype == 'function' then + seen[t] = insref or spath + local ok, res = pcall(string.dump, t) + local func = ok and ((opts.nocode and "function() --[[..skipped..]] end" or + "((loadstring or load)("..safestr(res)..",'@serialized'))")..comment(t, level)) + return tag..(func or globerr(t, level)) + else return tag..safestr(t) end -- handle all other types + end + local sepr = indent and "\n" or ";"..space + local body = val2str(t, name, indent) -- this call also populates sref + local tail = #sref>1 and table.concat(sref, sepr)..sepr or '' + local warn = opts.comment and #sref>1 and space.."--[[incomplete output with shared/self-references skipped]]" or '' + return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end" +end + +local function deserialize(data, opts) + local env = (opts and opts.safe == false) and G + or setmetatable({}, { + __index = function(t,k) return t end, + __call = function(t,...) error("cannot call functions") end + }) + local f, res = (loadstring or load)('return '..data, nil, nil, env) + if not f then f, res = (loadstring or load)(data, nil, nil, env) end + if not f then return f, res end + if setfenv then setfenv(f, env) end + return pcall(f) +end + +local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end +return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s, + load = deserialize, + dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end, + line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end, + block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end } diff --git a/libs/url.lua b/libs/url.lua new file mode 100644 index 0000000..2cbc7a6 --- /dev/null +++ b/libs/url.lua @@ -0,0 +1,269 @@ +--[[ +Copyright 2004-2007 Diego Nehab. +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. +]] +----------------------------------------------------------------------------- +-- URI parsing, composition and relative URL resolution +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: url.lua,v 1.38 2006/04/03 04:45:42 diego Exp $ +----------------------------------------------------------------------------- + + +-- updated for a module()-free world of 5.3 by slact + + +local string = require("string") +local base = _G +local table = require("table") + +local Url={} +Url._VERSION = "URL 1.0.2" + +function Url.escape(s) + return string.gsub(s, "([^A-Za-z0-9_])", function(c) + return string.format("%%%02x", string.byte(c)) + end) +end + +local function make_set(t) + local s = {} + for i,v in base.ipairs(t) do + s[t[i]] = 1 + end + return s +end + +local segment_set = make_set { + "-", "_", ".", "!", "~", "*", "'", "(", + ")", ":", "@", "&", "=", "+", "$", ",", +} + +local function protect_segment(s) + return string.gsub(s, "([^A-Za-z0-9_])", function (c) + if segment_set[c] then return c + else return string.format("%%%02x", string.byte(c)) end + end) +end + +function Url.unescape(s) + return string.gsub(s, "%%(%x%x)", function(hex) + return string.char(base.tonumber(hex, 16)) + end) +end + +local function absolute_path(base_path, relative_path) + if string.sub(relative_path, 1, 1) == "/" then return relative_path end + local path = string.gsub(base_path, "[^/]*$", "") + path = path .. relative_path + path = string.gsub(path, "([^/]*%./)", function (s) + if s ~= "./" then return s else return "" end + end) + path = string.gsub(path, "/%.$", "/") + local reduced + while reduced ~= path do + reduced = path + path = string.gsub(reduced, "([^/]*/%.%./)", function (s) + if s ~= "../../" then return "" else return s end + end) + end + path = string.gsub(reduced, "([^/]*/%.%.)$", function (s) + if s ~= "../.." then return "" else return s end + end) + return path +end + + +----------------------------------------------------------------------------- +-- Parses a url and returns a table with all its parts according to RFC 2396 +-- The following grammar describes the names given to the URL parts +-- ::= :///;?# +-- ::= @: +-- ::= [:] +-- :: = {/} +-- Input +-- url: uniform resource locator of request +-- default: table with default values for each field +-- Returns +-- table with the following fields, where RFC naming conventions have +-- been preserved: +-- scheme, authority, userinfo, user, password, host, port, +-- path, params, query, fragment +-- Obs: +-- the leading '/' in {/} is considered part of +----------------------------------------------------------------------------- +function Url.parse(url, default) + -- initialize default parameters + local parsed = {} + for i,v in base.pairs(default or parsed) do parsed[i] = v end + -- empty url is parsed to nil + if not url or url == "" then return nil, "invalid url" end + -- remove whitespace + -- url = string.gsub(url, "%s", "") + -- get fragment + url = string.gsub(url, "#(.*)$", function(f) + parsed.fragment = f + return "" + end) + -- get scheme + url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", + function(s) parsed.scheme = s; return "" end) + -- get authority + url = string.gsub(url, "^//([^/]*)", function(n) + parsed.authority = n + return "" + end) + -- get query stringing + url = string.gsub(url, "%?(.*)", function(q) + parsed.query = q + return "" + end) + -- get params + url = string.gsub(url, "%;(.*)", function(p) + parsed.params = p + return "" + end) + -- path is whatever was left + if url ~= "" then parsed.path = url end + local authority = parsed.authority + if not authority then return parsed end + authority = string.gsub(authority,"^([^@]*)@", + function(u) parsed.userinfo = u; return "" end) + authority = string.gsub(authority, ":([^:]*)$", + function(p) parsed.port = p; return "" end) + if authority ~= "" then parsed.host = authority end + local userinfo = parsed.userinfo + if not userinfo then return parsed end + userinfo = string.gsub(userinfo, ":([^:]*)$", + function(p) parsed.password = p; return "" end) + parsed.user = userinfo + return parsed +end + +----------------------------------------------------------------------------- +-- Rebuilds a parsed URL from its components. +-- Components are protected if any reserved or unallowed characters are found +-- Input +-- parsed: parsed URL, as returned by parse +-- Returns +-- a stringing with the corresponding URL +----------------------------------------------------------------------------- +function Url.build(parsed) + local ppath = Url.parse_path(parsed.path or "") + local url = Url.build_path(ppath) + if parsed.params then url = url .. ";" .. parsed.params end + if parsed.query then url = url .. "?" .. parsed.query end + local authority = parsed.authority + if parsed.host then + authority = parsed.host + if parsed.port then authority = authority .. ":" .. parsed.port end + local userinfo = parsed.userinfo + if parsed.user then + userinfo = parsed.user + if parsed.password then + userinfo = userinfo .. ":" .. parsed.password + end + end + if userinfo then authority = userinfo .. "@" .. authority end + end + if authority then url = "//" .. authority .. url end + if parsed.scheme then url = parsed.scheme .. ":" .. url end + if parsed.fragment then url = url .. "#" .. parsed.fragment end + -- url = string.gsub(url, "%s", "") + return url +end + +-- Builds a absolute URL from a base and a relative URL according to RFC 2396 +function Url.absolute(base_url, relative_url) + if base.type(base_url) == "table" then + base_parsed = base_url + base_url = Url.build(base_parsed) + else + base_parsed = Url.parse(base_url) + end + local relative_parsed = Url.parse(relative_url) + if not base_parsed then return relative_url + elseif not relative_parsed then return base_url + elseif relative_parsed.scheme then return relative_url + else + relative_parsed.scheme = base_parsed.scheme + if not relative_parsed.authority then + relative_parsed.authority = base_parsed.authority + if not relative_parsed.path then + relative_parsed.path = base_parsed.path + if not relative_parsed.params then + relative_parsed.params = base_parsed.params + if not relative_parsed.query then + relative_parsed.query = base_parsed.query + end + end + else + relative_parsed.path = absolute_path(base_parsed.path or "", + relative_parsed.path) + end + end + return Url.build(relative_parsed) + end +end + +-- Breaks a path into its segments, unescaping the segments +function Url.parse_path(path) + local parsed = {} + path = path or "" + --path = string.gsub(path, "%s", "") + string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) + for i = 1, #parsed do + parsed[i] = Url.unescape(parsed[i]) + end + if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end + if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end + return parsed +end + +-- Builds a path component from its segments, escaping protected characters. +function Url.build_path(parsed, unsafe) + local path = "" + local n = #parsed + if unsafe then + for i = 1, n-1 do + path = path .. parsed[i] + path = path .. "/" + end + if n > 0 then + path = path .. parsed[n] + if parsed.is_directory then path = path .. "/" end + end + else + for i = 1, n-1 do + path = path .. protect_segment(parsed[i]) + path = path .. "/" + end + if n > 0 then + path = path .. protect_segment(parsed[n]) + if parsed.is_directory then path = path .. "/" end + end + end + if parsed.is_absolute then path = "/" .. path end + return path +end + +return Url \ No newline at end of file From 3a255581de6b0ab5a1a9f3443d7e738bca66761b Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Mon, 21 Mar 2016 19:46:51 +0000 Subject: [PATCH 35/58] "Update banhammer.lua" --- plugins/banhammer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/banhammer.lua b/plugins/banhammer.lua index 5624939..3b7b879 100644 --- a/plugins/banhammer.lua +++ b/plugins/banhammer.lua @@ -238,7 +238,7 @@ local support_id = msg.from.id if matches[1]:lower() == 'kick' then if type(msg.reply_id)~="nil" and is_momod(msg) then if is_admin1(msg) then - local msgr = get_message(msg.reply_id,Kick_by_reply_admins, false) + msgr = get_message(msg.reply_id,Kick_by_reply_admins, false) else msgr = get_message(msg.reply_id,Kick_by_reply, false) end From 203a241483489a6feae34ef33af7b3cc9666828b Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Tue, 22 Mar 2016 19:31:03 +0200 Subject: [PATCH 36/58] Fix Supergroup --- plugins/supergroup.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index 15819a3..b52250a 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -459,7 +459,7 @@ local function set_public_membermod(msg, data, target) local group_public_lock = data[tostring(target)]['settings']['public'] local long_id = data[tostring(target)]['long_id'] if not long_id then - data[tostring(target)]['long_id'] = msg.to.peer_id + data[tostring(target)]['long_id'] = msg.to.peer_id save_data(_config.moderation.data, data) end if group_public_lock == 'yes' then @@ -478,14 +478,14 @@ local function unset_public_membermod(msg, data, target) local group_public_lock = data[tostring(target)]['settings']['public'] local long_id = data[tostring(target)]['long_id'] if not long_id then - data[tostring(target)]['long_id'] = msg.to.peer_id + data[tostring(target)]['long_id'] = msg.to.peer_id save_data(_config.moderation.data, data) end if group_public_lock == 'no' then return 'Group is not public' else data[tostring(target)]['settings']['public'] = 'no' - data[tostring(target)]['long_id'] = msg.to.long_id + data[tostring(target)]['long_id'] = msg.to.long_id save_data(_config.moderation.data, data) return 'SuperGroup is now: not public' end @@ -981,7 +981,7 @@ elseif get_cmd == "setadmin" then local receiver = channel_id local user_id = v.peer_id promote_admin(receiver, member_username, user_id) - + end send_large_msg(channel_id, text) return @@ -1034,6 +1034,9 @@ end --'Set supergroup photo' function local function set_supergroup_photo(msg, success, result) local data = load_data(_config.moderation.data) + if not data[tostring(msg.to.id)] then + return + end local receiver = get_receiver(msg) if success then local file = 'data/photos/channel_photo_'..msg.to.id..'.jpg' @@ -1053,7 +1056,7 @@ end --Run function local function run(msg, matches) if msg.to.type == 'chat' then - if matches[1] == 'tosuper' then + if matches[1] == 'tosuper' then if not is_admin1(msg) then return end @@ -1097,6 +1100,9 @@ local function run(msg, matches) rem_mutes(msg.to.id) end + if not data[tostring(msg.to.id)] then + return + end if matches[1] == "info" then if not is_owner(msg) then return From c383cc24e6865112043292bb0e23bd12ae50dc10 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Wed, 23 Mar 2016 15:49:41 -0300 Subject: [PATCH 37/58] Fix not text --- bot/utils.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bot/utils.lua b/bot/utils.lua index 095b945..1dae107 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -470,6 +470,9 @@ function send_large_msg_callback(cb_extra, success, result) local text_max = 4096 local destination = cb_extra.destination local text = cb_extra.text + if not text then + return + end local text_len = string.len(text) local num_msg = math.ceil(text_len / text_max) From 186d8006990212281fec53fbd72479b759d03bdb Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Wed, 30 Mar 2016 17:24:42 -0700 Subject: [PATCH 38/58] Update admin.lua --- plugins/admin.lua | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index 2be0389..5802010 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -213,8 +213,15 @@ local function run(msg,matches) del_contact("user#id"..matches[2],ok_cb,false) return "User "..matches[2].." removed from contact list" end + if matches[1] == "addcontact" and is_sudo(msg) then + phone = matches[2] + first_name = matches[3] + last_name = matches[4] + add_contact(phone, first_name, last_name, ok_cb, false) + return "User With Phone +"..matches[2].." has been added" +end if matches[1] == "dialoglist" then - get_dialog_list(get_dialog_list_callback, {target = msg.from.id}) + get_dialog_list(get_dialog_list_callback, {target = msg.from.id}) return "I've sent a group dialog list with both json and text format to your private messages" end if matches[1] == "whois" then @@ -231,7 +238,7 @@ local function run(msg,matches) redis:hset('user:'..v, 'print_name', k) banall_user(v) print(k, v.." Globally banned") - end + end end if matches[1] == 'reload' then receiver = get_receiver(msg) @@ -291,6 +298,7 @@ return { "^[#!/](contactlist)$", "^[#!/](dialoglist)$", "^[#!/](delcontact) (%d+)$", + "^[#!/](addcontact) (.*) (.*) (.*)$", "^[#/!](reload)$", "^[#/!](updateid)$", "^[#/!](addlog)$", @@ -302,4 +310,4 @@ return { } --By @imandaneshi :) --https://github.com/SEEDTEAM/TeleSeed/blob/test/plugins/admin.lua ----Modified by @Rondoozle for supergroups +---Modified by @Rondoozle for supergroups From d04b4422d45a0afb9abc42b5c54257a118c24e26 Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Wed, 30 Mar 2016 18:40:20 -0700 Subject: [PATCH 39/58] Update supergroup.lua --- plugins/supergroup.lua | 46 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index b52250a..b57853d 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -26,6 +26,7 @@ local function check_member_super(cb_extra, success, result) member = 'no', public = 'no', lock_rtl = 'no', + lock_tgservice = 'yes', lock_contacts = 'no', strict = 'no' } @@ -343,6 +344,34 @@ local function unlock_group_rtl(msg, data, target) end end +local function lock_group_tgservice(msg, data, target) + if not is_momod(msg) then + return + end + local group_tgservice_lock = data[tostring(target)]['settings']['lock_tgservice'] + if group_tgservice_lock == 'yes' then + return 'Tgservice is already locked' + else + data[tostring(target)]['settings']['lock_tgservice'] = 'yes' + save_data(_config.moderation.data, data) + return 'Tgservice has been locked' + end +end + +local function unlock_group_tgservice(msg, data, target) + if not is_momod(msg) then + return + end + local group_tgservice_lock = data[tostring(target)]['settings']['lock_tgservice'] + if group_tgservice_lock == 'no' then + return 'TgService Is Not Locked!' + else + data[tostring(target)]['settings']['lock_rtl'] = 'no' + save_data(_config.moderation.data, data) + return 'Tgservice has been unlocked' + end +end + local function lock_group_sticker(msg, data, target) if not is_momod(msg) then return @@ -514,6 +543,11 @@ function show_supergroup_settingsmod(msg, target) if not data[tostring(target)]['settings']['lock_rtl'] then data[tostring(target)]['settings']['lock_rtl'] = 'no' end +end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_tgservice'] then + data[tostring(target)]['settings']['lock_tgservice'] = 'no' + end end if data[tostring(target)]['settings'] then if not data[tostring(target)]['settings']['lock_member'] then @@ -521,7 +555,7 @@ function show_supergroup_settingsmod(msg, target) end end local settings = data[tostring(target)]['settings'] - local text = "SuperGroup settings:\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nFlood sensitivity : "..NUM_MSG_MAX.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict + local text = "SuperGroup settings:\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nFlood sensitivity : "..NUM_MSG_MAX.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock Tgservice : "..settings.lock_tgservice.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict return text end @@ -1626,6 +1660,10 @@ local function run(msg, matches) savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked rtl chars. in names") return lock_group_rtl(msg, data, target) end + if matches[2] == 'tgservice' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked Tgservice Actions") + return lock_group_tgservice(msg, data, target) + end if matches[2] == 'sticker' then savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked sticker posting") return lock_group_sticker(msg, data, target) @@ -1665,6 +1703,10 @@ local function run(msg, matches) if matches[2]:lower() == 'rtl' then savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked RTL chars. in names") return unlock_group_rtl(msg, data, target) + end + if matches[2] == 'tgservice' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked tgservice actions") + return unlock_group_tgservice(msg, data, target) end if matches[2] == 'sticker' then savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked sticker posting") @@ -1985,7 +2027,7 @@ return { "^[#!/]([Bb]ots)$", "^[#!/]([Ww]ho)$", "^[#!/]([Kk]icked)$", - "^[#!/]([Bb]lock) (.*)", + "^[#!/]([Bb]lock) (.*)", "^[#!/]([Bb]lock)", "^[#!/]([Tt]osuper)$", "^[#!/]([Ii][Dd])$", From b08ab5580013c6cb0b27ca3556dca541be825cfe Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Wed, 30 Mar 2016 20:31:52 -0700 Subject: [PATCH 40/58] Added Contact_Pro in Admin.lua --- plugins/admin.lua | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index 5802010..fe4373d 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -181,9 +181,11 @@ local function run(msg,matches) return end if matches[1] == "pm" then - send_large_msg("user#id"..matches[2],matches[3]) - return "Msg sent" + local text = "Message From "..(msg.from.username or msg.from.last_name).."\n\nMessage : "..matches[3] + send_large_msg("user#id"..matches[2],text) + return "Message has been sended" end + if matches[1] == "pmblock" then if is_admin2(matches[2]) then return "You can't block admins" @@ -220,6 +222,22 @@ local function run(msg,matches) add_contact(phone, first_name, last_name, ok_cb, false) return "User With Phone +"..matches[2].." has been added" end + if matches[1] == "sendcontact" and is_sudo(msg) then + phone = matches[2] + first_name = matches[3] + last_name = matches[4] + send_contact(get_receiver(msg), phone, first_name, last_name, ok_cb, false) +end + if matches[1] == "mycontact" and is_sudo(msg) then + if not msg.from.phone then + retrurn "I must Have Your Phone Number!" + end + phone = msg.from.phone + first_name = (msg.from.first_name or msg.from.phone) + last_name = (msg.from.last_name or msg.from.id) + send_contact(get_receiver(msg), phone, first_name, last_name, ok_cb, false) +end + if matches[1] == "dialoglist" then get_dialog_list(get_dialog_list_callback, {target = msg.from.id}) return "I've sent a group dialog list with both json and text format to your private messages" @@ -299,6 +317,8 @@ return { "^[#!/](dialoglist)$", "^[#!/](delcontact) (%d+)$", "^[#!/](addcontact) (.*) (.*) (.*)$", + "^[#!/](sendcontact) (.*) (.*) (.*)$", + "^[#!/](mycontact)$", "^[#/!](reload)$", "^[#/!](updateid)$", "^[#/!](addlog)$", From 382ceb1e587df6b3be83318601559cd80ff69b59 Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Wed, 30 Mar 2016 21:14:18 -0700 Subject: [PATCH 41/58] Added msg.service Cheks In msg_checks.lua --- plugins/msg_checks.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/msg_checks.lua b/plugins/msg_checks.lua index 5bd1054..a65cb62 100644 --- a/plugins/msg_checks.lua +++ b/plugins/msg_checks.lua @@ -22,6 +22,11 @@ if is_chat_msg(msg) or is_super_group(msg) then lock_rtl = settings.lock_rtl else lock_rtl = 'no' + end + if settings.lock_tgservice then + lock_tgservice = settings.lock_tgservice + else + lock_tgservice = 'no' end if settings.lock_link then lock_link = settings.lock_link @@ -76,7 +81,17 @@ if is_chat_msg(msg) or is_super_group(msg) then if strict == "yes" or to_chat then kick_user(msg.from.id, msg.to.id) end + end + if msg.service then + if lock_tgservice == "yes" and not is_momod(msg) then + delete_msg(msg.id, ok_cb, false) + if to_chat then + username = "@"..msg.from.username + --kick_user(msg.from.id, msg.to.id) Enable This If You Want To Use It In A Chat , Work's For Lock member and joing with link + --return "Tgservice Is Not Allowed User "..(username or msg.from.print_name).." ["..msg.from.id.."]\nStatus : User Kicked" + end end + end local is_squig_msg = msg.text:match("[\216-\219][\128-\191]") if is_squig_msg and lock_arabic == "yes" then delete_msg(msg.id, ok_cb, false) From 75fe0c268e38a7d7b66d73c1571020bbeb18bb2b Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Wed, 30 Mar 2016 21:20:12 -0700 Subject: [PATCH 42/58] Added msg.service Cheks In msg_checks.lua --- plugins/msg_checks.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/msg_checks.lua b/plugins/msg_checks.lua index a65cb62..a84b0cd 100644 --- a/plugins/msg_checks.lua +++ b/plugins/msg_checks.lua @@ -83,12 +83,10 @@ if is_chat_msg(msg) or is_super_group(msg) then end end if msg.service then - if lock_tgservice == "yes" and not is_momod(msg) then + if lock_tgservice == "yes" then delete_msg(msg.id, ok_cb, false) if to_chat then - username = "@"..msg.from.username - --kick_user(msg.from.id, msg.to.id) Enable This If You Want To Use It In A Chat , Work's For Lock member and joing with link - --return "Tgservice Is Not Allowed User "..(username or msg.from.print_name).." ["..msg.from.id.."]\nStatus : User Kicked" + return end end end From 7460dd9e45232922b7461de4db2e89cde0385d48 Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Thu, 31 Mar 2016 09:13:48 +0430 Subject: [PATCH 43/58] Added Lock Tgservice --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3902e1d..28aae72 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ * **Group administration via private messages** * **Only mods, owner and admin can add bots in groups** * **Arabic lock** +* **Lock TgService** * **Chat list** * **And more!** @@ -181,6 +182,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/](un)lock member | Y | Y | | [#!/](un)lock leave | Y | N | | [#!/](un)lock RTL | Y | Y | +| [#!/](un)lock tgservice | N | Y | | [#!/](un)lock sticker | Y| Y | | [#!/]public [yes|no] | Y | Y | | [#!/](un)lock strict | N | Y | From d880246dc2ecbcc916eef165f225252e6d7f2166 Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Thu, 31 Mar 2016 09:53:11 +0430 Subject: [PATCH 44/58] Update admin.lua --- plugins/admin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index fe4373d..8edab1c 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -183,7 +183,7 @@ local function run(msg,matches) if matches[1] == "pm" then local text = "Message From "..(msg.from.username or msg.from.last_name).."\n\nMessage : "..matches[3] send_large_msg("user#id"..matches[2],text) - return "Message has been sended" + return "Message has been sent" end if matches[1] == "pmblock" then From fcbf75f30d466fa417605dae8aa2dc0325b582f2 Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Fri, 1 Apr 2016 06:31:38 -0700 Subject: [PATCH 45/58] Fixed Types --- plugins/supergroup.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index b57853d..b6caaff 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -366,7 +366,7 @@ local function unlock_group_tgservice(msg, data, target) if group_tgservice_lock == 'no' then return 'TgService Is Not Locked!' else - data[tostring(target)]['settings']['lock_rtl'] = 'no' + data[tostring(target)]['settings']['lock_tgservice'] = 'no' save_data(_config.moderation.data, data) return 'Tgservice has been unlocked' end @@ -404,7 +404,7 @@ local function lock_group_contacts(msg, data, target) if not is_momod(msg) then return end - local group_rtl_lock = data[tostring(target)]['settings']['lock_contacts'] + local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] if group_contacts_lock == 'yes' then return 'Contact posting is already locked' else From 727db41ba25f4883e37eb8a71f5808e3c9bef42a Mon Sep 17 00:00:00 2001 From: ArashEmp Date: Mon, 4 Apr 2016 21:44:22 +0430 Subject: [PATCH 46/58] Update admin.lua --- plugins/admin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index 8edab1c..bc8a7c7 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -230,7 +230,7 @@ end end if matches[1] == "mycontact" and is_sudo(msg) then if not msg.from.phone then - retrurn "I must Have Your Phone Number!" + return "I must Have Your Phone Number!" end phone = msg.from.phone first_name = (msg.from.first_name or msg.from.phone) From 43f06144035c432f76f216dd4c8bc9c943792e1f Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Thu, 7 Apr 2016 16:57:24 -0300 Subject: [PATCH 47/58] Fix nil value in ingroup --- plugins/ingroup.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ingroup.lua b/plugins/ingroup.lua index e38ea4b..b05293b 100644 --- a/plugins/ingroup.lua +++ b/plugins/ingroup.lua @@ -942,7 +942,7 @@ local function run(msg, matches) 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 + if msg.media.type == 'photo' and data[tostring(msg.to.id)] 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 From 38e84b651c4df27076952207de2470f53b0bd3a9 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Sat, 9 Apr 2016 10:24:01 -0300 Subject: [PATCH 48/58] FIX #125 --- plugins/ingroup.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ingroup.lua b/plugins/ingroup.lua index b05293b..062bc5a 100644 --- a/plugins/ingroup.lua +++ b/plugins/ingroup.lua @@ -949,7 +949,7 @@ local function run(msg, matches) if msg.to.type == 'chat' then if is_admin1(msg) or not is_support(msg.from.id) then-- Admin only if matches[1] == 'add' and not matches[2] then - if not is_admin1(msg) or not is_support(msg.from.id) then-- Admin only + if not is_admin1(msg) and not is_support(msg.from.id) then-- Admin only savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to add group [ "..msg.to.id.." ]") return end @@ -973,7 +973,7 @@ if msg.to.type == 'chat' then return realmadd(msg) end if matches[1] == 'rem' and not matches[2] then - if not is_admin1(msg) or not is_support(msg.from.id) then-- Admin only + if not is_admin1(msg) and not is_support(msg.from.id) then-- Admin only savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to remove group [ "..msg.to.id.." ]") return end From f51863fef48e55fc31a4ef722e447836d8004bc9 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Sun, 10 Apr 2016 14:41:04 -0300 Subject: [PATCH 49/58] Fix utils (Text nil) --- bot/utils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/utils.lua b/bot/utils.lua index 1dae107..229ccc9 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -470,7 +470,7 @@ function send_large_msg_callback(cb_extra, success, result) local text_max = 4096 local destination = cb_extra.destination local text = cb_extra.text - if not text then + if not text or text ~= '' then return end local text_len = string.len(text) From dc07b7c8103d4f83a2aa9d511c93f98441cc4cec Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Sun, 10 Apr 2016 15:02:55 -0300 Subject: [PATCH 50/58] README update references --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 28aae72..8eb1a74 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,11 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]setlink | Set a new SuperGroup link _If bot is not creator_. | N | Y | | [#!/]link | Retrieves the group/SuperGroup link. | Y | Y | | [#!/]rules | Retrieves the group/SuperGroup rules. | Y | Y | -| [#!/]lock [setting](#settings) | Lock group/SuperGroup settings. | Y | Y | -| [#!/]unlock [setting](#settings) | Unlock group/SuperGroup. | Y | Y | -| [#!/]mute [mute](#mutes) | mute group message types. | Y | Y | -| [#!/]unmute [mute](#mutes) | unmute group message types. | Y | Y | -| [#!/]setflood [value](#settings) | Set [value] as flood sensitivity.| Y | Y | +| [#!/]lock [setting](#settings-settings) | Lock group/SuperGroup settings. | Y | Y | +| [#!/]unlock [setting](#settings-settings) | Unlock group/SuperGroup. | Y | Y | +| [#!/]mute [mute]#mutes-mutes) | mute group message types. | Y | Y | +| [#!/]unmute [mute](#mutes-mutes) | unmute group message types. | Y | Y | +| [#!/]setflood [value](#settings-settings) | Set [value] as flood sensitivity.| Y | Y | | [#!/]muteuser [username|id|reply] | Mute and unmute a user in chat. ***If a muted user posts a message, the message is deleted automaically only owners can mute | mods and owners can unmute*** | Y | Y | | [#!/]mutelist | Returns list of muted users in group/SuperGroup. | Y | Y | | [#!/]muteslist | Returns mutes for group/SuperGroup. | Y | Y | From 0f3d52bd94e862bf33918cf457bb5b12d459bc8f Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Sun, 10 Apr 2016 20:55:18 +0000 Subject: [PATCH 51/58] Reversed 38e84b6 and FixBug --- bot/utils.lua | 10 +++++----- plugins/all.lua | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/bot/utils.lua b/bot/utils.lua index 229ccc9..839f820 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -470,7 +470,7 @@ function send_large_msg_callback(cb_extra, success, result) local text_max = 4096 local destination = cb_extra.destination local text = cb_extra.text - if not text or text ~= '' then + if not text then return end local text_len = string.len(text) @@ -1108,9 +1108,10 @@ function muted_user_list(chat_id) local print_name = string.gsub(print_name, "‮", "") text = text..k.." - "..print_name.." ["..v.."]\n" else - text = text..k.." - [ "..v.." ]\n" + text = text..k.." - [ "..v.." ]\n" + end end - return text + return text end --End Chat Mutes @@ -1230,5 +1231,4 @@ function banall_by_reply(extra, success, result) else return end -end -end +end \ No newline at end of file diff --git a/plugins/all.lua b/plugins/all.lua index 820074d..002c819 100644 --- a/plugins/all.lua +++ b/plugins/all.lua @@ -87,6 +87,10 @@ local function get_link(target) end local function all(msg,target,receiver) + local data = load_data(_config.moderation.data) + if not data[tostring(target)] then + return + end 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 @@ -144,4 +148,4 @@ return { }, run = run } -end +end \ No newline at end of file From 3aae4a79222ffe40f496b0b10a5009af554a52bc Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Mon, 11 Apr 2016 16:26:06 +0000 Subject: [PATCH 52/58] Update banlist and fix #143 --- bot/utils.lua | 2 +- plugins/supergroup.lua | 4172 ++++++++++++++++++++-------------------- 2 files changed, 2087 insertions(+), 2087 deletions(-) diff --git a/bot/utils.lua b/bot/utils.lua index 839f820..be6abda 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -955,7 +955,7 @@ end function ban_list(chat_id) local hash = 'banned:'..chat_id local list = redis:smembers(hash) - local text = "Ban list!\n\n" + local text = "Ban list for: [ID: "..chat_id.." ]:\n\n" for k,v in pairs(list) do local user_info = redis:hgetall('user:'..v) if user_info and user_info.print_name then diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index b6caaff..701023d 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -1,2086 +1,2086 @@ ---Begin supergrpup.lua ---Check members #Add supergroup -local function check_member_super(cb_extra, success, result) - local receiver = cb_extra.receiver - local data = cb_extra.data - local msg = cb_extra.msg - if success == 0 then - send_large_msg(receiver, "Promote me to admin first!") - end - for k,v in pairs(result) do - local member_id = v.peer_id - if member_id ~= our_id then - -- SuperGroup configuration - data[tostring(msg.to.id)] = { - group_type = 'SuperGroup', - long_id = msg.to.peer_id, - moderators = {}, - set_owner = member_id , - settings = { - set_name = string.gsub(msg.to.title, '_', ' '), - lock_arabic = 'no', - lock_link = "no", - flood = 'yes', - lock_spam = 'yes', - lock_sticker = 'no', - member = 'no', - public = 'no', - lock_rtl = 'no', - lock_tgservice = 'yes', - lock_contacts = 'no', - strict = 'no' - } - } - 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) - local text = 'SuperGroup has been added!' - return reply_msg(msg.id, text, ok_cb, false) - end - end -end - ---Check Members #rem supergroup -local function check_member_superrem(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) 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) - local text = 'SuperGroup has been removed' - return reply_msg(msg.id, text, ok_cb, false) - end - end -end - ---Function to Add supergroup -local function superadd(msg) - local data = load_data(_config.moderation.data) - local receiver = get_receiver(msg) - channel_get_users(receiver, check_member_super,{receiver = receiver, data = data, msg = msg}) -end - ---Function to remove supergroup -local function superrem(msg) - local data = load_data(_config.moderation.data) - local receiver = get_receiver(msg) - channel_get_users(receiver, check_member_superrem,{receiver = receiver, data = data, msg = msg}) -end - ---Get and output admins and bots in supergroup -local function callback(cb_extra, success, result) -local i = 1 -local chat_name = string.gsub(cb_extra.msg.to.print_name, "_", " ") -local member_type = cb_extra.member_type -local text = member_type.." for "..chat_name..":\n" -for k,v in pairsByKeys(result) do -if not v.first_name then - name = " " -else - vname = v.first_name:gsub("‮", "") - name = vname:gsub("_", " ") - end - text = text.."\n"..i.." - "..name.."["..v.peer_id.."]" - i = i + 1 - end - send_large_msg(cb_extra.receiver, text) -end - ---Get and output info about supergroup -local function callback_info(cb_extra, success, result) -local title ="Info for SuperGroup: ["..result.title.."]\n\n" -local admin_num = "Admin count: "..result.admins_count.."\n" -local user_num = "User count: "..result.participants_count.."\n" -local kicked_num = "Kicked user count: "..result.kicked_count.."\n" -local channel_id = "ID: "..result.peer_id.."\n" -if result.username then - channel_username = "Username: @"..result.username -else - channel_username = "" -end -local text = title..admin_num..user_num..kicked_num..channel_id..channel_username - send_large_msg(cb_extra.receiver, text) -end - ---Get and output members of supergroup -local function callback_who(cb_extra, success, result) -local text = "Members for "..cb_extra.receiver -local i = 1 -for k,v in pairsByKeys(result) do -if not v.print_name then - name = " " -else - vname = v.print_name:gsub("‮", "") - name = vname:gsub("_", " ") -end - if v.username then - username = " @"..v.username - else - username = "" - end - text = text.."\n"..i.." - "..name.." "..username.." [ "..v.peer_id.." ]\n" - --text = text.."\n"..username - i = i + 1 -end - local file = io.open("./groups/lists/supergroups/"..cb_extra.receiver..".txt", "w") - file:write(text) - file:flush() - file:close() - send_document(cb_extra.receiver,"./groups/lists/supergroups/"..cb_extra.receiver..".txt", ok_cb, false) - post_msg(cb_extra.receiver, text, ok_cb, false) -end - ---Get and output list of kicked users for supergroup -local function callback_kicked(cb_extra, success, result) ---vardump(result) -local text = "Kicked Members for SuperGroup "..cb_extra.receiver.."\n\n" -local i = 1 -for k,v in pairsByKeys(result) do -if not v.print_name then - name = " " -else - vname = v.print_name:gsub("‮", "") - name = vname:gsub("_", " ") -end - if v.username then - name = name.." @"..v.username - end - text = text.."\n"..i.." - "..name.." [ "..v.peer_id.." ]\n" - i = i + 1 -end - local file = io.open("./groups/lists/supergroups/kicked/"..cb_extra.receiver..".txt", "w") - file:write(text) - file:flush() - file:close() - send_document(cb_extra.receiver,"./groups/lists/supergroups/kicked/"..cb_extra.receiver..".txt", ok_cb, false) - --send_large_msg(cb_extra.receiver, text) -end - ---Begin supergroup locks -local function lock_group_links(msg, data, target) - if not is_momod(msg) then - return - end - local group_link_lock = data[tostring(target)]['settings']['lock_link'] - if group_link_lock == 'yes' then - return 'Link posting is already locked' - else - data[tostring(target)]['settings']['lock_link'] = 'yes' - save_data(_config.moderation.data, data) - return 'Link posting has been locked' - end -end - -local function unlock_group_links(msg, data, target) - if not is_momod(msg) then - return - end - local group_link_lock = data[tostring(target)]['settings']['lock_link'] - if group_link_lock == 'no' then - return 'Link posting is not locked' - else - data[tostring(target)]['settings']['lock_link'] = 'no' - save_data(_config.moderation.data, data) - return 'Link posting has been unlocked' - end -end - -local function lock_group_spam(msg, data, target) - if not is_momod(msg) then - return - end - if not is_owner(msg) then - return "Owners only!" - end - local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] - if group_spam_lock == 'yes' then - return 'SuperGroup spam is already locked' - else - data[tostring(target)]['settings']['lock_spam'] = 'yes' - save_data(_config.moderation.data, data) - return 'SuperGroup spam has been locked' - end -end - -local function unlock_group_spam(msg, data, target) - if not is_momod(msg) then - return - end - local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] - if group_spam_lock == 'no' then - return 'SuperGroup spam is not locked' - else - data[tostring(target)]['settings']['lock_spam'] = 'no' - save_data(_config.moderation.data, data) - return 'SuperGroup spam has been unlocked' - end -end - -local function lock_group_flood(msg, data, target) - if not is_momod(msg) then - return - end - local group_flood_lock = data[tostring(target)]['settings']['flood'] - if group_flood_lock == 'yes' then - return 'Flood is already locked' - else - data[tostring(target)]['settings']['flood'] = 'yes' - save_data(_config.moderation.data, data) - return 'Flood has been locked' - end -end - -local function unlock_group_flood(msg, data, target) - if not is_momod(msg) then - return - end - local group_flood_lock = data[tostring(target)]['settings']['flood'] - if group_flood_lock == 'no' then - return 'Flood is not locked' - else - data[tostring(target)]['settings']['flood'] = 'no' - save_data(_config.moderation.data, data) - return 'Flood has been unlocked' - end -end - -local function lock_group_arabic(msg, data, target) - if not is_momod(msg) then - return - 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 - end - local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] - if group_arabic_lock == 'no' then - return 'Arabic/Persian is already unlocked' - else - data[tostring(target)]['settings']['lock_arabic'] = 'no' - save_data(_config.moderation.data, data) - return 'Arabic/Persian has been unlocked' - end -end - -local function lock_group_membermod(msg, data, target) - if not is_momod(msg) then - return - end - local group_member_lock = data[tostring(target)]['settings']['lock_member'] - if group_member_lock == 'yes' then - return 'SuperGroup members are already locked' - else - data[tostring(target)]['settings']['lock_member'] = 'yes' - save_data(_config.moderation.data, data) - end - return 'SuperGroup members has been locked' -end - -local function unlock_group_membermod(msg, data, target) - if not is_momod(msg) then - return - end - local group_member_lock = data[tostring(target)]['settings']['lock_member'] - if group_member_lock == 'no' then - return 'SuperGroup members are not locked' - else - data[tostring(target)]['settings']['lock_member'] = 'no' - save_data(_config.moderation.data, data) - return 'SuperGroup members has been unlocked' - end -end - -local function lock_group_rtl(msg, data, target) - if not is_momod(msg) then - return - end - local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] - if group_rtl_lock == 'yes' then - return 'RTL is already locked' - else - data[tostring(target)]['settings']['lock_rtl'] = 'yes' - save_data(_config.moderation.data, data) - return 'RTL has been locked' - end -end - -local function unlock_group_rtl(msg, data, target) - if not is_momod(msg) then - return - end - local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] - if group_rtl_lock == 'no' then - return 'RTL is already unlocked' - else - data[tostring(target)]['settings']['lock_rtl'] = 'no' - save_data(_config.moderation.data, data) - return 'RTL has been unlocked' - end -end - -local function lock_group_tgservice(msg, data, target) - if not is_momod(msg) then - return - end - local group_tgservice_lock = data[tostring(target)]['settings']['lock_tgservice'] - if group_tgservice_lock == 'yes' then - return 'Tgservice is already locked' - else - data[tostring(target)]['settings']['lock_tgservice'] = 'yes' - save_data(_config.moderation.data, data) - return 'Tgservice has been locked' - end -end - -local function unlock_group_tgservice(msg, data, target) - if not is_momod(msg) then - return - end - local group_tgservice_lock = data[tostring(target)]['settings']['lock_tgservice'] - if group_tgservice_lock == 'no' then - return 'TgService Is Not Locked!' - else - data[tostring(target)]['settings']['lock_tgservice'] = 'no' - save_data(_config.moderation.data, data) - return 'Tgservice has been unlocked' - end -end - -local function lock_group_sticker(msg, data, target) - if not is_momod(msg) then - return - end - local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] - if group_sticker_lock == 'yes' then - return 'Sticker posting is already locked' - else - data[tostring(target)]['settings']['lock_sticker'] = 'yes' - save_data(_config.moderation.data, data) - return 'Sticker posting has been locked' - end -end - -local function unlock_group_sticker(msg, data, target) - if not is_momod(msg) then - return - end - local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] - if group_sticker_lock == 'no' then - return 'Sticker posting is already unlocked' - else - data[tostring(target)]['settings']['lock_sticker'] = 'no' - save_data(_config.moderation.data, data) - return 'Sticker posting has been unlocked' - end -end - -local function lock_group_contacts(msg, data, target) - if not is_momod(msg) then - return - end - local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] - if group_contacts_lock == 'yes' then - return 'Contact posting is already locked' - else - data[tostring(target)]['settings']['lock_contacts'] = 'yes' - save_data(_config.moderation.data, data) - return 'Contact posting has been locked' - end -end - -local function unlock_group_contacts(msg, data, target) - if not is_momod(msg) then - return - end - local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] - if group_contacts_lock == 'no' then - return 'Contact posting is already unlocked' - else - data[tostring(target)]['settings']['lock_contacts'] = 'no' - save_data(_config.moderation.data, data) - return 'Contact posting has been unlocked' - end -end - -local function enable_strict_rules(msg, data, target) - if not is_momod(msg) then - return - end - local group_strict_lock = data[tostring(target)]['settings']['strict'] - if group_strict_lock == 'yes' then - return 'Settings are already strictly enforced' - else - data[tostring(target)]['settings']['strict'] = 'yes' - save_data(_config.moderation.data, data) - return 'Settings will be strictly enforced' - end -end - -local function disable_strict_rules(msg, data, target) - if not is_momod(msg) then - return - end - local group_strict_lock = data[tostring(target)]['settings']['strict'] - if group_strict_lock == 'no' then - return 'Settings are not strictly enforced' - else - data[tostring(target)]['settings']['strict'] = 'no' - save_data(_config.moderation.data, data) - return 'Settings will not be strictly enforced' - end -end ---End supergroup locks - ---'Set supergroup rules' function -local function set_rulesmod(msg, data, target) - if not is_momod(msg) then - return - end - local data_cat = 'rules' - data[tostring(target)][data_cat] = rules - save_data(_config.moderation.data, data) - return 'SuperGroup rules set' -end - ---'Get supergroup rules' function -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 group_name = data[tostring(msg.to.id)]['settings']['set_name'] - local rules = group_name..' rules:\n\n'..rules:gsub("/n", " ") - return rules -end - ---Set supergroup to public or not public function -local function set_public_membermod(msg, data, target) - if not is_momod(msg) then - return "For moderators only!" - end - local group_public_lock = data[tostring(target)]['settings']['public'] - local long_id = data[tostring(target)]['long_id'] - if not long_id then - data[tostring(target)]['long_id'] = msg.to.peer_id - save_data(_config.moderation.data, data) - end - if group_public_lock == 'yes' then - return 'Group is already public' - else - data[tostring(target)]['settings']['public'] = 'yes' - save_data(_config.moderation.data, data) - end - return 'SuperGroup is now: public' -end - -local function unset_public_membermod(msg, data, target) - if not is_momod(msg) then - return - end - local group_public_lock = data[tostring(target)]['settings']['public'] - local long_id = data[tostring(target)]['long_id'] - if not long_id then - data[tostring(target)]['long_id'] = msg.to.peer_id - save_data(_config.moderation.data, data) - end - if group_public_lock == 'no' then - return 'Group is not public' - else - data[tostring(target)]['settings']['public'] = 'no' - data[tostring(target)]['long_id'] = msg.to.long_id - save_data(_config.moderation.data, data) - return 'SuperGroup is now: not public' - end -end - ---Show supergroup settings; function -function show_supergroup_settingsmod(msg, target) - if not is_momod(msg) then - return - end - 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 - if data[tostring(target)]['settings'] then - if not data[tostring(target)]['settings']['public'] then - data[tostring(target)]['settings']['public'] = 'no' - end - end - if data[tostring(target)]['settings'] then - if not data[tostring(target)]['settings']['lock_rtl'] then - data[tostring(target)]['settings']['lock_rtl'] = 'no' - end -end - if data[tostring(target)]['settings'] then - if not data[tostring(target)]['settings']['lock_tgservice'] then - data[tostring(target)]['settings']['lock_tgservice'] = 'no' - end - end - if data[tostring(target)]['settings'] then - if not data[tostring(target)]['settings']['lock_member'] then - data[tostring(target)]['settings']['lock_member'] = 'no' - end - end - local settings = data[tostring(target)]['settings'] - local text = "SuperGroup settings:\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nFlood sensitivity : "..NUM_MSG_MAX.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock Tgservice : "..settings.lock_tgservice.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict - return text -end - -local function promote_admin(receiver, member_username, user_id) - local data = load_data(_config.moderation.data) - local group = string.gsub(receiver, 'channel#id', '') - local member_tag_username = string.gsub(member_username, '@', '(at)') - if not data[group] then - return - end - if data[group]['moderators'][tostring(user_id)] then - return send_large_msg(receiver, member_username..' is already a moderator.') - end - data[group]['moderators'][tostring(user_id)] = member_tag_username - save_data(_config.moderation.data, data) -end - -local function demote_admin(receiver, member_username, user_id) - local data = load_data(_config.moderation.data) - local group = string.gsub(receiver, 'channel#id', '') - if not data[group] then - return - end - if not data[group]['moderators'][tostring(user_id)] then - return send_large_msg(receiver, member_tag_username..' is not a moderator.') - end - data[group]['moderators'][tostring(user_id)] = nil - save_data(_config.moderation.data, data) -end - -local function promote2(receiver, member_username, user_id) - local data = load_data(_config.moderation.data) - local group = string.gsub(receiver, 'channel#id', '') - local member_tag_username = string.gsub(member_username, '@', '(at)') - if not data[group] then - return send_large_msg(receiver, 'SuperGroup is not added.') - end - if data[group]['moderators'][tostring(user_id)] then - return send_large_msg(receiver, member_username..' is already a moderator.') - end - data[group]['moderators'][tostring(user_id)] = member_tag_username - save_data(_config.moderation.data, data) - send_large_msg(receiver, member_username..' has been promoted.') -end - -local function demote2(receiver, member_username, user_id) - local data = load_data(_config.moderation.data) - local group = string.gsub(receiver, 'channel#id', '') - if not data[group] then - return send_large_msg(receiver, 'Group is not added.') - end - if not data[group]['moderators'][tostring(user_id)] then - return send_large_msg(receiver, member_tag_username..' is not a moderator.') - end - data[group]['moderators'][tostring(user_id)] = nil - save_data(_config.moderation.data, data) - send_large_msg(receiver, member_username..' has been demoted.') -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 'SuperGroup is not added.' - end - -- determine if table is empty - if next(data[tostring(msg.to.id)]['moderators']) == nil then - 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 - --- Start by reply actions -function get_message_callback(extra, success, result) - local get_cmd = extra.get_cmd - local msg = extra.msg - local data = load_data(_config.moderation.data) - local print_name = user_print_name(msg.from):gsub("‮", "") - local name_log = print_name:gsub("_", " ") - if get_cmd == "id" and not result.action then - local channel = 'channel#id'..result.to.peer_id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id for: ["..result.from.peer_id.."]") - id1 = send_large_msg(channel, result.from.peer_id) - elseif get_cmd == 'id' and result.action then - local action = result.action.type - if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then - if result.action.user then - user_id = result.action.user.peer_id - else - user_id = result.peer_id - end - local channel = 'channel#id'..result.to.peer_id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id by service msg for: ["..user_id.."]") - id1 = send_large_msg(channel, user_id) - end - elseif get_cmd == "idfrom" then - local channel = 'channel#id'..result.to.peer_id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id for msg fwd from: ["..result.fwd_from.peer_id.."]") - id2 = send_large_msg(channel, result.fwd_from.peer_id) - elseif get_cmd == 'channel_block' and not result.action then - local member_id = result.from.peer_id - local channel_id = result.to.peer_id - if member_id == msg.from.id then - return send_large_msg("channel#id"..channel_id, "Leave using kickme command") - end - if is_momod2(member_id, channel_id) and not is_admin2(msg.from.id) then - return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") - end - if is_admin2(member_id) then - return send_large_msg("channel#id"..channel_id, "You can't kick other admins") - end - --savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..user_id.."] by reply") - kick_user(member_id, channel_id) - elseif get_cmd == 'channel_block' and result.action and result.action.type == 'chat_add_user' then - local user_id = result.action.user.peer_id - local channel_id = result.to.peer_id - if member_id == msg.from.id then - return send_large_msg("channel#id"..channel_id, "Leave using kickme command") - end - if is_momod2(member_id, channel_id) and not is_admin2(msg.from.id) then - return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") - end - if is_admin2(member_id) then - return send_large_msg("channel#id"..channel_id, "You can't kick other admins") - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..user_id.."] by reply to sev. msg.") - kick_user(user_id, channel_id) - elseif get_cmd == "del" then - delete_msg(result.id, ok_cb, false) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] deleted a message by reply") - elseif get_cmd == "setadmin" then - local user_id = result.from.peer_id - local channel_id = "channel#id"..result.to.peer_id - channel_set_admin(channel_id, "user#id"..user_id, ok_cb, false) - if result.from.username then - text = "@"..result.from.username.." set as an admin" - else - text = "[ "..user_id.." ]set as an admin" - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set: ["..user_id.."] as admin by reply") - send_large_msg(channel_id, text) - elseif get_cmd == "demoteadmin" then - local user_id = result.from.peer_id - local channel_id = "channel#id"..result.to.peer_id - if is_admin2(result.from.peer_id) then - return send_large_msg(channel_id, "You can't demote global admins!") - end - channel_demote(channel_id, "user#id"..user_id, ok_cb, false) - if result.from.username then - text = "@"..result.from.username.." has been demoted from admin" - else - text = "[ "..user_id.." ] has been demoted from admin" - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted: ["..user_id.."] from admin by reply") - send_large_msg(channel_id, text) - elseif get_cmd == "setowner" then - local group_owner = data[tostring(result.to.peer_id)]['set_owner'] - if group_owner then - local channel_id = 'channel#id'..result.to.peer_id - if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then - local user = "user#id"..group_owner - channel_demote(channel_id, user, ok_cb, false) - end - local user_id = "user#id"..result.from.peer_id - channel_set_admin(channel_id, user_id, ok_cb, false) - data[tostring(result.to.peer_id)]['set_owner'] = tostring(result.from.peer_id) - save_data(_config.moderation.data, data) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set: ["..result.from.peer_id.."] as owner by reply") - if result.from.username then - text = "@"..result.from.username.." [ "..result.from.peer_id.." ] added as owner" - else - text = "[ "..result.from.peer_id.." ] added as owner" - end - send_large_msg(channel_id, text) - end - elseif get_cmd == "promote" then - local receiver = result.to.peer_id - local full_name = (result.from.first_name or '')..' '..(result.from.last_name or '') - local member_name = full_name:gsub("‮", "") - local member_username = member_name:gsub("_", " ") - if result.from.username then - member_username = '@'.. result.from.username - end - local member_id = result.from.peer_id - if result.to.peer_type == 'channel' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted mod: @"..member_username.."["..result.from.peer_id.."] by reply") - promote2("channel#id"..result.to.peer_id, member_username, member_id) - --channel_set_mod(channel_id, user, ok_cb, false) - end - elseif get_cmd == "demote" then - local full_name = (result.from.first_name or '')..' '..(result.from.last_name or '') - local member_name = full_name:gsub("‮", "") - local member_username = member_name:gsub("_", " ") - if result.from.username then - member_username = '@'.. result.from.username - end - local member_id = result.from.peer_id - --local user = "user#id"..result.peer_id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted mod: @"..member_username.."["..user_id.."] by reply") - demote2("channel#id"..result.to.peer_id, member_username, member_id) - --channel_demote(channel_id, user, ok_cb, false) - elseif get_cmd == 'mute_user' then - if result.service then - local action = result.action.type - if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then - if result.action.user then - user_id = result.action.user.peer_id - end - end - if action == 'chat_add_user_link' then - if result.from then - user_id = result.from.peer_id - end - end - else - user_id = result.from.peer_id - end - local receiver = extra.receiver - local chat_id = msg.to.id - print(user_id) - print(chat_id) - if is_muted_user(chat_id, user_id) then - unmute_user(chat_id, user_id) - send_large_msg(receiver, "["..user_id.."] removed from the muted user list") - elseif is_admin1(msg) then - mute_user(chat_id, user_id) - send_large_msg(receiver, " ["..user_id.."] added to the muted user list") - end - end -end --- End by reply actions - ---By ID actions -local function cb_user_info(extra, success, result) - local receiver = extra.receiver - local user_id = result.peer_id - local get_cmd = extra.get_cmd - local data = load_data(_config.moderation.data) - --[[if get_cmd == "setadmin" then - local user_id = "user#id"..result.peer_id - channel_set_admin(receiver, user_id, ok_cb, false) - if result.username then - text = "@"..result.username.." has been set as an admin" - else - text = "[ "..result.peer_id.." ] has been set as an admin" - end - send_large_msg(receiver, text)]] - if get_cmd == "demoteadmin" then - if is_admin2(result.peer_id) then - return send_large_msg(receiver, "You can't demote global admins!") - end - local user_id = "user#id"..result.peer_id - channel_demote(receiver, user_id, ok_cb, false) - if result.username then - text = "@"..result.username.." has been demoted from admin" - send_large_msg(receiver, text) - else - text = "[ "..result.peer_id.." ] has been demoted from admin" - send_large_msg(receiver, text) - end - elseif get_cmd == "promote" then - if result.username then - member_username = "@"..result.username - else - member_username = string.gsub(result.print_name, '_', ' ') - end - promote2(receiver, member_username, user_id) - elseif get_cmd == "demote" then - if result.username then - member_username = "@"..result.username - else - member_username = string.gsub(result.print_name, '_', ' ') - end - demote2(receiver, member_username, user_id) - end -end - --- Begin resolve username actions -local function callbackres(extra, success, result) - local member_id = result.peer_id - local member_username = "@"..result.username - local get_cmd = extra.get_cmd - if get_cmd == "res" then - local user = result.peer_id - local name = string.gsub(result.print_name, "_", " ") - local channel = 'channel#id'..extra.channelid - send_large_msg(channel, user..'\n'..name) - return user - elseif get_cmd == "id" then - local user = result.peer_id - local channel = 'channel#id'..extra.channelid - send_large_msg(channel, user) - return user - elseif get_cmd == "invite" then - local receiver = extra.channel - local user_id = "user#id"..result.peer_id - channel_invite(receiver, user_id, ok_cb, false) - --[[elseif get_cmd == "channel_block" then - local user_id = result.peer_id - local channel_id = extra.channelid - local sender = extra.sender - if member_id == sender then - return send_large_msg("channel#id"..channel_id, "Leave using kickme command") - end - if is_momod2(member_id, channel_id) and not is_admin2(sender) then - return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") - end - if is_admin2(member_id) then - return send_large_msg("channel#id"..channel_id, "You can't kick other admins") - end - kick_user(user_id, channel_id) - elseif get_cmd == "setadmin" then - local user_id = "user#id"..result.peer_id - local channel_id = extra.channel - channel_set_admin(channel_id, user_id, ok_cb, false) - if result.username then - text = "@"..result.username.." has been set as an admin" - send_large_msg(channel_id, text) - else - text = "@"..result.peer_id.." has been set as an admin" - send_large_msg(channel_id, text) - end - elseif get_cmd == "setowner" then - local receiver = extra.channel - local channel = string.gsub(receiver, 'channel#id', '') - local from_id = extra.from_id - local group_owner = data[tostring(channel)]['set_owner'] - if group_owner then - local user = "user#id"..group_owner - if not is_admin2(group_owner) and not is_support(group_owner) then - channel_demote(receiver, user, ok_cb, false) - end - local user_id = "user#id"..result.peer_id - channel_set_admin(receiver, user_id, ok_cb, false) - data[tostring(channel)]['set_owner'] = tostring(result.peer_id) - save_data(_config.moderation.data, data) - savelog(channel, name_log.." ["..from_id.."] set ["..result.peer_id.."] as owner by username") - if result.username then - text = member_username.." [ "..result.peer_id.." ] added as owner" - else - text = "[ "..result.peer_id.." ] added as owner" - end - send_large_msg(receiver, text) - end]] - elseif get_cmd == "promote" then - local receiver = extra.channel - local user_id = result.peer_id - --local user = "user#id"..result.peer_id - promote2(receiver, member_username, user_id) - --channel_set_mod(receiver, user, ok_cb, false) - elseif get_cmd == "demote" then - local receiver = extra.channel - local user_id = result.peer_id - local user = "user#id"..result.peer_id - demote2(receiver, member_username, user_id) - elseif get_cmd == "demoteadmin" then - local user_id = "user#id"..result.peer_id - local channel_id = extra.channel - if is_admin2(result.peer_id) then - return send_large_msg(channel_id, "You can't demote global admins!") - end - channel_demote(channel_id, user_id, ok_cb, false) - if result.username then - text = "@"..result.username.." has been demoted from admin" - send_large_msg(channel_id, text) - else - text = "@"..result.peer_id.." has been demoted from admin" - send_large_msg(channel_id, text) - end - local receiver = extra.channel - local user_id = result.peer_id - demote_admin(receiver, member_username, user_id) - elseif get_cmd == 'mute_user' then - local user_id = result.peer_id - local receiver = extra.receiver - local chat_id = string.gsub(receiver, 'channel#id', '') - if is_muted_user(chat_id, user_id) then - unmute_user(chat_id, user_id) - send_large_msg(receiver, " ["..user_id.."] removed from muted user list") - elseif is_owner(extra.msg) then - mute_user(chat_id, user_id) - send_large_msg(receiver, " ["..user_id.."] added to muted user list") - end - end -end ---End resolve username actions - ---Begin non-channel_invite username actions -local function in_channel_cb(cb_extra, success, result) - local get_cmd = cb_extra.get_cmd - local receiver = cb_extra.receiver - local msg = cb_extra.msg - local data = load_data(_config.moderation.data) - local print_name = user_print_name(cb_extra.msg.from):gsub("‮", "") - local name_log = print_name:gsub("_", " ") - local member = cb_extra.username - local memberid = cb_extra.user_id - if member then - text = 'No user @'..member..' in this SuperGroup.' - else - text = 'No user ['..memberid..'] in this SuperGroup.' - end -if get_cmd == "channel_block" then - for k,v in pairs(result) do - vusername = v.username - vpeer_id = tostring(v.peer_id) - if vusername == member or vpeer_id == memberid then - local user_id = v.peer_id - local channel_id = cb_extra.msg.to.id - local sender = cb_extra.msg.from.id - if user_id == sender then - return send_large_msg("channel#id"..channel_id, "Leave using kickme command") - end - if is_momod2(user_id, channel_id) and not is_admin2(sender) then - return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") - end - if is_admin2(user_id) then - return send_large_msg("channel#id"..channel_id, "You can't kick other admins") - end - if v.username then - text = "" - savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: @"..v.username.." ["..v.peer_id.."]") - else - text = "" - savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..v.peer_id.."]") - end - kick_user(user_id, channel_id) - return - end - end -elseif get_cmd == "setadmin" then - for k,v in pairs(result) do - vusername = v.username - vpeer_id = tostring(v.peer_id) - if vusername == member or vpeer_id == memberid then - local user_id = "user#id"..v.peer_id - local channel_id = "channel#id"..cb_extra.msg.to.id - channel_set_admin(channel_id, user_id, ok_cb, false) - if v.username then - text = "@"..v.username.." ["..v.peer_id.."] has been set as an admin" - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin @"..v.username.." ["..v.peer_id.."]") - else - text = "["..v.peer_id.."] has been set as an admin" - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin "..v.peer_id) - end - if v.username then - member_username = "@"..v.username - else - member_username = string.gsub(v.print_name, '_', ' ') - end - local receiver = channel_id - local user_id = v.peer_id - promote_admin(receiver, member_username, user_id) - - end - send_large_msg(channel_id, text) - return - end - elseif get_cmd == 'setowner' then - for k,v in pairs(result) do - vusername = v.username - vpeer_id = tostring(v.peer_id) - if vusername == member or vpeer_id == memberid then - local channel = string.gsub(receiver, 'channel#id', '') - local from_id = cb_extra.msg.from.id - local group_owner = data[tostring(channel)]['set_owner'] - if group_owner then - if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then - local user = "user#id"..group_owner - channel_demote(receiver, user, ok_cb, false) - end - local user_id = "user#id"..v.peer_id - channel_set_admin(receiver, user_id, ok_cb, false) - data[tostring(channel)]['set_owner'] = tostring(v.peer_id) - save_data(_config.moderation.data, data) - savelog(channel, name_log.."["..from_id.."] set ["..v.peer_id.."] as owner by username") - if result.username then - text = member_username.." ["..v.peer_id.."] added as owner" - else - text = "["..v.peer_id.."] added as owner" - end - end - elseif memberid and vusername ~= member and vpeer_id ~= memberid then - local channel = string.gsub(receiver, 'channel#id', '') - local from_id = cb_extra.msg.from.id - local group_owner = data[tostring(channel)]['set_owner'] - if group_owner then - if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then - local user = "user#id"..group_owner - channel_demote(receiver, user, ok_cb, false) - end - data[tostring(channel)]['set_owner'] = tostring(memberid) - save_data(_config.moderation.data, data) - savelog(channel, name_log.."["..from_id.."] set ["..memberid.."] as owner by username") - text = "["..memberid.."] added as owner" - end - end - end - end -send_large_msg(receiver, text) -end ---End non-channel_invite username actions - ---'Set supergroup photo' function -local function set_supergroup_photo(msg, success, result) - local data = load_data(_config.moderation.data) - if not data[tostring(msg.to.id)] then - return - end - local receiver = get_receiver(msg) - if success then - local file = 'data/photos/channel_photo_'..msg.to.id..'.jpg' - print('File downloaded to:', result) - os.rename(result, file) - print('File moved to:', file) - channel_set_photo(receiver, file, ok_cb, false) - data[tostring(msg.to.id)]['settings']['set_photo'] = file - 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 - ---Run function -local function run(msg, matches) - if msg.to.type == 'chat' then - if matches[1] == 'tosuper' then - if not is_admin1(msg) then - return - end - local receiver = get_receiver(msg) - chat_upgrade(receiver, ok_cb, false) - end - elseif msg.to.type == 'channel'then - if matches[1] == 'tosuper' then - if not is_admin1(msg) then - return - end - return "Already a SuperGroup" - end - end - if msg.to.type == 'channel' then - local support_id = msg.from.id - local receiver = get_receiver(msg) - local print_name = user_print_name(msg.from):gsub("‮", "") - local name_log = print_name:gsub("_", " ") - local data = load_data(_config.moderation.data) - if matches[1] == 'add' and not matches[2] then - if not is_admin1(msg) and not is_support(support_id) then - return - end - if is_super_group(msg) then - return reply_msg(msg.id, 'SuperGroup is already added.', ok_cb, false) - end - print("SuperGroup "..msg.to.print_name.."("..msg.to.id..") added") - savelog(msg.to.id, name_log.." ["..msg.from.id.."] added SuperGroup") - superadd(msg) - set_mutes(msg.to.id) - channel_set_admin(receiver, 'user#id'..msg.from.id, ok_cb, false) - end - - if matches[1] == 'rem' and is_admin1(msg) and not matches[2] then - if not is_super_group(msg) then - return reply_msg(msg.id, 'SuperGroup is not added.', ok_cb, false) - end - print("SuperGroup "..msg.to.print_name.."("..msg.to.id..") removed") - superrem(msg) - rem_mutes(msg.to.id) - end - - if not data[tostring(msg.to.id)] then - return - end - if matches[1] == "info" then - if not is_owner(msg) then - return - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup info") - channel_info(receiver, callback_info, {receiver = receiver, msg = msg}) - end - - if matches[1] == "admins" then - if not is_owner(msg) and not is_support(msg.from.id) then - return - end - member_type = 'Admins' - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup Admins list") - admins = channel_get_admins(receiver,callback, {receiver = receiver, msg = msg, member_type = member_type}) - end - - if matches[1] == "owner" then - local group_owner = data[tostring(msg.to.id)]['set_owner'] - if not group_owner then - return "no owner,ask admins in support groups to set owner for your SuperGroup" - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] used /owner") - return "SuperGroup owner is ["..group_owner..']' - end - - if matches[1] == "modlist" then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group modlist") - return modlist(msg) - -- channel_get_admins(receiver,callback, {receiver = receiver}) - end - - if matches[1] == "bots" and is_momod(msg) then - member_type = 'Bots' - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup bots list") - channel_get_bots(receiver, callback, {receiver = receiver, msg = msg, member_type = member_type}) - end - - if matches[1] == "who" and not matches[2] and is_momod(msg) then - local user_id = msg.from.peer_id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup users list") - channel_get_users(receiver, callback_who, {receiver = receiver}) - end - - if matches[1] == "kicked" and is_momod(msg) then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested Kicked users list") - channel_get_kicked(receiver, callback_kicked, {receiver = receiver}) - end - - if matches[1] == 'del' and is_momod(msg) then - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'del', - msg = msg - } - delete_msg(msg.id, ok_cb, false) - get_message(msg.reply_id, get_message_callback, cbreply_extra) - end - end - - if matches[1] == 'block' and is_momod(msg) then - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'channel_block', - msg = msg - } - get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif matches[1] == 'block' and string.match(matches[2], '^%d+$') then - --[[local user_id = matches[2] - local channel_id = msg.to.id - if is_momod2(user_id, channel_id) and not is_admin2(user_id) then - return send_large_msg(receiver, "You can't kick mods/owner/admins") - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: [ user#id"..user_id.." ]") - kick_user(user_id, channel_id)]] - local get_cmd = 'channel_block' - local msg = msg - local user_id = matches[2] - channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) - elseif msg.text:match("@[%a%d]") then - --[[local cbres_extra = { - channelid = msg.to.id, - get_cmd = 'channel_block', - sender = msg.from.id - } - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: @"..username) - resolve_username(username, callbackres, cbres_extra)]] - local get_cmd = 'channel_block' - local msg = msg - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) - end - end - - if matches[1] == 'id' then - if type(msg.reply_id) ~= "nil" and is_momod(msg) and not matches[2] then - local cbreply_extra = { - get_cmd = 'id', - msg = msg - } - get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif type(msg.reply_id) ~= "nil" and matches[2] == "from" and is_momod(msg) then - local cbreply_extra = { - get_cmd = 'idfrom', - msg = msg - } - get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif msg.text:match("@[%a%d]") then - local cbres_extra = { - channelid = msg.to.id, - get_cmd = 'id' - } - local username = matches[2] - local username = username:gsub("@","") - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested ID for: @"..username) - resolve_username(username, callbackres, cbres_extra) - else - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup ID") - return "SuperGroup ID for " ..string.gsub(msg.to.print_name, "_", " ").. ":\n\n"..msg.to.id - end - end - - if matches[1] == 'kickme' then - if msg.to.type == 'channel' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] left via kickme") - channel_kick("channel#id"..msg.to.id, "user#id"..msg.from.id, ok_cb, false) - end - end - - if matches[1] == 'newlink' and is_momod(msg)then - local function callback_link (extra , success, result) - local receiver = get_receiver(msg) - if success == 0 then - send_large_msg(receiver, '*Error: Failed to retrieve link* \nReason: Not creator.\n\nIf you have the link, please use /setlink to set it') - data[tostring(msg.to.id)]['settings']['set_link'] = nil - save_data(_config.moderation.data, data) - else - send_large_msg(receiver, "Created a new link") - data[tostring(msg.to.id)]['settings']['set_link'] = result - save_data(_config.moderation.data, data) - end - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to create a new SuperGroup link") - export_channel_link(receiver, callback_link, false) - end - - if matches[1] == 'setlink' and is_owner(msg) then - data[tostring(msg.to.id)]['settings']['set_link'] = 'waiting' - save_data(_config.moderation.data, data) - return 'Please send the new group link now' - end - - if msg.text then - if msg.text:match("^(https://telegram.me/joinchat/%S+)$") and data[tostring(msg.to.id)]['settings']['set_link'] == 'waiting' and is_owner(msg) then - data[tostring(msg.to.id)]['settings']['set_link'] = msg.text - save_data(_config.moderation.data, data) - return "New link set" - end - end - - if matches[1] == 'link' then - if not is_momod(msg) then - return - end - local group_link = data[tostring(msg.to.id)]['settings']['set_link'] - if not group_link then - return "Create a link using /newlink first!\n\nOr if I am not creator use /setlink to set your link" - 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] == "invite" and is_sudo(msg) then - local cbres_extra = { - channel = get_receiver(msg), - get_cmd = "invite" - } - local username = matches[2] - local username = username:gsub("@","") - savelog(msg.to.id, name_log.." ["..msg.from.id.."] invited @"..username) - resolve_username(username, callbackres, cbres_extra) - end - - if matches[1] == 'res' and is_owner(msg) then - local cbres_extra = { - channelid = msg.to.id, - get_cmd = 'res' - } - local username = matches[2] - local username = username:gsub("@","") - savelog(msg.to.id, name_log.." ["..msg.from.id.."] resolved username: @"..username) - resolve_username(username, callbackres, cbres_extra) - end - - --[[if matches[1] == 'kick' and is_momod(msg) then - local receiver = channel..matches[3] - local user = "user#id"..matches[2] - chaannel_kick(receiver, user, ok_cb, false) - end]] - - if matches[1] == 'setadmin' then - if not is_support(msg.from.id) and not is_owner(msg) then - return - end - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'setadmin', - msg = msg - } - setadmin = get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif matches[1] == 'setadmin' and string.match(matches[2], '^%d+$') then - --[[] local receiver = get_receiver(msg) - local user_id = "user#id"..matches[2] - local get_cmd = 'setadmin' - user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd})]] - local get_cmd = 'setadmin' - local msg = msg - local user_id = matches[2] - channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) - elseif matches[1] == 'setadmin' and not string.match(matches[2], '^%d+$') then - --[[local cbres_extra = { - channel = get_receiver(msg), - get_cmd = 'setadmin' - } - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin @"..username) - resolve_username(username, callbackres, cbres_extra)]] - local get_cmd = 'setadmin' - local msg = msg - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) - end - end - - if matches[1] == 'demoteadmin' then - if not is_support(msg.from.id) and not is_owner(msg) then - return - end - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'demoteadmin', - msg = msg - } - demoteadmin = get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif matches[1] == 'demoteadmin' and string.match(matches[2], '^%d+$') then - local receiver = get_receiver(msg) - local user_id = "user#id"..matches[2] - local get_cmd = 'demoteadmin' - user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) - elseif matches[1] == 'demoteadmin' and not string.match(matches[2], '^%d+$') then - local cbres_extra = { - channel = get_receiver(msg), - get_cmd = 'demoteadmin' - } - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted admin @"..username) - resolve_username(username, callbackres, cbres_extra) - end - end - - if matches[1] == 'setowner' and is_owner(msg) then - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'setowner', - msg = msg - } - setowner = get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif matches[1] == 'setowner' and string.match(matches[2], '^%d+$') then - --[[ local group_owner = data[tostring(msg.to.id)]['set_owner'] - if group_owner then - local receiver = get_receiver(msg) - local user_id = "user#id"..group_owner - if not is_admin2(group_owner) and not is_support(group_owner) then - channel_demote(receiver, user_id, ok_cb, false) - end - local user = "user#id"..matches[2] - channel_set_admin(receiver, user, ok_cb, false) - data[tostring(msg.to.id)]['set_owner'] = tostring(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]] - local get_cmd = 'setowner' - local msg = msg - local user_id = matches[2] - channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) - elseif matches[1] == 'setowner' and not string.match(matches[2], '^%d+$') then - local get_cmd = 'setowner' - local msg = msg - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) - end - end - - if matches[1] == 'promote' then - if not is_momod(msg) then - return - end - if not is_owner(msg) then - return "Only owner/admin can promote" - end - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'promote', - msg = msg - } - promote = get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif matches[1] == 'promote' and string.match(matches[2], '^%d+$') then - local receiver = get_receiver(msg) - local user_id = "user#id"..matches[2] - local get_cmd = 'promote' - savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted user#id"..matches[2]) - user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) - elseif matches[1] == 'promote' and not string.match(matches[2], '^%d+$') then - local cbres_extra = { - channel = get_receiver(msg), - get_cmd = 'promote', - } - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted @"..username) - return resolve_username(username, callbackres, cbres_extra) - end - end - - if matches[1] == 'mp' and is_sudo(msg) then - channel = get_receiver(msg) - user_id = 'user#id'..matches[2] - channel_set_mod(channel, user_id, ok_cb, false) - return "ok" - end - if matches[1] == 'md' and is_sudo(msg) then - channel = get_receiver(msg) - user_id = 'user#id'..matches[2] - channel_demote(channel, user_id, ok_cb, false) - return "ok" - end - - if matches[1] == 'demote' then - if not is_momod(msg) then - return - end - if not is_owner(msg) then - return "Only owner/support/admin can promote" - end - if type(msg.reply_id) ~= "nil" then - local cbreply_extra = { - get_cmd = 'demote', - msg = msg - } - demote = get_message(msg.reply_id, get_message_callback, cbreply_extra) - elseif matches[1] == 'demote' and string.match(matches[2], '^%d+$') then - local receiver = get_receiver(msg) - local user_id = "user#id"..matches[2] - local get_cmd = 'demote' - savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted user#id"..matches[2]) - user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) - elseif not string.match(matches[2], '^%d+$') then - local cbres_extra = { - channel = get_receiver(msg), - get_cmd = 'demote' - } - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted @"..username) - return resolve_username(username, callbackres, cbres_extra) - end - end - - if matches[1] == "setname" and is_momod(msg) then - local receiver = get_receiver(msg) - local set_name = string.gsub(matches[2], '_', '') - savelog(msg.to.id, name_log.." ["..msg.from.id.."] renamed SuperGroup to: "..matches[2]) - rename_channel(receiver, set_name, ok_cb, false) - end - - if msg.service and msg.action.type == 'chat_rename' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] renamed SuperGroup to: "..msg.to.title) - data[tostring(msg.to.id)]['settings']['set_name'] = msg.to.title - save_data(_config.moderation.data, data) - end - - if matches[1] == "setabout" and is_momod(msg) then - local receiver = get_receiver(msg) - local about_text = matches[2] - local data_cat = 'description' - local target = msg.to.id - data[tostring(target)][data_cat] = about_text - save_data(_config.moderation.data, data) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup description to: "..about_text) - channel_set_about(receiver, about_text, ok_cb, false) - return "Description has been set.\n\nSelect the chat again to see the changes." - end - - if matches[1] == "setusername" and is_admin1(msg) then - local function ok_username_cb (extra, success, result) - local receiver = extra.receiver - if success == 1 then - send_large_msg(receiver, "SuperGroup username Set.\n\nSelect the chat again to see the changes.") - elseif success == 0 then - send_large_msg(receiver, "Failed to set SuperGroup username.\nUsername may already be taken.\n\nNote: Username can use a-z, 0-9 and underscores.\nMinimum length is 5 characters.") - end - end - local username = string.gsub(matches[2], '@', '') - channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) - end - - if matches[1] == 'setrules' and is_momod(msg) then - rules = matches[2] - local target = msg.to.id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] has changed group rules to ["..matches[2].."]") - return set_rulesmod(msg, data, target) - end - - if msg.media then - if msg.media.type == 'photo' and data[tostring(msg.to.id)]['settings']['set_photo'] == 'waiting' and is_momod(msg) then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set new SuperGroup photo") - load_photo(msg.id, set_supergroup_photo, msg) - return - end - 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) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] started setting new SuperGroup photo") - return 'Please send the new group photo now' - end - - if matches[1] == 'clean' then - if not is_momod(msg) then - return - end - if not is_momod(msg) then - return "Only owner can clean" - end - if matches[2] == 'modlist' then - if next(data[tostring(msg.to.id)]['moderators']) == nil then - return 'No moderator(s) in this SuperGroup.' - end - 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") - return 'Modlist has been cleaned' - end - if matches[2] == 'rules' then - local data_cat = 'rules' - if data[tostring(msg.to.id)][data_cat] == nil then - return "Rules have not been set" - end - 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") - return 'Rules have been cleaned' - end - if matches[2] == 'about' then - local receiver = get_receiver(msg) - local about_text = ' ' - local data_cat = 'description' - if data[tostring(msg.to.id)][data_cat] == nil then - return 'About is not set' - end - 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") - channel_set_about(receiver, about_text, ok_cb, false) - return "About has been cleaned" - end - if matches[2] == 'mutelist' then - chat_id = msg.to.id - local hash = 'mute_user:'..chat_id - redis:del(hash) - return "Mutelist Cleaned" - end - if matches[2] == 'username' and is_admin1(msg) then - local function ok_username_cb (extra, success, result) - local receiver = extra.receiver - if success == 1 then - send_large_msg(receiver, "SuperGroup username cleaned.") - elseif success == 0 then - send_large_msg(receiver, "Failed to clean SuperGroup username.") - end - end - local username = "" - channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) - end - end - - if matches[1] == 'lock' and is_momod(msg) then - local target = msg.to.id - if matches[2] == 'links' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked link posting ") - return lock_group_links(msg, data, target) - end - if matches[2] == 'spam' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked spam ") - return lock_group_spam(msg, data, target) - end - if matches[2] == 'flood' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked flood ") - return lock_group_flood(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] == 'member' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked member ") - return lock_group_membermod(msg, data, target) - end - if matches[2]:lower() == 'rtl' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked rtl chars. in names") - return lock_group_rtl(msg, data, target) - end - if matches[2] == 'tgservice' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked Tgservice Actions") - return lock_group_tgservice(msg, data, target) - end - if matches[2] == 'sticker' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked sticker posting") - return lock_group_sticker(msg, data, target) - end - if matches[2] == 'contacts' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked contact posting") - return lock_group_contacts(msg, data, target) - end - if matches[2] == 'strict' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked enabled strict settings") - return enable_strict_rules(msg, data, target) - end - end - - if matches[1] == 'unlock' and is_momod(msg) then - local target = msg.to.id - if matches[2] == 'links' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked link posting") - return unlock_group_links(msg, data, target) - end - if matches[2] == 'spam' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked spam") - return unlock_group_spam(msg, data, target) - end - if matches[2] == 'flood' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked flood") - return unlock_group_flood(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] == 'member' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked member ") - return unlock_group_membermod(msg, data, target) - end - if matches[2]:lower() == 'rtl' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked RTL chars. in names") - return unlock_group_rtl(msg, data, target) - end - if matches[2] == 'tgservice' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked tgservice actions") - return unlock_group_tgservice(msg, data, target) - end - if matches[2] == 'sticker' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked sticker posting") - return unlock_group_sticker(msg, data, target) - end - if matches[2] == 'contacts' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked contact posting") - return unlock_group_contacts(msg, data, target) - end - if matches[2] == 'strict' then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked disabled strict settings") - return disable_strict_rules(msg, data, target) - end - end - - if matches[1] == 'setflood' then - if not is_momod(msg) then - return - 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 'Flood has been set to: '..matches[2] - end - if matches[1] == 'public' and is_momod(msg) 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 SuperGroup to: not public") - return unset_public_membermod(msg, data, target) - end - end - - if matches[1] == 'mute' and is_owner(msg) then - local chat_id = msg.to.id - if matches[2] == 'audio' then - local msg_type = 'Audio' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return msg_type.." has been muted" - else - return "SuperGroup mute "..msg_type.." is already on" - end - end - if matches[2] == 'photo' then - local msg_type = 'Photo' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return msg_type.." has been muted" - else - return "SuperGroup mute "..msg_type.." is already on" - end - end - if matches[2] == 'video' then - local msg_type = 'Video' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return msg_type.." has been muted" - else - return "SuperGroup mute "..msg_type.." is already on" - end - end - if matches[2] == 'gifs' then - local msg_type = 'Gifs' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return msg_type.." have been muted" - else - return "SuperGroup mute "..msg_type.." is already on" - end - end - if matches[2] == 'documents' then - local msg_type = 'Documents' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return msg_type.." have been muted" - else - return "SuperGroup mute "..msg_type.." is already on" - end - end - if matches[2] == 'text' then - local msg_type = 'Text' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return msg_type.." has been muted" - else - return "Mute "..msg_type.." is already on" - end - end - if matches[2] == 'all' then - local msg_type = 'All' - if not is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) - mute(chat_id, msg_type) - return "Mute "..msg_type.." has been enabled" - else - return "Mute "..msg_type.." is already on" - end - end - end - if matches[1] == 'unmute' and is_momod(msg) then - local chat_id = msg.to.id - if matches[2] == 'audio' then - local msg_type = 'Audio' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) - unmute(chat_id, msg_type) - return msg_type.." has been unmuted" - else - return "Mute "..msg_type.." is already off" - end - end - if matches[2] == 'photo' then - local msg_type = 'Photo' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) - unmute(chat_id, msg_type) - return msg_type.." has been unmuted" - else - return "Mute "..msg_type.." is already off" - end - end - if matches[2] == 'video' then - local msg_type = 'Video' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) - unmute(chat_id, msg_type) - return msg_type.." has been unmuted" - else - return "Mute "..msg_type.." is already off" - end - end - if matches[2] == 'gifs' then - local msg_type = 'Gifs' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) - unmute(chat_id, msg_type) - return msg_type.." have been unmuted" - else - return "Mute "..msg_type.." is already off" - end - end - if matches[2] == 'documents' then - local msg_type = 'Documents' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) - unmute(chat_id, msg_type) - return msg_type.." have been unmuted" - else - return "Mute "..msg_type.." is already off" - end - end - if matches[2] == 'text' then - local msg_type = 'Text' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute message") - unmute(chat_id, msg_type) - return msg_type.." has been unmuted" - else - return "Mute text is already off" - end - end - if matches[2] == 'all' then - local msg_type = 'All' - if is_muted(chat_id, msg_type..': yes') then - savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) - unmute(chat_id, msg_type) - return "Mute "..msg_type.." has been disabled" - else - return "Mute "..msg_type.." is already disabled" - end - end - end - - - if matches[1] == "muteuser" and is_momod(msg) then - local chat_id = msg.to.id - local hash = "mute_user"..chat_id - local user_id = "" - if type(msg.reply_id) ~= "nil" then - local receiver = get_receiver(msg) - local get_cmd = "mute_user" - muteuser = get_message(msg.reply_id, get_message_callback, {receiver = receiver, get_cmd = get_cmd, msg = msg}) - elseif matches[1] == "muteuser" and string.match(matches[2], '^%d+$') then - local user_id = matches[2] - if is_muted_user(chat_id, user_id) then - unmute_user(chat_id, user_id) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] removed ["..user_id.."] from the muted users list") - return "["..user_id.."] removed from the muted users list" - elseif is_owner(msg) then - mute_user(chat_id, user_id) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] added ["..user_id.."] to the muted users list") - return "["..user_id.."] added to the muted user list" - end - elseif matches[1] == "muteuser" and not string.match(matches[2], '^%d+$') then - local receiver = get_receiver(msg) - local get_cmd = "mute_user" - local username = matches[2] - local username = string.gsub(matches[2], '@', '') - resolve_username(username, callbackres, {receiver = receiver, get_cmd = get_cmd, msg=msg}) - end - end - - if matches[1] == "muteslist" and is_momod(msg) then - local chat_id = msg.to.id - if not has_mutes(chat_id) then - set_mutes(chat_id) - return mutes_list(chat_id) - end - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup muteslist") - return mutes_list(chat_id) - end - if matches[1] == "mutelist" and is_momod(msg) then - local chat_id = msg.to.id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup mutelist") - return muted_user_list(chat_id) - end - - if matches[1] == 'settings' and is_momod(msg) then - local target = msg.to.id - savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup settings ") - return show_supergroup_settingsmod(msg, target) - 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] == 'help' and not is_owner(msg) then - text = "Message /superhelp to @Teleseed in private for SuperGroup help" - reply_msg(msg.id, text, ok_cb, false) - elseif matches[1] == 'help' and is_owner(msg) then - local name_log = user_print_name(msg.from) - savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /superhelp") - return super_help() - end - - if matches[1] == 'peer_id' and is_admin1(msg)then - text = msg.to.peer_id - reply_msg(msg.id, text, ok_cb, false) - post_large_msg(receiver, text) - end - - if matches[1] == 'msg.to.id' and is_admin1(msg) then - text = msg.to.id - reply_msg(msg.id, text, ok_cb, false) - post_large_msg(receiver, text) - end - - --Admin Join Service Message - if msg.service then - local action = msg.action.type - if action == 'chat_add_user_link' then - if is_owner2(msg.from.id) then - local receiver = get_receiver(msg) - local user = "user#id"..msg.from.id - savelog(msg.to.id, name_log.." Admin ["..msg.from.id.."] joined the SuperGroup via link") - channel_set_admin(receiver, user, ok_cb, false) - end - if is_support(msg.from.id) and not is_owner2(msg.from.id) then - local receiver = get_receiver(msg) - local user = "user#id"..msg.from.id - savelog(msg.to.id, name_log.." Support member ["..msg.from.id.."] joined the SuperGroup") - channel_set_mod(receiver, user, ok_cb, false) - end - end - if action == 'chat_add_user' then - if is_owner2(msg.action.user.id) then - local receiver = get_receiver(msg) - local user = "user#id"..msg.action.user.id - savelog(msg.to.id, name_log.." Admin ["..msg.action.user.id.."] added to the SuperGroup by [ "..msg.from.id.." ]") - channel_set_admin(receiver, user, ok_cb, false) - end - if is_support(msg.action.user.id) and not is_owner2(msg.action.user.id) then - local receiver = get_receiver(msg) - local user = "user#id"..msg.action.user.id - savelog(msg.to.id, name_log.." Support member ["..msg.action.user.id.."] added to the SuperGroup by [ "..msg.from.id.." ]") - channel_set_mod(receiver, user, ok_cb, false) - end - end - end - if matches[1] == 'msg.to.peer_id' then - post_large_msg(receiver, msg.to.peer_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 { - patterns = { - "^[#!/]([Aa]dd)$", - "^[#!/]([Rr]em)$", - "^[#!/]([Mm]ove) (.*)$", - "^[#!/]([Ii]nfo)$", - "^[#!/]([Aa]dmins)$", - "^[#!/]([Oo]wner)$", - "^[#!/]([Mm]odlist)$", - "^[#!/]([Bb]ots)$", - "^[#!/]([Ww]ho)$", - "^[#!/]([Kk]icked)$", - "^[#!/]([Bb]lock) (.*)", - "^[#!/]([Bb]lock)", - "^[#!/]([Tt]osuper)$", - "^[#!/]([Ii][Dd])$", - "^[#!/]([Ii][Dd]) (.*)$", - "^[#!/]([Kk]ickme)$", - "^[#!/]([Kk]ick) (.*)$", - "^[#!/]([Nn]ewlink)$", - "^[#!/]([Ss]etlink)$", - "^[#!/]([Ll]ink)$", - "^[#!/]([Rr]es) (.*)$", - "^[#!/]([Ss]etadmin) (.*)$", - "^[#!/]([Ss]etadmin)", - "^[#!/]([Dd]emoteadmin) (.*)$", - "^[#!/]([Dd]emoteadmin)", - "^[#!/]([Ss]etowner) (.*)$", - "^[#!/]([Ss]etowner)$", - "^[#!/]([Pp]romote) (.*)$", - "^[#!/]([Pp]romote)", - "^[#!/]([Dd]emote) (.*)$", - "^[#!/]([Dd]emote)", - "^[#!/]([Ss]etname) (.*)$", - "^[#!/]([Ss]etabout) (.*)$", - "^[#!/]([Ss]etrules) (.*)$", - "^[#!/]([Ss]etphoto)$", - "^[#!/]([Ss]etusername) (.*)$", - "^[#!/]([Dd]el)$", - "^[#!/]([Ll]ock) (.*)$", - "^[#!/]([Uu]nlock) (.*)$", - "^[#!/]([Mm]ute) ([^%s]+)$", - "^[#!/]([Uu]nmute) ([^%s]+)$", - "^[#!/]([Mm]uteuser)$", - "^[#!/]([Mm]uteuser) (.*)$", - "^[#!/]([Pp]ublic) (.*)$", - "^[#!/]([Ss]ettings)$", - "^[#!/]([Rr]ules)$", - "^[#!/]([Ss]etflood) (%d+)$", - "^[#!/]([Cc]lean) (.*)$", - "^[#!/]([Hh]elp)$", - "^[#!/]([Mm]uteslist)$", - "^[#!/]([Mm]utelist)$", - "[#!/](mp) (.*)", - "[#!/](md) (.*)", - "^(https://telegram.me/joinchat/%S+)$", - "msg.to.peer_id", - "%[(document)%]", - "%[(photo)%]", - "%[(video)%]", - "%[(audio)%]", - "%[(contact)%]", - "^!!tgservice (.+)$", - }, - run = run, - pre_process = pre_process -} ---End supergrpup.lua ---By @Rondoozle +--Begin supergrpup.lua +--Check members #Add supergroup +local function check_member_super(cb_extra, success, result) + local receiver = cb_extra.receiver + local data = cb_extra.data + local msg = cb_extra.msg + if success == 0 then + send_large_msg(receiver, "Promote me to admin first!") + end + for k,v in pairs(result) do + local member_id = v.peer_id + if member_id ~= our_id then + -- SuperGroup configuration + data[tostring(msg.to.id)] = { + group_type = 'SuperGroup', + long_id = msg.to.peer_id, + moderators = {}, + set_owner = member_id , + settings = { + set_name = string.gsub(msg.to.title, '_', ' '), + lock_arabic = 'no', + lock_link = "no", + flood = 'yes', + lock_spam = 'yes', + lock_sticker = 'no', + member = 'no', + public = 'no', + lock_rtl = 'no', + lock_tgservice = 'yes', + lock_contacts = 'no', + strict = 'no' + } + } + 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) + local text = 'SuperGroup has been added!' + return reply_msg(msg.id, text, ok_cb, false) + end + end +end + +--Check Members #rem supergroup +local function check_member_superrem(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) 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) + local text = 'SuperGroup has been removed' + return reply_msg(msg.id, text, ok_cb, false) + end + end +end + +--Function to Add supergroup +local function superadd(msg) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + channel_get_users(receiver, check_member_super,{receiver = receiver, data = data, msg = msg}) +end + +--Function to remove supergroup +local function superrem(msg) + local data = load_data(_config.moderation.data) + local receiver = get_receiver(msg) + channel_get_users(receiver, check_member_superrem,{receiver = receiver, data = data, msg = msg}) +end + +--Get and output admins and bots in supergroup +local function callback(cb_extra, success, result) +local i = 1 +local chat_name = string.gsub(cb_extra.msg.to.print_name, "_", " ") +local member_type = cb_extra.member_type +local text = member_type.." for "..chat_name..":\n" +for k,v in pairsByKeys(result) do +if not v.first_name then + name = " " +else + vname = v.first_name:gsub("‮", "") + name = vname:gsub("_", " ") + end + text = text.."\n"..i.." - "..name.."["..v.peer_id.."]" + i = i + 1 + end + send_large_msg(cb_extra.receiver, text) +end + +--Get and output info about supergroup +local function callback_info(cb_extra, success, result) +local title ="Info for SuperGroup: ["..result.title.."]\n\n" +local admin_num = "Admin count: "..result.admins_count.."\n" +local user_num = "User count: "..result.participants_count.."\n" +local kicked_num = "Kicked user count: "..result.kicked_count.."\n" +local channel_id = "ID: "..result.peer_id.."\n" +if result.username then + channel_username = "Username: @"..result.username +else + channel_username = "" +end +local text = title..admin_num..user_num..kicked_num..channel_id..channel_username + send_large_msg(cb_extra.receiver, text) +end + +--Get and output members of supergroup +local function callback_who(cb_extra, success, result) +local text = "Members for "..cb_extra.receiver +local i = 1 +for k,v in pairsByKeys(result) do +if not v.print_name then + name = " " +else + vname = v.print_name:gsub("‮", "") + name = vname:gsub("_", " ") +end + if v.username then + username = " @"..v.username + else + username = "" + end + text = text.."\n"..i.." - "..name.." "..username.." [ "..v.peer_id.." ]\n" + --text = text.."\n"..username + i = i + 1 +end + local file = io.open("./groups/lists/supergroups/"..cb_extra.receiver..".txt", "w") + file:write(text) + file:flush() + file:close() + send_document(cb_extra.receiver,"./groups/lists/supergroups/"..cb_extra.receiver..".txt", ok_cb, false) + post_msg(cb_extra.receiver, text, ok_cb, false) +end + +--Get and output list of kicked users for supergroup +local function callback_kicked(cb_extra, success, result) +--vardump(result) +local text = "Kicked Members for SuperGroup "..cb_extra.receiver.."\n\n" +local i = 1 +for k,v in pairsByKeys(result) do +if not v.print_name then + name = " " +else + vname = v.print_name:gsub("‮", "") + name = vname:gsub("_", " ") +end + if v.username then + name = name.." @"..v.username + end + text = text.."\n"..i.." - "..name.." [ "..v.peer_id.." ]\n" + i = i + 1 +end + local file = io.open("./groups/lists/supergroups/kicked/"..cb_extra.receiver..".txt", "w") + file:write(text) + file:flush() + file:close() + send_document(cb_extra.receiver,"./groups/lists/supergroups/kicked/"..cb_extra.receiver..".txt", ok_cb, false) + --send_large_msg(cb_extra.receiver, text) +end + +--Begin supergroup locks +local function lock_group_links(msg, data, target) + if not is_momod(msg) then + return + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'yes' then + return 'Link posting is already locked' + else + data[tostring(target)]['settings']['lock_link'] = 'yes' + save_data(_config.moderation.data, data) + return 'Link posting has been locked' + end +end + +local function unlock_group_links(msg, data, target) + if not is_momod(msg) then + return + end + local group_link_lock = data[tostring(target)]['settings']['lock_link'] + if group_link_lock == 'no' then + return 'Link posting is not locked' + else + data[tostring(target)]['settings']['lock_link'] = 'no' + save_data(_config.moderation.data, data) + return 'Link posting has been unlocked' + end +end + +local function lock_group_spam(msg, data, target) + if not is_momod(msg) then + return + end + if not is_owner(msg) then + return "Owners only!" + end + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'yes' then + return 'SuperGroup spam is already locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'yes' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been locked' + end +end + +local function unlock_group_spam(msg, data, target) + if not is_momod(msg) then + return + end + local group_spam_lock = data[tostring(target)]['settings']['lock_spam'] + if group_spam_lock == 'no' then + return 'SuperGroup spam is not locked' + else + data[tostring(target)]['settings']['lock_spam'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup spam has been unlocked' + end +end + +local function lock_group_flood(msg, data, target) + if not is_momod(msg) then + return + end + local group_flood_lock = data[tostring(target)]['settings']['flood'] + if group_flood_lock == 'yes' then + return 'Flood is already locked' + else + data[tostring(target)]['settings']['flood'] = 'yes' + save_data(_config.moderation.data, data) + return 'Flood has been locked' + end +end + +local function unlock_group_flood(msg, data, target) + if not is_momod(msg) then + return + end + local group_flood_lock = data[tostring(target)]['settings']['flood'] + if group_flood_lock == 'no' then + return 'Flood is not locked' + else + data[tostring(target)]['settings']['flood'] = 'no' + save_data(_config.moderation.data, data) + return 'Flood has been unlocked' + end +end + +local function lock_group_arabic(msg, data, target) + if not is_momod(msg) then + return + 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 + end + local group_arabic_lock = data[tostring(target)]['settings']['lock_arabic'] + if group_arabic_lock == 'no' then + return 'Arabic/Persian is already unlocked' + else + data[tostring(target)]['settings']['lock_arabic'] = 'no' + save_data(_config.moderation.data, data) + return 'Arabic/Persian has been unlocked' + end +end + +local function lock_group_membermod(msg, data, target) + if not is_momod(msg) then + return + end + local group_member_lock = data[tostring(target)]['settings']['lock_member'] + if group_member_lock == 'yes' then + return 'SuperGroup members are already locked' + else + data[tostring(target)]['settings']['lock_member'] = 'yes' + save_data(_config.moderation.data, data) + end + return 'SuperGroup members has been locked' +end + +local function unlock_group_membermod(msg, data, target) + if not is_momod(msg) then + return + end + local group_member_lock = data[tostring(target)]['settings']['lock_member'] + if group_member_lock == 'no' then + return 'SuperGroup members are not locked' + else + data[tostring(target)]['settings']['lock_member'] = 'no' + save_data(_config.moderation.data, data) + return 'SuperGroup members has been unlocked' + end +end + +local function lock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'yes' then + return 'RTL is already locked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'yes' + save_data(_config.moderation.data, data) + return 'RTL has been locked' + end +end + +local function unlock_group_rtl(msg, data, target) + if not is_momod(msg) then + return + end + local group_rtl_lock = data[tostring(target)]['settings']['lock_rtl'] + if group_rtl_lock == 'no' then + return 'RTL is already unlocked' + else + data[tostring(target)]['settings']['lock_rtl'] = 'no' + save_data(_config.moderation.data, data) + return 'RTL has been unlocked' + end +end + +local function lock_group_tgservice(msg, data, target) + if not is_momod(msg) then + return + end + local group_tgservice_lock = data[tostring(target)]['settings']['lock_tgservice'] + if group_tgservice_lock == 'yes' then + return 'Tgservice is already locked' + else + data[tostring(target)]['settings']['lock_tgservice'] = 'yes' + save_data(_config.moderation.data, data) + return 'Tgservice has been locked' + end +end + +local function unlock_group_tgservice(msg, data, target) + if not is_momod(msg) then + return + end + local group_tgservice_lock = data[tostring(target)]['settings']['lock_tgservice'] + if group_tgservice_lock == 'no' then + return 'TgService Is Not Locked!' + else + data[tostring(target)]['settings']['lock_tgservice'] = 'no' + save_data(_config.moderation.data, data) + return 'Tgservice has been unlocked' + end +end + +local function lock_group_sticker(msg, data, target) + if not is_momod(msg) then + return + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'yes' then + return 'Sticker posting is already locked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'yes' + save_data(_config.moderation.data, data) + return 'Sticker posting has been locked' + end +end + +local function unlock_group_sticker(msg, data, target) + if not is_momod(msg) then + return + end + local group_sticker_lock = data[tostring(target)]['settings']['lock_sticker'] + if group_sticker_lock == 'no' then + return 'Sticker posting is already unlocked' + else + data[tostring(target)]['settings']['lock_sticker'] = 'no' + save_data(_config.moderation.data, data) + return 'Sticker posting has been unlocked' + end +end + +local function lock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'yes' then + return 'Contact posting is already locked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'yes' + save_data(_config.moderation.data, data) + return 'Contact posting has been locked' + end +end + +local function unlock_group_contacts(msg, data, target) + if not is_momod(msg) then + return + end + local group_contacts_lock = data[tostring(target)]['settings']['lock_contacts'] + if group_contacts_lock == 'no' then + return 'Contact posting is already unlocked' + else + data[tostring(target)]['settings']['lock_contacts'] = 'no' + save_data(_config.moderation.data, data) + return 'Contact posting has been unlocked' + end +end + +local function enable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_strict_lock = data[tostring(target)]['settings']['strict'] + if group_strict_lock == 'yes' then + return 'Settings are already strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'yes' + save_data(_config.moderation.data, data) + return 'Settings will be strictly enforced' + end +end + +local function disable_strict_rules(msg, data, target) + if not is_momod(msg) then + return + end + local group_strict_lock = data[tostring(target)]['settings']['strict'] + if group_strict_lock == 'no' then + return 'Settings are not strictly enforced' + else + data[tostring(target)]['settings']['strict'] = 'no' + save_data(_config.moderation.data, data) + return 'Settings will not be strictly enforced' + end +end +--End supergroup locks + +--'Set supergroup rules' function +local function set_rulesmod(msg, data, target) + if not is_momod(msg) then + return + end + local data_cat = 'rules' + data[tostring(target)][data_cat] = rules + save_data(_config.moderation.data, data) + return 'SuperGroup rules set' +end + +--'Get supergroup rules' function +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 group_name = data[tostring(msg.to.id)]['settings']['set_name'] + local rules = group_name..' rules:\n\n'..rules:gsub("/n", " ") + return rules +end + +--Set supergroup to public or not public function +local function set_public_membermod(msg, data, target) + if not is_momod(msg) then + return "For moderators only!" + end + local group_public_lock = data[tostring(target)]['settings']['public'] + local long_id = data[tostring(target)]['long_id'] + if not long_id then + data[tostring(target)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + end + if group_public_lock == 'yes' then + return 'Group is already public' + else + data[tostring(target)]['settings']['public'] = 'yes' + save_data(_config.moderation.data, data) + end + return 'SuperGroup is now: public' +end + +local function unset_public_membermod(msg, data, target) + if not is_momod(msg) then + return + end + local group_public_lock = data[tostring(target)]['settings']['public'] + local long_id = data[tostring(target)]['long_id'] + if not long_id then + data[tostring(target)]['long_id'] = msg.to.peer_id + save_data(_config.moderation.data, data) + end + if group_public_lock == 'no' then + return 'Group is not public' + else + data[tostring(target)]['settings']['public'] = 'no' + data[tostring(target)]['long_id'] = msg.to.long_id + save_data(_config.moderation.data, data) + return 'SuperGroup is now: not public' + end +end + +--Show supergroup settings; function +function show_supergroup_settingsmod(msg, target) + if not is_momod(msg) then + return + end + 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 + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['public'] then + data[tostring(target)]['settings']['public'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_rtl'] then + data[tostring(target)]['settings']['lock_rtl'] = 'no' + end +end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_tgservice'] then + data[tostring(target)]['settings']['lock_tgservice'] = 'no' + end + end + if data[tostring(target)]['settings'] then + if not data[tostring(target)]['settings']['lock_member'] then + data[tostring(target)]['settings']['lock_member'] = 'no' + end + end + local settings = data[tostring(target)]['settings'] + local text = "SuperGroup settings:\nLock links : "..settings.lock_link.."\nLock flood: "..settings.flood.."\nFlood sensitivity : "..NUM_MSG_MAX.."\nLock spam: "..settings.lock_spam.."\nLock Arabic: "..settings.lock_arabic.."\nLock Member: "..settings.lock_member.."\nLock RTL: "..settings.lock_rtl.."\nLock Tgservice : "..settings.lock_tgservice.."\nLock sticker: "..settings.lock_sticker.."\nPublic: "..settings.public.."\nStrict settings: "..settings.strict + return text +end + +local function promote_admin(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + local member_tag_username = string.gsub(member_username, '@', '(at)') + if not data[group] then + return + end + if data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_username..' is already a moderator.') + end + data[group]['moderators'][tostring(user_id)] = member_tag_username + save_data(_config.moderation.data, data) +end + +local function demote_admin(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + if not data[group] then + return + end + if not data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_tag_username..' is not a moderator.') + end + data[group]['moderators'][tostring(user_id)] = nil + save_data(_config.moderation.data, data) +end + +local function promote2(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + local member_tag_username = string.gsub(member_username, '@', '(at)') + if not data[group] then + return send_large_msg(receiver, 'SuperGroup is not added.') + end + if data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_username..' is already a moderator.') + end + data[group]['moderators'][tostring(user_id)] = member_tag_username + save_data(_config.moderation.data, data) + send_large_msg(receiver, member_username..' has been promoted.') +end + +local function demote2(receiver, member_username, user_id) + local data = load_data(_config.moderation.data) + local group = string.gsub(receiver, 'channel#id', '') + if not data[group] then + return send_large_msg(receiver, 'Group is not added.') + end + if not data[group]['moderators'][tostring(user_id)] then + return send_large_msg(receiver, member_tag_username..' is not a moderator.') + end + data[group]['moderators'][tostring(user_id)] = nil + save_data(_config.moderation.data, data) + send_large_msg(receiver, member_username..' has been demoted.') +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 'SuperGroup is not added.' + end + -- determine if table is empty + if next(data[tostring(msg.to.id)]['moderators']) == nil then + 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 + +-- Start by reply actions +function get_message_callback(extra, success, result) + local get_cmd = extra.get_cmd + local msg = extra.msg + local data = load_data(_config.moderation.data) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + if get_cmd == "id" and not result.action then + local channel = 'channel#id'..result.to.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id for: ["..result.from.peer_id.."]") + id1 = send_large_msg(channel, result.from.peer_id) + elseif get_cmd == 'id' and result.action then + local action = result.action.type + if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then + if result.action.user then + user_id = result.action.user.peer_id + else + user_id = result.peer_id + end + local channel = 'channel#id'..result.to.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id by service msg for: ["..user_id.."]") + id1 = send_large_msg(channel, user_id) + end + elseif get_cmd == "idfrom" then + local channel = 'channel#id'..result.to.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] obtained id for msg fwd from: ["..result.fwd_from.peer_id.."]") + id2 = send_large_msg(channel, result.fwd_from.peer_id) + elseif get_cmd == 'channel_block' and not result.action then + local member_id = result.from.peer_id + local channel_id = result.to.peer_id + if member_id == msg.from.id then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(member_id, channel_id) and not is_admin2(msg.from.id) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(member_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + --savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..user_id.."] by reply") + kick_user(member_id, channel_id) + elseif get_cmd == 'channel_block' and result.action and result.action.type == 'chat_add_user' then + local user_id = result.action.user.peer_id + local channel_id = result.to.peer_id + if member_id == msg.from.id then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(member_id, channel_id) and not is_admin2(msg.from.id) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(member_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..user_id.."] by reply to sev. msg.") + kick_user(user_id, channel_id) + elseif get_cmd == "del" then + delete_msg(result.id, ok_cb, false) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] deleted a message by reply") + elseif get_cmd == "setadmin" then + local user_id = result.from.peer_id + local channel_id = "channel#id"..result.to.peer_id + channel_set_admin(channel_id, "user#id"..user_id, ok_cb, false) + if result.from.username then + text = "@"..result.from.username.." set as an admin" + else + text = "[ "..user_id.." ]set as an admin" + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set: ["..user_id.."] as admin by reply") + send_large_msg(channel_id, text) + elseif get_cmd == "demoteadmin" then + local user_id = result.from.peer_id + local channel_id = "channel#id"..result.to.peer_id + if is_admin2(result.from.peer_id) then + return send_large_msg(channel_id, "You can't demote global admins!") + end + channel_demote(channel_id, "user#id"..user_id, ok_cb, false) + if result.from.username then + text = "@"..result.from.username.." has been demoted from admin" + else + text = "[ "..user_id.." ] has been demoted from admin" + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted: ["..user_id.."] from admin by reply") + send_large_msg(channel_id, text) + elseif get_cmd == "setowner" then + local group_owner = data[tostring(result.to.peer_id)]['set_owner'] + if group_owner then + local channel_id = 'channel#id'..result.to.peer_id + if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then + local user = "user#id"..group_owner + channel_demote(channel_id, user, ok_cb, false) + end + local user_id = "user#id"..result.from.peer_id + channel_set_admin(channel_id, user_id, ok_cb, false) + data[tostring(result.to.peer_id)]['set_owner'] = tostring(result.from.peer_id) + save_data(_config.moderation.data, data) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set: ["..result.from.peer_id.."] as owner by reply") + if result.from.username then + text = "@"..result.from.username.." [ "..result.from.peer_id.." ] added as owner" + else + text = "[ "..result.from.peer_id.." ] added as owner" + end + send_large_msg(channel_id, text) + end + elseif get_cmd == "promote" then + local receiver = result.to.peer_id + local full_name = (result.from.first_name or '')..' '..(result.from.last_name or '') + local member_name = full_name:gsub("‮", "") + local member_username = member_name:gsub("_", " ") + if result.from.username then + member_username = '@'.. result.from.username + end + local member_id = result.from.peer_id + if result.to.peer_type == 'channel' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted mod: @"..member_username.."["..result.from.peer_id.."] by reply") + promote2("channel#id"..result.to.peer_id, member_username, member_id) + --channel_set_mod(channel_id, user, ok_cb, false) + end + elseif get_cmd == "demote" then + local full_name = (result.from.first_name or '')..' '..(result.from.last_name or '') + local member_name = full_name:gsub("‮", "") + local member_username = member_name:gsub("_", " ") + if result.from.username then + member_username = '@'.. result.from.username + end + local member_id = result.from.peer_id + --local user = "user#id"..result.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted mod: @"..member_username.."["..user_id.."] by reply") + demote2("channel#id"..result.to.peer_id, member_username, member_id) + --channel_demote(channel_id, user, ok_cb, false) + elseif get_cmd == 'mute_user' then + if result.service then + local action = result.action.type + if action == 'chat_add_user' or action == 'chat_del_user' or action == 'chat_rename' or action == 'chat_change_photo' then + if result.action.user then + user_id = result.action.user.peer_id + end + end + if action == 'chat_add_user_link' then + if result.from then + user_id = result.from.peer_id + end + end + else + user_id = result.from.peer_id + end + local receiver = extra.receiver + local chat_id = msg.to.id + print(user_id) + print(chat_id) + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + send_large_msg(receiver, "["..user_id.."] removed from the muted user list") + elseif is_admin1(msg) then + mute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] added to the muted user list") + end + end +end +-- End by reply actions + +--By ID actions +local function cb_user_info(extra, success, result) + local receiver = extra.receiver + local user_id = result.peer_id + local get_cmd = extra.get_cmd + local data = load_data(_config.moderation.data) + --[[if get_cmd == "setadmin" then + local user_id = "user#id"..result.peer_id + channel_set_admin(receiver, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been set as an admin" + else + text = "[ "..result.peer_id.." ] has been set as an admin" + end + send_large_msg(receiver, text)]] + if get_cmd == "demoteadmin" then + if is_admin2(result.peer_id) then + return send_large_msg(receiver, "You can't demote global admins!") + end + local user_id = "user#id"..result.peer_id + channel_demote(receiver, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been demoted from admin" + send_large_msg(receiver, text) + else + text = "[ "..result.peer_id.." ] has been demoted from admin" + send_large_msg(receiver, text) + end + elseif get_cmd == "promote" then + if result.username then + member_username = "@"..result.username + else + member_username = string.gsub(result.print_name, '_', ' ') + end + promote2(receiver, member_username, user_id) + elseif get_cmd == "demote" then + if result.username then + member_username = "@"..result.username + else + member_username = string.gsub(result.print_name, '_', ' ') + end + demote2(receiver, member_username, user_id) + end +end + +-- Begin resolve username actions +local function callbackres(extra, success, result) + local member_id = result.peer_id + local member_username = "@"..result.username + local get_cmd = extra.get_cmd + if get_cmd == "res" then + local user = result.peer_id + local name = string.gsub(result.print_name, "_", " ") + local channel = 'channel#id'..extra.channelid + send_large_msg(channel, user..'\n'..name) + return user + elseif get_cmd == "id" then + local user = result.peer_id + local channel = 'channel#id'..extra.channelid + send_large_msg(channel, user) + return user + elseif get_cmd == "invite" then + local receiver = extra.channel + local user_id = "user#id"..result.peer_id + channel_invite(receiver, user_id, ok_cb, false) + --[[elseif get_cmd == "channel_block" then + local user_id = result.peer_id + local channel_id = extra.channelid + local sender = extra.sender + if member_id == sender then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(member_id, channel_id) and not is_admin2(sender) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(member_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + kick_user(user_id, channel_id) + elseif get_cmd == "setadmin" then + local user_id = "user#id"..result.peer_id + local channel_id = extra.channel + channel_set_admin(channel_id, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been set as an admin" + send_large_msg(channel_id, text) + else + text = "@"..result.peer_id.." has been set as an admin" + send_large_msg(channel_id, text) + end + elseif get_cmd == "setowner" then + local receiver = extra.channel + local channel = string.gsub(receiver, 'channel#id', '') + local from_id = extra.from_id + local group_owner = data[tostring(channel)]['set_owner'] + if group_owner then + local user = "user#id"..group_owner + if not is_admin2(group_owner) and not is_support(group_owner) then + channel_demote(receiver, user, ok_cb, false) + end + local user_id = "user#id"..result.peer_id + channel_set_admin(receiver, user_id, ok_cb, false) + data[tostring(channel)]['set_owner'] = tostring(result.peer_id) + save_data(_config.moderation.data, data) + savelog(channel, name_log.." ["..from_id.."] set ["..result.peer_id.."] as owner by username") + if result.username then + text = member_username.." [ "..result.peer_id.." ] added as owner" + else + text = "[ "..result.peer_id.." ] added as owner" + end + send_large_msg(receiver, text) + end]] + elseif get_cmd == "promote" then + local receiver = extra.channel + local user_id = result.peer_id + --local user = "user#id"..result.peer_id + promote2(receiver, member_username, user_id) + --channel_set_mod(receiver, user, ok_cb, false) + elseif get_cmd == "demote" then + local receiver = extra.channel + local user_id = result.peer_id + local user = "user#id"..result.peer_id + demote2(receiver, member_username, user_id) + elseif get_cmd == "demoteadmin" then + local user_id = "user#id"..result.peer_id + local channel_id = extra.channel + if is_admin2(result.peer_id) then + return send_large_msg(channel_id, "You can't demote global admins!") + end + channel_demote(channel_id, user_id, ok_cb, false) + if result.username then + text = "@"..result.username.." has been demoted from admin" + send_large_msg(channel_id, text) + else + text = "@"..result.peer_id.." has been demoted from admin" + send_large_msg(channel_id, text) + end + local receiver = extra.channel + local user_id = result.peer_id + demote_admin(receiver, member_username, user_id) + elseif get_cmd == 'mute_user' then + local user_id = result.peer_id + local receiver = extra.receiver + local chat_id = string.gsub(receiver, 'channel#id', '') + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] removed from muted user list") + elseif is_owner(extra.msg) then + mute_user(chat_id, user_id) + send_large_msg(receiver, " ["..user_id.."] added to muted user list") + end + end +end +--End resolve username actions + +--Begin non-channel_invite username actions +local function in_channel_cb(cb_extra, success, result) + local get_cmd = cb_extra.get_cmd + local receiver = cb_extra.receiver + local msg = cb_extra.msg + local data = load_data(_config.moderation.data) + local print_name = user_print_name(cb_extra.msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + local member = cb_extra.username + local memberid = cb_extra.user_id + if member then + text = 'No user @'..member..' in this SuperGroup.' + else + text = 'No user ['..memberid..'] in this SuperGroup.' + end +if get_cmd == "channel_block" then + for k,v in pairs(result) do + vusername = v.username + vpeer_id = tostring(v.peer_id) + if vusername == member or vpeer_id == memberid then + local user_id = v.peer_id + local channel_id = cb_extra.msg.to.id + local sender = cb_extra.msg.from.id + if user_id == sender then + return send_large_msg("channel#id"..channel_id, "Leave using kickme command") + end + if is_momod2(user_id, channel_id) and not is_admin2(sender) then + return send_large_msg("channel#id"..channel_id, "You can't kick mods/owner/admins") + end + if is_admin2(user_id) then + return send_large_msg("channel#id"..channel_id, "You can't kick other admins") + end + if v.username then + text = "" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: @"..v.username.." ["..v.peer_id.."]") + else + text = "" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: ["..v.peer_id.."]") + end + kick_user(user_id, channel_id) + return + end + end +elseif get_cmd == "setadmin" then + for k,v in pairs(result) do + vusername = v.username + vpeer_id = tostring(v.peer_id) + if vusername == member or vpeer_id == memberid then + local user_id = "user#id"..v.peer_id + local channel_id = "channel#id"..cb_extra.msg.to.id + channel_set_admin(channel_id, user_id, ok_cb, false) + if v.username then + text = "@"..v.username.." ["..v.peer_id.."] has been set as an admin" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin @"..v.username.." ["..v.peer_id.."]") + else + text = "["..v.peer_id.."] has been set as an admin" + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin "..v.peer_id) + end + if v.username then + member_username = "@"..v.username + else + member_username = string.gsub(v.print_name, '_', ' ') + end + local receiver = channel_id + local user_id = v.peer_id + promote_admin(receiver, member_username, user_id) + + end + send_large_msg(channel_id, text) + return + end + elseif get_cmd == 'setowner' then + for k,v in pairs(result) do + vusername = v.username + vpeer_id = tostring(v.peer_id) + if vusername == member or vpeer_id == memberid then + local channel = string.gsub(receiver, 'channel#id', '') + local from_id = cb_extra.msg.from.id + local group_owner = data[tostring(channel)]['set_owner'] + if group_owner then + if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then + local user = "user#id"..group_owner + channel_demote(receiver, user, ok_cb, false) + end + local user_id = "user#id"..v.peer_id + channel_set_admin(receiver, user_id, ok_cb, false) + data[tostring(channel)]['set_owner'] = tostring(v.peer_id) + save_data(_config.moderation.data, data) + savelog(channel, name_log.."["..from_id.."] set ["..v.peer_id.."] as owner by username") + if result.username then + text = member_username.." ["..v.peer_id.."] added as owner" + else + text = "["..v.peer_id.."] added as owner" + end + end + elseif memberid and vusername ~= member and vpeer_id ~= memberid then + local channel = string.gsub(receiver, 'channel#id', '') + local from_id = cb_extra.msg.from.id + local group_owner = data[tostring(channel)]['set_owner'] + if group_owner then + if not is_admin2(tonumber(group_owner)) and not is_support(tonumber(group_owner)) then + local user = "user#id"..group_owner + channel_demote(receiver, user, ok_cb, false) + end + data[tostring(channel)]['set_owner'] = tostring(memberid) + save_data(_config.moderation.data, data) + savelog(channel, name_log.."["..from_id.."] set ["..memberid.."] as owner by username") + text = "["..memberid.."] added as owner" + end + end + end + end +send_large_msg(receiver, text) +end +--End non-channel_invite username actions + +--'Set supergroup photo' function +local function set_supergroup_photo(msg, success, result) + local data = load_data(_config.moderation.data) + if not data[tostring(msg.to.id)] then + return + end + local receiver = get_receiver(msg) + if success then + local file = 'data/photos/channel_photo_'..msg.to.id..'.jpg' + print('File downloaded to:', result) + os.rename(result, file) + print('File moved to:', file) + channel_set_photo(receiver, file, ok_cb, false) + data[tostring(msg.to.id)]['settings']['set_photo'] = file + 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 + +--Run function +local function run(msg, matches) + if msg.to.type == 'chat' then + if matches[1] == 'tosuper' then + if not is_admin1(msg) then + return + end + local receiver = get_receiver(msg) + chat_upgrade(receiver, ok_cb, false) + end + elseif msg.to.type == 'channel'then + if matches[1] == 'tosuper' then + if not is_admin1(msg) then + return + end + return "Already a SuperGroup" + end + end + if msg.to.type == 'channel' then + local support_id = msg.from.id + local receiver = get_receiver(msg) + local print_name = user_print_name(msg.from):gsub("‮", "") + local name_log = print_name:gsub("_", " ") + local data = load_data(_config.moderation.data) + if matches[1] == 'add' and not matches[2] then + if not is_admin1(msg) and not is_support(support_id) then + return + end + if is_super_group(msg) then + return reply_msg(msg.id, 'SuperGroup is already added.', ok_cb, false) + end + print("SuperGroup "..msg.to.print_name.."("..msg.to.id..") added") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added SuperGroup") + superadd(msg) + set_mutes(msg.to.id) + channel_set_admin(receiver, 'user#id'..msg.from.id, ok_cb, false) + end + + if matches[1] == 'rem' and is_admin1(msg) and not matches[2] then + if not is_super_group(msg) then + return reply_msg(msg.id, 'SuperGroup is not added.', ok_cb, false) + end + print("SuperGroup "..msg.to.print_name.."("..msg.to.id..") removed") + superrem(msg) + rem_mutes(msg.to.id) + end + + if not data[tostring(msg.to.id)] then + return + end + if matches[1] == "info" then + if not is_owner(msg) then + return + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup info") + channel_info(receiver, callback_info, {receiver = receiver, msg = msg}) + end + + if matches[1] == "admins" then + if not is_owner(msg) and not is_support(msg.from.id) then + return + end + member_type = 'Admins' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup Admins list") + admins = channel_get_admins(receiver,callback, {receiver = receiver, msg = msg, member_type = member_type}) + end + + if matches[1] == "owner" then + local group_owner = data[tostring(msg.to.id)]['set_owner'] + if not group_owner then + return "no owner,ask admins in support groups to set owner for your SuperGroup" + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] used /owner") + return "SuperGroup owner is ["..group_owner..']' + end + + if matches[1] == "modlist" then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested group modlist") + return modlist(msg) + -- channel_get_admins(receiver,callback, {receiver = receiver}) + end + + if matches[1] == "bots" and is_momod(msg) then + member_type = 'Bots' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup bots list") + channel_get_bots(receiver, callback, {receiver = receiver, msg = msg, member_type = member_type}) + end + + if matches[1] == "who" and not matches[2] and is_momod(msg) then + local user_id = msg.from.peer_id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup users list") + channel_get_users(receiver, callback_who, {receiver = receiver}) + end + + if matches[1] == "kicked" and is_momod(msg) then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested Kicked users list") + channel_get_kicked(receiver, callback_kicked, {receiver = receiver}) + end + + if matches[1] == 'del' and is_momod(msg) then + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'del', + msg = msg + } + delete_msg(msg.id, ok_cb, false) + get_message(msg.reply_id, get_message_callback, cbreply_extra) + end + end + + if matches[1] == 'block' and is_momod(msg) then + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'channel_block', + msg = msg + } + get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'block' and matches[2] and string.match(matches[2], '^%d+$') then + --[[local user_id = matches[2] + local channel_id = msg.to.id + if is_momod2(user_id, channel_id) and not is_admin2(user_id) then + return send_large_msg(receiver, "You can't kick mods/owner/admins") + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: [ user#id"..user_id.." ]") + kick_user(user_id, channel_id)]] + local get_cmd = 'channel_block' + local msg = msg + local user_id = matches[2] + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) + elseif matches[1] == "block" and matches[2] and not string.match(matches[2], '^%d+$') then + --[[local cbres_extra = { + channelid = msg.to.id, + get_cmd = 'channel_block', + sender = msg.from.id + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked: @"..username) + resolve_username(username, callbackres, cbres_extra)]] + local get_cmd = 'channel_block' + local msg = msg + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) + end + end + + if matches[1] == 'id' then + if type(msg.reply_id) ~= "nil" and is_momod(msg) and not matches[2] then + local cbreply_extra = { + get_cmd = 'id', + msg = msg + } + get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif type(msg.reply_id) ~= "nil" and matches[2] == "from" and is_momod(msg) then + local cbreply_extra = { + get_cmd = 'idfrom', + msg = msg + } + get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif msg.text:match("@[%a%d]") then + local cbres_extra = { + channelid = msg.to.id, + get_cmd = 'id' + } + local username = matches[2] + local username = username:gsub("@","") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested ID for: @"..username) + resolve_username(username, callbackres, cbres_extra) + else + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup ID") + return "SuperGroup ID for " ..string.gsub(msg.to.print_name, "_", " ").. ":\n\n"..msg.to.id + end + end + + if matches[1] == 'kickme' then + if msg.to.type == 'channel' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] left via kickme") + channel_kick("channel#id"..msg.to.id, "user#id"..msg.from.id, ok_cb, false) + end + end + + if matches[1] == 'newlink' and is_momod(msg)then + local function callback_link (extra , success, result) + local receiver = get_receiver(msg) + if success == 0 then + send_large_msg(receiver, '*Error: Failed to retrieve link* \nReason: Not creator.\n\nIf you have the link, please use /setlink to set it') + data[tostring(msg.to.id)]['settings']['set_link'] = nil + save_data(_config.moderation.data, data) + else + send_large_msg(receiver, "Created a new link") + data[tostring(msg.to.id)]['settings']['set_link'] = result + save_data(_config.moderation.data, data) + end + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] attempted to create a new SuperGroup link") + export_channel_link(receiver, callback_link, false) + end + + if matches[1] == 'setlink' and is_owner(msg) then + data[tostring(msg.to.id)]['settings']['set_link'] = 'waiting' + save_data(_config.moderation.data, data) + return 'Please send the new group link now' + end + + if msg.text then + if msg.text:match("^(https://telegram.me/joinchat/%S+)$") and data[tostring(msg.to.id)]['settings']['set_link'] == 'waiting' and is_owner(msg) then + data[tostring(msg.to.id)]['settings']['set_link'] = msg.text + save_data(_config.moderation.data, data) + return "New link set" + end + end + + if matches[1] == 'link' then + if not is_momod(msg) then + return + end + local group_link = data[tostring(msg.to.id)]['settings']['set_link'] + if not group_link then + return "Create a link using /newlink first!\n\nOr if I am not creator use /setlink to set your link" + 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] == "invite" and is_sudo(msg) then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = "invite" + } + local username = matches[2] + local username = username:gsub("@","") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] invited @"..username) + resolve_username(username, callbackres, cbres_extra) + end + + if matches[1] == 'res' and is_owner(msg) then + local cbres_extra = { + channelid = msg.to.id, + get_cmd = 'res' + } + local username = matches[2] + local username = username:gsub("@","") + savelog(msg.to.id, name_log.." ["..msg.from.id.."] resolved username: @"..username) + resolve_username(username, callbackres, cbres_extra) + end + + --[[if matches[1] == 'kick' and is_momod(msg) then + local receiver = channel..matches[3] + local user = "user#id"..matches[2] + chaannel_kick(receiver, user, ok_cb, false) + end]] + + if matches[1] == 'setadmin' then + if not is_support(msg.from.id) and not is_owner(msg) then + return + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'setadmin', + msg = msg + } + setadmin = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'setadmin' and matches[2] and string.match(matches[2], '^%d+$') then + --[[] local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'setadmin' + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd})]] + local get_cmd = 'setadmin' + local msg = msg + local user_id = matches[2] + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) + elseif matches[1] == 'setadmin' and matches[2] and not string.match(matches[2], '^%d+$') then + --[[local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'setadmin' + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set admin @"..username) + resolve_username(username, callbackres, cbres_extra)]] + local get_cmd = 'setadmin' + local msg = msg + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) + end + end + + if matches[1] == 'demoteadmin' then + if not is_support(msg.from.id) and not is_owner(msg) then + return + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'demoteadmin', + msg = msg + } + demoteadmin = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'demoteadmin' and matches[2] and string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'demoteadmin' + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) + elseif matches[1] == 'demoteadmin' and matches[2] and not string.match(matches[2], '^%d+$') then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'demoteadmin' + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted admin @"..username) + resolve_username(username, callbackres, cbres_extra) + end + end + + if matches[1] == 'setowner' and is_owner(msg) then + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'setowner', + msg = msg + } + setowner = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'setowner' and matches[2] and string.match(matches[2], '^%d+$') then + --[[ local group_owner = data[tostring(msg.to.id)]['set_owner'] + if group_owner then + local receiver = get_receiver(msg) + local user_id = "user#id"..group_owner + if not is_admin2(group_owner) and not is_support(group_owner) then + channel_demote(receiver, user_id, ok_cb, false) + end + local user = "user#id"..matches[2] + channel_set_admin(receiver, user, ok_cb, false) + data[tostring(msg.to.id)]['set_owner'] = tostring(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]] + local get_cmd = 'setowner' + local msg = msg + local user_id = matches[2] + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, user_id=user_id}) + elseif matches[1] == 'setowner' and matches[2] and not string.match(matches[2], '^%d+$') then + local get_cmd = 'setowner' + local msg = msg + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + channel_get_users (receiver, in_channel_cb, {get_cmd=get_cmd, receiver=receiver, msg=msg, username=username}) + end + end + + if matches[1] == 'promote' then + if not is_momod(msg) then + return + end + if not is_owner(msg) then + return "Only owner/admin can promote" + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'promote', + msg = msg + } + promote = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'promote' and matches[2] and string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'promote' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted user#id"..matches[2]) + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) + elseif matches[1] == 'promote' and matches[2] and not string.match(matches[2], '^%d+$') then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'promote', + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] promoted @"..username) + return resolve_username(username, callbackres, cbres_extra) + end + end + + if matches[1] == 'mp' and is_sudo(msg) then + channel = get_receiver(msg) + user_id = 'user#id'..matches[2] + channel_set_mod(channel, user_id, ok_cb, false) + return "ok" + end + if matches[1] == 'md' and is_sudo(msg) then + channel = get_receiver(msg) + user_id = 'user#id'..matches[2] + channel_demote(channel, user_id, ok_cb, false) + return "ok" + end + + if matches[1] == 'demote' then + if not is_momod(msg) then + return + end + if not is_owner(msg) then + return "Only owner/support/admin can promote" + end + if type(msg.reply_id) ~= "nil" then + local cbreply_extra = { + get_cmd = 'demote', + msg = msg + } + demote = get_message(msg.reply_id, get_message_callback, cbreply_extra) + elseif matches[1] == 'demote' and matches[2] and string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local user_id = "user#id"..matches[2] + local get_cmd = 'demote' + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted user#id"..matches[2]) + user_info(user_id, cb_user_info, {receiver = receiver, get_cmd = get_cmd}) + elseif matches[1] == 'demote' and matches[2] and not string.match(matches[2], '^%d+$') then + local cbres_extra = { + channel = get_receiver(msg), + get_cmd = 'demote' + } + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] demoted @"..username) + return resolve_username(username, callbackres, cbres_extra) + end + end + + if matches[1] == "setname" and is_momod(msg) then + local receiver = get_receiver(msg) + local set_name = string.gsub(matches[2], '_', '') + savelog(msg.to.id, name_log.." ["..msg.from.id.."] renamed SuperGroup to: "..matches[2]) + rename_channel(receiver, set_name, ok_cb, false) + end + + if msg.service and msg.action.type == 'chat_rename' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] renamed SuperGroup to: "..msg.to.title) + data[tostring(msg.to.id)]['settings']['set_name'] = msg.to.title + save_data(_config.moderation.data, data) + end + + if matches[1] == "setabout" and is_momod(msg) then + local receiver = get_receiver(msg) + local about_text = matches[2] + local data_cat = 'description' + local target = msg.to.id + data[tostring(target)][data_cat] = about_text + save_data(_config.moderation.data, data) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup description to: "..about_text) + channel_set_about(receiver, about_text, ok_cb, false) + return "Description has been set.\n\nSelect the chat again to see the changes." + end + + if matches[1] == "setusername" and is_admin1(msg) then + local function ok_username_cb (extra, success, result) + local receiver = extra.receiver + if success == 1 then + send_large_msg(receiver, "SuperGroup username Set.\n\nSelect the chat again to see the changes.") + elseif success == 0 then + send_large_msg(receiver, "Failed to set SuperGroup username.\nUsername may already be taken.\n\nNote: Username can use a-z, 0-9 and underscores.\nMinimum length is 5 characters.") + end + end + local username = string.gsub(matches[2], '@', '') + channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) + end + + if matches[1] == 'setrules' and is_momod(msg) then + rules = matches[2] + local target = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] has changed group rules to ["..matches[2].."]") + return set_rulesmod(msg, data, target) + end + + if msg.media then + if msg.media.type == 'photo' and data[tostring(msg.to.id)]['settings']['set_photo'] == 'waiting' and is_momod(msg) then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set new SuperGroup photo") + load_photo(msg.id, set_supergroup_photo, msg) + return + end + 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) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] started setting new SuperGroup photo") + return 'Please send the new group photo now' + end + + if matches[1] == 'clean' then + if not is_momod(msg) then + return + end + if not is_momod(msg) then + return "Only owner can clean" + end + if matches[2] == 'modlist' then + if next(data[tostring(msg.to.id)]['moderators']) == nil then + return 'No moderator(s) in this SuperGroup.' + end + 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") + return 'Modlist has been cleaned' + end + if matches[2] == 'rules' then + local data_cat = 'rules' + if data[tostring(msg.to.id)][data_cat] == nil then + return "Rules have not been set" + end + 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") + return 'Rules have been cleaned' + end + if matches[2] == 'about' then + local receiver = get_receiver(msg) + local about_text = ' ' + local data_cat = 'description' + if data[tostring(msg.to.id)][data_cat] == nil then + return 'About is not set' + end + 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") + channel_set_about(receiver, about_text, ok_cb, false) + return "About has been cleaned" + end + if matches[2] == 'mutelist' then + chat_id = msg.to.id + local hash = 'mute_user:'..chat_id + redis:del(hash) + return "Mutelist Cleaned" + end + if matches[2] == 'username' and is_admin1(msg) then + local function ok_username_cb (extra, success, result) + local receiver = extra.receiver + if success == 1 then + send_large_msg(receiver, "SuperGroup username cleaned.") + elseif success == 0 then + send_large_msg(receiver, "Failed to clean SuperGroup username.") + end + end + local username = "" + channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) + end + end + + if matches[1] == 'lock' and is_momod(msg) then + local target = msg.to.id + if matches[2] == 'links' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked link posting ") + return lock_group_links(msg, data, target) + end + if matches[2] == 'spam' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked spam ") + return lock_group_spam(msg, data, target) + end + if matches[2] == 'flood' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked flood ") + return lock_group_flood(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] == 'member' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked member ") + return lock_group_membermod(msg, data, target) + end + if matches[2]:lower() == 'rtl' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked rtl chars. in names") + return lock_group_rtl(msg, data, target) + end + if matches[2] == 'tgservice' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked Tgservice Actions") + return lock_group_tgservice(msg, data, target) + end + if matches[2] == 'sticker' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked sticker posting") + return lock_group_sticker(msg, data, target) + end + if matches[2] == 'contacts' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked contact posting") + return lock_group_contacts(msg, data, target) + end + if matches[2] == 'strict' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked enabled strict settings") + return enable_strict_rules(msg, data, target) + end + end + + if matches[1] == 'unlock' and is_momod(msg) then + local target = msg.to.id + if matches[2] == 'links' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked link posting") + return unlock_group_links(msg, data, target) + end + if matches[2] == 'spam' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked spam") + return unlock_group_spam(msg, data, target) + end + if matches[2] == 'flood' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked flood") + return unlock_group_flood(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] == 'member' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked member ") + return unlock_group_membermod(msg, data, target) + end + if matches[2]:lower() == 'rtl' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked RTL chars. in names") + return unlock_group_rtl(msg, data, target) + end + if matches[2] == 'tgservice' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked tgservice actions") + return unlock_group_tgservice(msg, data, target) + end + if matches[2] == 'sticker' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked sticker posting") + return unlock_group_sticker(msg, data, target) + end + if matches[2] == 'contacts' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] unlocked contact posting") + return unlock_group_contacts(msg, data, target) + end + if matches[2] == 'strict' then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] locked disabled strict settings") + return disable_strict_rules(msg, data, target) + end + end + + if matches[1] == 'setflood' then + if not is_momod(msg) then + return + 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 'Flood has been set to: '..matches[2] + end + if matches[1] == 'public' and is_momod(msg) 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 SuperGroup to: not public") + return unset_public_membermod(msg, data, target) + end + end + + if matches[1] == 'mute' and is_owner(msg) then + local chat_id = msg.to.id + if matches[2] == 'audio' then + local msg_type = 'Audio' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'photo' then + local msg_type = 'Photo' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'video' then + local msg_type = 'Video' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'gifs' then + local msg_type = 'Gifs' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." have been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'documents' then + local msg_type = 'Documents' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." have been muted" + else + return "SuperGroup mute "..msg_type.." is already on" + end + end + if matches[2] == 'text' then + local msg_type = 'Text' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return msg_type.." has been muted" + else + return "Mute "..msg_type.." is already on" + end + end + if matches[2] == 'all' then + local msg_type = 'All' + if not is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: mute "..msg_type) + mute(chat_id, msg_type) + return "Mute "..msg_type.." has been enabled" + else + return "Mute "..msg_type.." is already on" + end + end + end + if matches[1] == 'unmute' and is_momod(msg) then + local chat_id = msg.to.id + if matches[2] == 'audio' then + local msg_type = 'Audio' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'photo' then + local msg_type = 'Photo' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'video' then + local msg_type = 'Video' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'gifs' then + local msg_type = 'Gifs' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." have been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'documents' then + local msg_type = 'Documents' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return msg_type.." have been unmuted" + else + return "Mute "..msg_type.." is already off" + end + end + if matches[2] == 'text' then + local msg_type = 'Text' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute message") + unmute(chat_id, msg_type) + return msg_type.." has been unmuted" + else + return "Mute text is already off" + end + end + if matches[2] == 'all' then + local msg_type = 'All' + if is_muted(chat_id, msg_type..': yes') then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] set SuperGroup to: unmute "..msg_type) + unmute(chat_id, msg_type) + return "Mute "..msg_type.." has been disabled" + else + return "Mute "..msg_type.." is already disabled" + end + end + end + + + if matches[1] == "muteuser" and is_momod(msg) then + local chat_id = msg.to.id + local hash = "mute_user"..chat_id + local user_id = "" + if type(msg.reply_id) ~= "nil" then + local receiver = get_receiver(msg) + local get_cmd = "mute_user" + muteuser = get_message(msg.reply_id, get_message_callback, {receiver = receiver, get_cmd = get_cmd, msg = msg}) + elseif matches[1] == "muteuser" and matches[2] and string.match(matches[2], '^%d+$') then + local user_id = matches[2] + if is_muted_user(chat_id, user_id) then + unmute_user(chat_id, user_id) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] removed ["..user_id.."] from the muted users list") + return "["..user_id.."] removed from the muted users list" + elseif is_owner(msg) then + mute_user(chat_id, user_id) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] added ["..user_id.."] to the muted users list") + return "["..user_id.."] added to the muted user list" + end + elseif matches[1] == "muteuser" and matches[2] and not string.match(matches[2], '^%d+$') then + local receiver = get_receiver(msg) + local get_cmd = "mute_user" + local username = matches[2] + local username = string.gsub(matches[2], '@', '') + resolve_username(username, callbackres, {receiver = receiver, get_cmd = get_cmd, msg=msg}) + end + end + + if matches[1] == "muteslist" and is_momod(msg) then + local chat_id = msg.to.id + if not has_mutes(chat_id) then + set_mutes(chat_id) + return mutes_list(chat_id) + end + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup muteslist") + return mutes_list(chat_id) + end + if matches[1] == "mutelist" and is_momod(msg) then + local chat_id = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup mutelist") + return muted_user_list(chat_id) + end + + if matches[1] == 'settings' and is_momod(msg) then + local target = msg.to.id + savelog(msg.to.id, name_log.." ["..msg.from.id.."] requested SuperGroup settings ") + return show_supergroup_settingsmod(msg, target) + 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] == 'help' and not is_owner(msg) then + text = "Message /superhelp to @Teleseed in private for SuperGroup help" + reply_msg(msg.id, text, ok_cb, false) + elseif matches[1] == 'help' and is_owner(msg) then + local name_log = user_print_name(msg.from) + savelog(msg.to.id, name_log.." ["..msg.from.id.."] Used /superhelp") + return super_help() + end + + if matches[1] == 'peer_id' and is_admin1(msg)then + text = msg.to.peer_id + reply_msg(msg.id, text, ok_cb, false) + post_large_msg(receiver, text) + end + + if matches[1] == 'msg.to.id' and is_admin1(msg) then + text = msg.to.id + reply_msg(msg.id, text, ok_cb, false) + post_large_msg(receiver, text) + end + + --Admin Join Service Message + if msg.service then + local action = msg.action.type + if action == 'chat_add_user_link' then + if is_owner2(msg.from.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.from.id + savelog(msg.to.id, name_log.." Admin ["..msg.from.id.."] joined the SuperGroup via link") + channel_set_admin(receiver, user, ok_cb, false) + end + if is_support(msg.from.id) and not is_owner2(msg.from.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.from.id + savelog(msg.to.id, name_log.." Support member ["..msg.from.id.."] joined the SuperGroup") + channel_set_mod(receiver, user, ok_cb, false) + end + end + if action == 'chat_add_user' then + if is_owner2(msg.action.user.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.action.user.id + savelog(msg.to.id, name_log.." Admin ["..msg.action.user.id.."] added to the SuperGroup by [ "..msg.from.id.." ]") + channel_set_admin(receiver, user, ok_cb, false) + end + if is_support(msg.action.user.id) and not is_owner2(msg.action.user.id) then + local receiver = get_receiver(msg) + local user = "user#id"..msg.action.user.id + savelog(msg.to.id, name_log.." Support member ["..msg.action.user.id.."] added to the SuperGroup by [ "..msg.from.id.." ]") + channel_set_mod(receiver, user, ok_cb, false) + end + end + end + if matches[1] == 'msg.to.peer_id' then + post_large_msg(receiver, msg.to.peer_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 { + patterns = { + "^[#!/]([Aa]dd)$", + "^[#!/]([Rr]em)$", + "^[#!/]([Mm]ove) (.*)$", + "^[#!/]([Ii]nfo)$", + "^[#!/]([Aa]dmins)$", + "^[#!/]([Oo]wner)$", + "^[#!/]([Mm]odlist)$", + "^[#!/]([Bb]ots)$", + "^[#!/]([Ww]ho)$", + "^[#!/]([Kk]icked)$", + "^[#!/]([Bb]lock) (.*)", + "^[#!/]([Bb]lock)", + "^[#!/]([Tt]osuper)$", + "^[#!/]([Ii][Dd])$", + "^[#!/]([Ii][Dd]) (.*)$", + "^[#!/]([Kk]ickme)$", + "^[#!/]([Kk]ick) (.*)$", + "^[#!/]([Nn]ewlink)$", + "^[#!/]([Ss]etlink)$", + "^[#!/]([Ll]ink)$", + "^[#!/]([Rr]es) (.*)$", + "^[#!/]([Ss]etadmin) (.*)$", + "^[#!/]([Ss]etadmin)", + "^[#!/]([Dd]emoteadmin) (.*)$", + "^[#!/]([Dd]emoteadmin)", + "^[#!/]([Ss]etowner) (.*)$", + "^[#!/]([Ss]etowner)$", + "^[#!/]([Pp]romote) (.*)$", + "^[#!/]([Pp]romote)", + "^[#!/]([Dd]emote) (.*)$", + "^[#!/]([Dd]emote)", + "^[#!/]([Ss]etname) (.*)$", + "^[#!/]([Ss]etabout) (.*)$", + "^[#!/]([Ss]etrules) (.*)$", + "^[#!/]([Ss]etphoto)$", + "^[#!/]([Ss]etusername) (.*)$", + "^[#!/]([Dd]el)$", + "^[#!/]([Ll]ock) (.*)$", + "^[#!/]([Uu]nlock) (.*)$", + "^[#!/]([Mm]ute) ([^%s]+)$", + "^[#!/]([Uu]nmute) ([^%s]+)$", + "^[#!/]([Mm]uteuser)$", + "^[#!/]([Mm]uteuser) (.*)$", + "^[#!/]([Pp]ublic) (.*)$", + "^[#!/]([Ss]ettings)$", + "^[#!/]([Rr]ules)$", + "^[#!/]([Ss]etflood) (%d+)$", + "^[#!/]([Cc]lean) (.*)$", + "^[#!/]([Hh]elp)$", + "^[#!/]([Mm]uteslist)$", + "^[#!/]([Mm]utelist)$", + "[#!/](mp) (.*)", + "[#!/](md) (.*)", + "^(https://telegram.me/joinchat/%S+)$", + "msg.to.peer_id", + "%[(document)%]", + "%[(photo)%]", + "%[(video)%]", + "%[(audio)%]", + "%[(contact)%]", + "^!!tgservice (.+)$", + }, + run = run, + pre_process = pre_process +} +--End supergrpup.lua +--By @Rondoozle From 64b46f66313f4e097486a6137c369b374ae6ef81 Mon Sep 17 00:00:00 2001 From: ArashEmpix Date: Thu, 14 Apr 2016 04:47:26 -0700 Subject: [PATCH 53/58] Added Missing Patterns --- plugins/admin.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/admin.lua b/plugins/admin.lua index bc8a7c7..9b61481 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -315,6 +315,7 @@ return { "^[#!/](setbotphoto)$", "^[#!/](contactlist)$", "^[#!/](dialoglist)$", + "^[#/!](sync_gbans)$", "^[#!/](delcontact) (%d+)$", "^[#!/](addcontact) (.*) (.*) (.*)$", "^[#!/](sendcontact) (.*) (.*) (.*)$", From 9b5a091b20bba2eee787e40e6978f70e48d3b672 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Thu, 14 Apr 2016 11:33:36 -0300 Subject: [PATCH 54/58] Update gitignore and fix bug --- .gitignore | 2 ++ bot/utils.lua | 81 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 6fd0a37..1c81078 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ luac.out *.x86_64 *.hex +#Data +data/* diff --git a/bot/utils.lua b/bot/utils.lua index be6abda..827df43 100644 --- a/bot/utils.lua +++ b/bot/utils.lua @@ -13,6 +13,7 @@ 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 @@ -128,7 +129,7 @@ function download_to_file(url, file_name) file_name = file_name or get_http_file_name(url, headers) - local file_path = "/tmp/"..file_name + local file_path = "data/tmp/"..file_name print("Saved to: "..file_path) file = io.open(file_path, "w+") @@ -470,7 +471,7 @@ function send_large_msg_callback(cb_extra, success, result) local text_max = 4096 local destination = cb_extra.destination local text = cb_extra.text - if not text then + if not text or type(text) == 'boolean' then return end local text_len = string.len(text) @@ -966,7 +967,7 @@ function ban_list(chat_id) text = text..k.." - "..v.."\n" end end - return text + return text end -- Returns globally ban list @@ -1108,34 +1109,42 @@ function muted_user_list(chat_id) local print_name = string.gsub(print_name, "‮", "") text = text..k.." - "..print_name.." ["..v.."]\n" else - text = text..k.." - [ "..v.." ]\n" - end + text = text..k.." - [ "..v.." ]\n" + end end - return text + return text end --End Chat Mutes -- /id by reply function get_message_callback_id(extra, success, result) - if result.to.type == 'chat' then - local chat = 'chat#id'..result.to.peer_id - send_large_msg(chat, result.from.peer_id) - else - return - end + if type(result) == 'boolean' then + print('Old message :(') + return false + end + if result.to.type == 'chat' then + local chat = 'chat#id'..result.to.peer_id + send_large_msg(chat, result.from.peer_id) + else + return + end end -- kick by reply for mods and owner function Kick_by_reply(extra, success, result) + if type(result) == 'boolean' then + print('Old message :(') + return false + end if result.to.type == 'chat' or result.to.type == 'channel' then local chat = 'chat#id'..result.to.peer_id - if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot return - end - if is_momod2(result.from.peer_id, result.to.peer_id) then -- Ignore mods,owner,admin + end + if is_momod2(result.from.peer_id, result.to.peer_id) then -- Ignore mods,owner,admin return "you can't kick mods,owner and admins" - end + end chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) channel_kick(channel, 'user#id'..result.from.peer_id, ok_cb, false) else @@ -1145,15 +1154,19 @@ end -- Kick by reply for admins function Kick_by_reply_admins(extra, success, result) + if type(result) == 'boolean' then + print('Old message :(') + return false + end if result.to.type == 'chat' or result.to.type == 'channel' then local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot return - end + end if is_admin2(result.from.peer_id) then -- Ignore admins return - end + end chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) channel_kick(channel, 'user#id'..result.from.peer_id, ok_cb, false) else @@ -1163,6 +1176,10 @@ end --Ban by reply for admins function ban_by_reply(extra, success, result) + if type(result) == 'boolean' then + print('Old message :(') + return false + end if result.to.type == 'chat' or result.to.type == 'channel' then local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id @@ -1181,15 +1198,19 @@ end -- Ban by reply for admins function ban_by_reply_admins(extra, success, result) + if type(result) == 'boolean' then + print('Old message :(') + return false + end if result.to.peer_type == 'chat' or result.to.peer_type == 'channel' then local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot return end - if is_admin2(result.from.peer_id) then -- Ignore admins + if is_admin2(result.from.peer_id) then -- Ignore admins return - end + end ban_user(result.from.peer_id, result.to.peer_id) send_large_msg(chat, "User "..result.from.peer_id.." Banned") send_large_msg(channel, "User "..result.from.peer_id.." Banned") @@ -1200,6 +1221,10 @@ end -- Unban by reply function unban_by_reply(extra, success, result) + if type(result) == 'boolean' then + print('Old message :(') + return false + end if result.to.type == 'chat' or result.to.type == 'channel' then local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id @@ -1207,7 +1232,7 @@ function unban_by_reply(extra, success, result) return end send_large_msg(chat, "User "..result.from.peer_id.." Unbanned") - -- Save on redis + -- Save on redis local hash = 'banned:'..result.to.peer_id redis:srem(hash, result.from.peer_id) else @@ -1215,15 +1240,19 @@ function unban_by_reply(extra, success, result) end end function banall_by_reply(extra, success, result) + if type(result) == 'boolean' then + print('Old message :(') + return false + end if result.to.type == 'chat' or result.to.type == 'channel' then local chat = 'chat#id'..result.to.peer_id local channel = 'channel#id'..result.to.peer_id - if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot + if tonumber(result.from.peer_id) == tonumber(our_id) then -- Ignore bot return - end - if is_admin2(result.from.peer_id) then -- Ignore admins + end + if is_admin2(result.from.peer_id) then -- Ignore admins return - end + end local name = user_print_name(result.from) banall_user(result.from.peer_id) chat_del_user(chat, 'user#id'..result.from.peer_id, ok_cb, false) @@ -1231,4 +1260,4 @@ function banall_by_reply(extra, success, result) else return end -end \ No newline at end of file +end From 312d37d4743bc8b642649762b7f2e9f8cc057939 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Thu, 14 Apr 2016 11:44:20 -0300 Subject: [PATCH 55/58] fix gitignore --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1c81078..2a1a554 100644 --- a/.gitignore +++ b/.gitignore @@ -39,5 +39,7 @@ luac.out *.x86_64 *.hex -#Data -data/* +#TeleSeed Data +data/*.* +data/photos/*.* +data/tmp/*.* From 43431d1643e938dc861e469b6c55efe34d80f342 Mon Sep 17 00:00:00 2001 From: Tiago Danin Date: Thu, 14 Apr 2016 12:03:40 -0300 Subject: [PATCH 56/58] Added tmp folder --- .gitignore | 3 +++ data/tmp/.gitkeep | 0 2 files changed, 3 insertions(+) create mode 100644 data/tmp/.gitkeep diff --git a/.gitignore b/.gitignore index 2a1a554..6a5c68d 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ luac.out data/*.* data/photos/*.* data/tmp/*.* +!data/tmp/.gitkeep +!data/photos/.gitkeep +!data/.gitkeep diff --git a/data/tmp/.gitkeep b/data/tmp/.gitkeep new file mode 100644 index 0000000..e69de29 From bd6403b2a6d03c6d4c9b88d9c3c508d168368644 Mon Sep 17 00:00:00 2001 From: Garemyah Johnson Date: Fri, 15 Apr 2016 22:32:39 +0100 Subject: [PATCH 57/58] "Add clean bots and update README.md" --- README.md | 18 +++++++++--------- plugins/banhammer.lua | 1 - plugins/supergroup.lua | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8eb1a74..4d5637b 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,14 @@ TeleSeed has several commands that are only usable at certain ranks. -## General Commands {#general_commands} +## General Commands | Command | Description | |:--------|:------------| | [#!/]id | Returns group/SuperGroup ID or user id in pm. | | [#!/]teleseed | Returns bot information. | -## Private Message Commands {#privmsg_commands} +## Private Message Commands | Command | Description | |:--------|:------------| | [#!/]help | Returns help text. | @@ -46,7 +46,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]join [GroupID] | Join a public chat by id | -## Moderator commands {#moderator_commands} +## Moderator commands | Command | Description | Groups? | SuperGroups? | |:--------|:------------|:--------|:-------------| @@ -90,12 +90,12 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]stats | Returns simple message statistics in a .txt document. | Y | Y | | [#!/]statslist | Returns simple message statistics in a message. | Y | Y | | [#!/]banlist | Returns group/SuperGroup banlist. | Y | Y | -| [#!/]clean [rules|about|modlist|mutelist] | Clears rules, about, modlist, or mutelist | Y | Y | +| [#!/]clean [rules|about|modlisthtml>|bots|mutelist] | Clears rules, about, modlist, bots, or mutelist | Y | Y | | [#!/]del | Deletes a message by reply. | N | Y | | [#!/]res [username] | Returns users name and id by username. | Y | Y | | [#!/]log | Returns group logs.***In SuperGroups:*** Search for kick reasons using [#RTL|#spam|#lockmember] | Y | Y | -## Owner commands {#moderator_commands} +## Owner commands | Command | Description | groups/SuperGroups? | In private? | |:--------|:------------|:----------------------|:-------------| @@ -160,7 +160,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]mp | (Mod Promote) Set user as a mod of supergroup. **TESTING** | N | Y | N | | [#!/]md | (Mod demote) Removes user from mod of supergroup. **TESTING**| N | Y | N | -## Sudo Commands {#sudo_commands} +## Sudo Commands | Command | Groups? | SuperGroups? | Realms? | |:--------|:--------|:-------------|---------| @@ -169,7 +169,7 @@ TeleSeed has several commands that are only usable at certain ranks. | [#!/]sync_gbans | Sync your GBans with official @TeleSeed | Y | Y | Y | -## Settings {#settings} +## Settings | Command | Groups? | SuperGroups? | |:--------|:--------|:-------------| @@ -193,7 +193,7 @@ TeleSeed has several commands that are only usable at certain ranks. /public [yes|no]: Set group/SuperGroup visibility in pm `!chats` or `!chatlist` commands. -### Mutes {#mutes} +### Mutes | Command | |:--------| @@ -208,7 +208,7 @@ TeleSeed has several commands that are only usable at certain ranks. **SuperGroups: A "muted" message type is auto-deleted if posted ** -### Ranks {#ranks} +### Ranks | Rank | Description | |:------|:------------| diff --git a/plugins/banhammer.lua b/plugins/banhammer.lua index 3b7b879..9cce924 100644 --- a/plugins/banhammer.lua +++ b/plugins/banhammer.lua @@ -254,7 +254,6 @@ if matches[1]:lower() == 'kick' then end local user_id = matches[2] local chat_id = msg.to.id - print("sexy") local print_name = user_print_name(msg.from):gsub("‮", "") local name = print_name:gsub("_", "") savelog(msg.to.id, name.." ["..msg.from.id.."] kicked user ".. matches[2]) diff --git a/plugins/supergroup.lua b/plugins/supergroup.lua index 701023d..eddff50 100644 --- a/plugins/supergroup.lua +++ b/plugins/supergroup.lua @@ -102,6 +102,16 @@ else send_large_msg(cb_extra.receiver, text) end +local function callback_clean_bots (extra, success, result) + local msg = extra.msg + local receiver = 'channel#id'..msg.to.id + local channel_id = msg.to.id + for k,v in pairs(result) do + local bot_id = v.peer_id + kick_user(bot_id,channel_id) + end +end + --Get and output info about supergroup local function callback_info(cb_extra, success, result) local title ="Info for SuperGroup: ["..result.title.."]\n\n" @@ -1632,6 +1642,10 @@ local function run(msg, matches) local username = "" channel_set_username(receiver, username, ok_username_cb, {receiver=receiver}) end + if matches[2] == "bots" and is_momod(msg) then + savelog(msg.to.id, name_log.." ["..msg.from.id.."] kicked all SuperGroup bots") + channel_get_bots(receiver, callback_clean_bots, {msg = msg}) + end end if matches[1] == 'lock' and is_momod(msg) then From f4d57117f8acbed411e9e4ced2ae2254cc80a3e9 Mon Sep 17 00:00:00 2001 From: Rondoozle Date: Fri, 15 Apr 2016 17:53:26 -0400 Subject: [PATCH 58/58] Revert "Added Missing Patterns" --- plugins/admin.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/admin.lua b/plugins/admin.lua index 9b61481..bc8a7c7 100644 --- a/plugins/admin.lua +++ b/plugins/admin.lua @@ -315,7 +315,6 @@ return { "^[#!/](setbotphoto)$", "^[#!/](contactlist)$", "^[#!/](dialoglist)$", - "^[#/!](sync_gbans)$", "^[#!/](delcontact) (%d+)$", "^[#!/](addcontact) (.*) (.*) (.*)$", "^[#!/](sendcontact) (.*) (.*) (.*)$",