Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F108486
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/plugins/admin/chatinfo.lua b/src/plugins/admin/chatinfo.lua
new file mode 100644
index 0000000..99efe3c
--- /dev/null
+++ b/src/plugins/admin/chatinfo.lua
@@ -0,0 +1,39 @@
+--[[
+ mattata v2.1 - Chat Info Plugin
+ Set chat title and description.
+]]
+
+local plugin = {}
+plugin.name = 'chatinfo'
+plugin.category = 'admin'
+plugin.description = 'Set chat title or description'
+plugin.commands = { 'settitle', 'setdescription' }
+plugin.help = '/settitle <title> - Set the chat title.\n/setdescription <text> - Set the chat description.'
+plugin.group_only = true
+plugin.admin_only = true
+
+function plugin.on_message(api, message, ctx)
+ if not message.args or message.args == '' then
+ if message.command == 'settitle' then
+ return api.send_message(message.chat.id, 'Usage: /settitle <new title>')
+ else
+ return api.send_message(message.chat.id, 'Usage: /setdescription <new description>')
+ end
+ end
+
+ if message.command == 'settitle' then
+ local result = api.set_chat_title(message.chat.id, message.args)
+ if result then
+ return api.send_message(message.chat.id, 'Chat title updated.')
+ end
+ return api.send_message(message.chat.id, 'Failed to update chat title. Make sure I have the correct permissions.')
+ else
+ local result = api.set_chat_description(message.chat.id, message.args)
+ if result then
+ return api.send_message(message.chat.id, 'Chat description updated.')
+ end
+ return api.send_message(message.chat.id, 'Failed to update chat description. Make sure I have the correct permissions.')
+ end
+end
+
+return plugin
diff --git a/src/plugins/admin/chatpermissions.lua b/src/plugins/admin/chatpermissions.lua
new file mode 100644
index 0000000..0e5f0c3
--- /dev/null
+++ b/src/plugins/admin/chatpermissions.lua
@@ -0,0 +1,101 @@
+--[[
+ mattata v2.1 - Chat Permissions Plugin
+ Manage default chat permissions with inline keyboard toggles.
+]]
+
+local plugin = {}
+plugin.name = 'chatpermissions'
+plugin.category = 'admin'
+plugin.description = 'Manage chat permissions'
+plugin.commands = { 'permissions', 'perms' }
+plugin.help = '/permissions - View and toggle default chat permissions.'
+plugin.group_only = true
+plugin.admin_only = true
+
+local json = require('dkjson')
+
+local PERMISSION_LABELS = {
+ { key = 'can_send_messages', label = 'Send Messages' },
+ { key = 'can_send_audios', label = 'Send Audios' },
+ { key = 'can_send_documents', label = 'Send Documents' },
+ { key = 'can_send_photos', label = 'Send Photos' },
+ { key = 'can_send_videos', label = 'Send Videos' },
+ { key = 'can_send_video_notes', label = 'Send Video Notes' },
+ { key = 'can_send_voice_notes', label = 'Send Voice Notes' },
+ { key = 'can_send_polls', label = 'Send Polls' },
+ { key = 'can_send_other_messages', label = 'Stickers/GIFs' },
+ { key = 'can_add_web_page_previews', label = 'Link Previews' },
+ { key = 'can_change_info', label = 'Change Info' },
+ { key = 'can_invite_users', label = 'Invite Users' },
+ { key = 'can_pin_messages', label = 'Pin Messages' },
+ { key = 'can_manage_topics', label = 'Manage Topics' },
+}
+
+local function build_keyboard(perms, chat_id)
+ local rows = {}
+ for _, perm in ipairs(PERMISSION_LABELS) do
+ local enabled = perms[perm.key]
+ local icon = enabled and '\xe2\x9c\x85' or '\xe2\x9b\x94'
+ table.insert(rows, { {
+ text = icon .. ' ' .. perm.label,
+ callback_data = 'chatpermissions:toggle:' .. chat_id .. ':' .. perm.key
+ } })
+ end
+ table.insert(rows, { { text = 'Done', callback_data = 'chatpermissions:done' } })
+ return json.encode({ inline_keyboard = rows })
+end
+
+local function get_current_permissions(api, chat_id)
+ local chat = api.get_chat(chat_id)
+ if chat and chat.result and chat.result.permissions then
+ return chat.result.permissions
+ end
+ -- Default to all enabled
+ local defaults = {}
+ for _, perm in ipairs(PERMISSION_LABELS) do
+ defaults[perm.key] = true
+ end
+ return defaults
+end
+
+function plugin.on_message(api, message, ctx)
+ local perms = get_current_permissions(api, message.chat.id)
+ local keyboard = build_keyboard(perms, message.chat.id)
+ return api.send_message(message.chat.id, '<b>Default Chat Permissions</b>\nTap a permission to toggle it.', 'html', false, false, nil, keyboard)
+end
+
+function plugin.on_callback_query(api, callback_query, message, ctx)
+ local data = callback_query.data
+ if not data then return end
+
+ if data == 'done' then
+ api.delete_message(message.chat.id, message.message_id)
+ return api.answer_callback_query(callback_query.id, 'Permissions saved.')
+ end
+
+ local chat_id, perm_key = data:match('^toggle:(%-?%d+):(.+)$')
+ if not chat_id or not perm_key then return end
+ chat_id = tonumber(chat_id)
+
+ -- Only admins can toggle
+ local permissions = require('src.core.permissions')
+ if not permissions.is_group_admin(api, chat_id, callback_query.from.id) then
+ return api.answer_callback_query(callback_query.id, 'Only admins can change permissions.')
+ end
+
+ local perms = get_current_permissions(api, chat_id)
+
+ -- Toggle
+ perms[perm_key] = not perms[perm_key]
+
+ local result = api.set_chat_permissions(chat_id, perms)
+ if not result then
+ return api.answer_callback_query(callback_query.id, 'Failed to update permissions.')
+ end
+
+ local keyboard = build_keyboard(perms, chat_id)
+ api.edit_message_reply_markup(message.chat.id, message.message_id, nil, keyboard)
+ return api.answer_callback_query(callback_query.id, 'Permission updated.')
+end
+
+return plugin
diff --git a/src/plugins/admin/customtitle.lua b/src/plugins/admin/customtitle.lua
new file mode 100644
index 0000000..298dcfc
--- /dev/null
+++ b/src/plugins/admin/customtitle.lua
@@ -0,0 +1,55 @@
+--[[
+ mattata v2.1 - Custom Title Plugin
+ Set custom admin titles.
+]]
+
+local plugin = {}
+plugin.name = 'customtitle'
+plugin.category = 'admin'
+plugin.description = 'Set admin custom title'
+plugin.commands = { 'customtitle', 'title' }
+plugin.help = '/customtitle <title> - Set a custom title for an admin. Reply to a user or pass their ID/username.'
+plugin.group_only = true
+plugin.admin_only = true
+
+function plugin.on_message(api, message, ctx)
+ local tools = require('telegram-bot-lua.tools')
+ local permissions = require('src.core.permissions')
+
+ if not permissions.can_promote(api, message.chat.id) then
+ return api.send_message(message.chat.id, 'I need the "Promote Members" admin permission to use this command.')
+ end
+
+ local target_id
+ local title
+
+ if message.reply and message.reply.from then
+ target_id = message.reply.from.id
+ title = message.args
+ elseif message.args then
+ local id_or_user, rest = message.args:match('^(%S+)%s+(.+)$')
+ if id_or_user then
+ target_id = tonumber(id_or_user) or ctx.redis.get('username:' .. id_or_user:lower():gsub('^@', ''))
+ title = rest
+ end
+ end
+
+ if not target_id or not title or title == '' then
+ return api.send_message(message.chat.id, 'Usage: Reply to an admin with /customtitle <title>, or use /customtitle <user> <title>')
+ end
+
+ if #title > 16 then
+ return api.send_message(message.chat.id, 'Custom title must be 16 characters or less.')
+ end
+
+ local result = api.set_chat_administrator_custom_title(message.chat.id, target_id, title)
+ if result then
+ return api.send_message(message.chat.id, string.format(
+ 'Custom title for <a href="tg://user?id=%s">this admin</a> set to: <b>%s</b>',
+ tostring(target_id), tools.escape_html(title)
+ ), 'html')
+ end
+ return api.send_message(message.chat.id, 'Failed to set custom title. The user must be an admin promoted by me.')
+end
+
+return plugin
diff --git a/src/plugins/admin/init.lua b/src/plugins/admin/init.lua
index 74c699e..0957f0c 100644
--- a/src/plugins/admin/init.lua
+++ b/src/plugins/admin/init.lua
@@ -1,63 +1,70 @@
--[[
mattata v2.0 - Admin Plugin Category
]]
return {
plugins = {
'administration',
'ban',
'unban',
'kick',
'mute',
'unmute',
'warn',
'tempban',
'tempmute',
'promote',
'demote',
'trust',
'untrust',
'report',
'staff',
'purge',
'rules',
'setwelcome',
'setcaptcha',
'antispam',
'filter',
'unfilter',
'wordfilter',
'antilink',
'logchat',
'setgrouplang',
'link',
'addalias',
'triggers',
'addtrigger',
'nodelete',
'channel',
'save',
'import',
'allowlist',
'blocklist',
'groups',
'join_captcha',
'pin',
'allowedlinks',
'allowlink',
+ 'unpinall',
+ 'chatinfo',
+ 'customtitle',
+ 'slowmode',
+ 'topic',
+ 'joinrequest',
+ 'chatpermissions',
-- Federation sub-package
'federation.newfed',
'federation.delfed',
'federation.joinfed',
'federation.leavefed',
'federation.fban',
'federation.unfban',
'federation.fbaninfo',
'federation.fpromote',
'federation.fdemote',
'federation.fadmins',
'federation.fallowlist',
'federation.myfeds',
'federation.feds'
}
}
diff --git a/src/plugins/admin/joinrequest.lua b/src/plugins/admin/joinrequest.lua
new file mode 100644
index 0000000..91e9b6b
--- /dev/null
+++ b/src/plugins/admin/joinrequest.lua
@@ -0,0 +1,135 @@
+--[[
+ mattata v2.1 - Join Request Plugin
+ Manage join request policies for groups with approval-required invites.
+ Depends on the on_chat_join_request router hook (Phase 3).
+]]
+
+local plugin = {}
+plugin.name = 'joinrequest'
+plugin.category = 'admin'
+plugin.description = 'Manage join request policy'
+plugin.commands = { 'joinrequest' }
+plugin.help = '/joinrequest <auto-approve|auto-reject|manual> - Set the join request policy for this chat.'
+plugin.group_only = true
+plugin.admin_only = true
+
+local json = require('dkjson')
+
+local POLICIES = {
+ ['auto-approve'] = true, ['approve'] = true, ['auto'] = true,
+ ['auto-reject'] = true, ['reject'] = true, ['deny'] = true,
+ ['manual'] = true, ['notify'] = true
+}
+
+local function normalize_policy(input)
+ input = input:lower()
+ if input == 'auto-approve' or input == 'approve' or input == 'auto' then
+ return 'auto-approve'
+ elseif input == 'auto-reject' or input == 'reject' or input == 'deny' then
+ return 'auto-reject'
+ elseif input == 'manual' or input == 'notify' then
+ return 'manual'
+ end
+ return nil
+end
+
+function plugin.on_message(api, message, ctx)
+ if not message.args or message.args == '' then
+ local current = ctx.db.call('sp_get_chat_setting', { message.chat.id, 'join_request_policy' })
+ local policy = (current and #current > 0) and current[1].value or 'manual'
+ return api.send_message(message.chat.id, string.format(
+ 'Current join request policy: <b>%s</b>\n\nUsage: /joinrequest <auto-approve|auto-reject|manual>',
+ policy
+ ), 'html')
+ end
+
+ local policy = normalize_policy(message.args)
+ if not policy then
+ return api.send_message(message.chat.id, 'Invalid policy. Use: auto-approve, auto-reject, or manual')
+ end
+
+ ctx.db.call('sp_upsert_chat_setting', { message.chat.id, 'join_request_policy', policy })
+ require('src.core.session').invalidate_setting(message.chat.id, 'join_request_policy')
+
+ return api.send_message(message.chat.id, string.format(
+ 'Join request policy set to <b>%s</b>.', policy
+ ), 'html')
+end
+
+-- Handle incoming join requests based on configured policy
+function plugin.on_chat_join_request(api, request, ctx)
+ local session = require('src.core.session')
+ local tools = require('telegram-bot-lua.tools')
+
+ local policy = session.get_cached_setting(request.chat.id, 'join_request_policy', function()
+ local result = ctx.db.call('sp_get_chat_setting', { request.chat.id, 'join_request_policy' })
+ if result and #result > 0 then return result[1].value end
+ return nil
+ end, 300)
+
+ if not policy or policy == 'manual' then
+ -- Post notification with approve/reject buttons
+ local keyboard = {
+ inline_keyboard = { {
+ { text = 'Approve', callback_data = 'joinrequest:approve:' .. request.from.id },
+ { text = 'Reject', callback_data = 'joinrequest:reject:' .. request.from.id }
+ } }
+ }
+ local text = string.format(
+ '<a href="tg://user?id=%d">%s</a> wants to join this chat.',
+ request.from.id,
+ tools.escape_html(request.from.first_name)
+ )
+ return api.send_message(request.chat.id, text, 'html', false, false, nil, json.encode(keyboard))
+
+ elseif policy == 'auto-approve' then
+ return api.approve_chat_join_request(request.chat.id, request.from.id)
+
+ elseif policy == 'auto-reject' then
+ return api.decline_chat_join_request(request.chat.id, request.from.id)
+ end
+end
+
+function plugin.on_callback_query(api, callback_query, message, ctx)
+ local data = callback_query.data
+ if not data then return end
+
+ local action, user_id = data:match('^(approve):(%d+)$')
+ if not action then
+ action, user_id = data:match('^(reject):(%d+)$')
+ end
+ if not action or not user_id then return end
+
+ user_id = tonumber(user_id)
+
+ -- Only admins can handle join requests
+ local permissions = require('src.core.permissions')
+ if not permissions.is_group_admin(api, message.chat.id, callback_query.from.id) then
+ return api.answer_callback_query(callback_query.id, 'Only admins can handle join requests.')
+ end
+
+ local tools = require('telegram-bot-lua.tools')
+ if action == 'approve' then
+ local result = api.approve_chat_join_request(message.chat.id, user_id)
+ if result then
+ api.edit_message_text(message.chat.id, message.message_id, string.format(
+ 'Join request from <a href="tg://user?id=%d">user</a> approved by %s.',
+ user_id, tools.escape_html(callback_query.from.first_name)
+ ), 'html')
+ return api.answer_callback_query(callback_query.id, 'Approved.')
+ end
+ return api.answer_callback_query(callback_query.id, 'Failed to approve. The request may have expired.')
+ else
+ local result = api.decline_chat_join_request(message.chat.id, user_id)
+ if result then
+ api.edit_message_text(message.chat.id, message.message_id, string.format(
+ 'Join request from <a href="tg://user?id=%d">user</a> rejected by %s.',
+ user_id, tools.escape_html(callback_query.from.first_name)
+ ), 'html')
+ return api.answer_callback_query(callback_query.id, 'Rejected.')
+ end
+ return api.answer_callback_query(callback_query.id, 'Failed to reject. The request may have expired.')
+ end
+end
+
+return plugin
diff --git a/src/plugins/admin/slowmode.lua b/src/plugins/admin/slowmode.lua
new file mode 100644
index 0000000..8575f6c
--- /dev/null
+++ b/src/plugins/admin/slowmode.lua
@@ -0,0 +1,50 @@
+--[[
+ mattata v2.1 - Slow Mode Plugin
+ Control slow mode delay in groups.
+]]
+
+local plugin = {}
+plugin.name = 'slowmode'
+plugin.category = 'admin'
+plugin.description = 'Set slow mode delay'
+plugin.commands = { 'slowmode', 'slow' }
+plugin.help = '/slowmode <off|10s|30s|1m|5m|15m|1h> - Set slow mode delay for the chat.'
+plugin.group_only = true
+plugin.admin_only = true
+
+local DELAYS = {
+ ['off'] = 0, ['0'] = 0, ['disable'] = 0,
+ ['10s'] = 10, ['10'] = 10,
+ ['30s'] = 30, ['30'] = 30,
+ ['1m'] = 60, ['60'] = 60, ['60s'] = 60,
+ ['5m'] = 300, ['300'] = 300, ['300s'] = 300,
+ ['15m'] = 900, ['900'] = 900, ['900s'] = 900,
+ ['1h'] = 3600, ['3600'] = 3600, ['3600s'] = 3600,
+}
+
+local function format_delay(seconds)
+ if seconds == 0 then return 'disabled' end
+ if seconds < 60 then return seconds .. ' seconds' end
+ if seconds < 3600 then return (seconds / 60) .. ' minutes' end
+ return (seconds / 3600) .. ' hour'
+end
+
+function plugin.on_message(api, message, ctx)
+ if not message.args or message.args == '' then
+ return api.send_message(message.chat.id, 'Usage: /slowmode <off|10s|30s|1m|5m|15m|1h>')
+ end
+
+ local delay = DELAYS[message.args:lower()]
+ if not delay then
+ return api.send_message(message.chat.id, 'Invalid delay. Options: off, 10s, 30s, 1m, 5m, 15m, 1h')
+ end
+
+ local result = api.set_chat_slow_mode_delay(message.chat.id, delay)
+ if result then
+ local label = format_delay(delay)
+ return api.send_message(message.chat.id, string.format('Slow mode set to <b>%s</b>.', label), 'html')
+ end
+ return api.send_message(message.chat.id, 'Failed to set slow mode. Make sure I have the correct permissions.')
+end
+
+return plugin
diff --git a/src/plugins/admin/topic.lua b/src/plugins/admin/topic.lua
new file mode 100644
index 0000000..39d0dea
--- /dev/null
+++ b/src/plugins/admin/topic.lua
@@ -0,0 +1,93 @@
+--[[
+ mattata v2.1 - Topic Plugin
+ Forum topic management for supergroups with topics enabled.
+]]
+
+local plugin = {}
+plugin.name = 'topic'
+plugin.category = 'admin'
+plugin.description = 'Manage forum topics'
+plugin.commands = { 'topic' }
+plugin.help = '/topic <create|close|reopen|delete|rename> [name] - Manage forum topics.'
+plugin.group_only = true
+plugin.admin_only = true
+
+function plugin.on_message(api, message, ctx)
+ if not message.chat.is_forum then
+ return api.send_message(message.chat.id, 'This command only works in forum-enabled groups.')
+ end
+
+ if not message.args or message.args == '' then
+ return api.send_message(message.chat.id, 'Usage:\n/topic create <name>\n/topic close\n/topic reopen\n/topic delete\n/topic rename <name>')
+ end
+
+ local subcommand, args = message.args:match('^(%S+)%s*(.*)')
+ subcommand = subcommand:lower()
+
+ local topic_id = message.message_thread_id
+
+ if subcommand == 'create' then
+ if not args or args == '' then
+ return api.send_message(message.chat.id, 'Usage: /topic create <name>')
+ end
+ local result = api.create_forum_topic(message.chat.id, args)
+ if result and result.result then
+ return api.send_message(message.chat.id, string.format(
+ 'Topic "<b>%s</b>" created.',
+ require('telegram-bot-lua.tools').escape_html(args)
+ ), 'html')
+ end
+ return api.send_message(message.chat.id, 'Failed to create topic.')
+
+ elseif subcommand == 'close' then
+ if not topic_id then
+ return api.send_message(message.chat.id, 'Send this command inside the topic you want to close.')
+ end
+ local result = api.close_forum_topic(message.chat.id, topic_id)
+ if result then
+ return api.send_message(message.chat.id, 'Topic closed.')
+ end
+ return api.send_message(message.chat.id, 'Failed to close topic.')
+
+ elseif subcommand == 'reopen' then
+ if not topic_id then
+ return api.send_message(message.chat.id, 'Send this command inside the topic you want to reopen.')
+ end
+ local result = api.reopen_forum_topic(message.chat.id, topic_id)
+ if result then
+ return api.send_message(message.chat.id, 'Topic reopened.')
+ end
+ return api.send_message(message.chat.id, 'Failed to reopen topic.')
+
+ elseif subcommand == 'delete' then
+ if not topic_id then
+ return api.send_message(message.chat.id, 'Send this command inside the topic you want to delete.')
+ end
+ local result = api.delete_forum_topic(message.chat.id, topic_id)
+ if result then
+ return -- topic deleted, can't send message to it
+ end
+ return api.send_message(message.chat.id, 'Failed to delete topic.')
+
+ elseif subcommand == 'rename' then
+ if not topic_id then
+ return api.send_message(message.chat.id, 'Send this command inside the topic you want to rename.')
+ end
+ if not args or args == '' then
+ return api.send_message(message.chat.id, 'Usage: /topic rename <new name>')
+ end
+ local result = api.edit_forum_topic(message.chat.id, topic_id, args)
+ if result then
+ return api.send_message(message.chat.id, string.format(
+ 'Topic renamed to "<b>%s</b>".',
+ require('telegram-bot-lua.tools').escape_html(args)
+ ), 'html')
+ end
+ return api.send_message(message.chat.id, 'Failed to rename topic.')
+
+ else
+ return api.send_message(message.chat.id, 'Unknown subcommand. Use: create, close, reopen, delete, rename')
+ end
+end
+
+return plugin
diff --git a/src/plugins/admin/unpinall.lua b/src/plugins/admin/unpinall.lua
new file mode 100644
index 0000000..1387efd
--- /dev/null
+++ b/src/plugins/admin/unpinall.lua
@@ -0,0 +1,28 @@
+--[[
+ mattata v2.1 - Unpin All Plugin
+ Unpins all messages in a chat.
+]]
+
+local plugin = {}
+plugin.name = 'unpinall'
+plugin.category = 'admin'
+plugin.description = 'Unpin all pinned messages'
+plugin.commands = { 'unpinall' }
+plugin.help = '/unpinall - Unpins all pinned messages in this chat.'
+plugin.group_only = true
+plugin.admin_only = true
+
+function plugin.on_message(api, message, ctx)
+ local permissions = require('src.core.permissions')
+ if not permissions.can_pin(api, message.chat.id) then
+ return api.send_message(message.chat.id, 'I need the "Pin Messages" admin permission to use this command.')
+ end
+
+ local result = api.unpin_all_chat_messages(message.chat.id)
+ if result then
+ return api.send_message(message.chat.id, 'All pinned messages have been unpinned.')
+ end
+ return api.send_message(message.chat.id, 'Failed to unpin messages. Make sure I have the correct permissions.')
+end
+
+return plugin
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Apr 1, 11:15 AM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
57029
Default Alt Text
(22 KB)
Attached To
Mode
R69 mattata
Attached
Detach File
Event Timeline