From 5a725610de1bdd45a5a9612860bdd2d9df87393b Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:11:58 +0330 Subject: [PATCH 01/36] V 0.85 --- redis.lua | 1140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1140 insertions(+) create mode 100644 redis.lua diff --git a/redis.lua b/redis.lua new file mode 100644 index 0000000..77aea79 --- /dev/null +++ b/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 From 2e40c2d99702e892192b0233f6794ba63388ca7e Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:12:48 +0330 Subject: [PATCH 02/36] V 0.85 --- bot.lua | 439 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 bot.lua diff --git a/bot.lua b/bot.lua new file mode 100644 index 0000000..d869c96 --- /dev/null +++ b/bot.lua @@ -0,0 +1,439 @@ +redis = (loadfile "redis.lua")() +redis = redis.connect('127.0.0.1', 6379) + +function dl_cb(arg, data) +end + +function get_admin () + if redis:get('botBOT-IDadmin') then + admin = redis:get('botBOT-IDadmin') + else + print("\n\27[32m لازمه کارکرد صحیح ، فرامین و امورات مدیریتی ربات تبلیغ گر <<\n تعریف کاربری به عنوان مدیر است\n\27[34m ایدی خود را به عنوان مدیر وارد کنید\n\27[32m شما می توانید از ربات زیر شناسه عددی خود را بدست اورید\n\27[34m ربات: @info_ProBot") + print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @info_ProBot") + print("\n\27[36m : شناسه عددی ادمین را وارد کنید << \n >> Imput the Admin ID :\n\27[31m ") + admin=io.read() + redis:set("botBOT-IDadmin", admin) + end + return print("\n\27[36m ADMIN ID |\27[32m ".. admin .." \27[36m| شناسه ادمین") +end + +function get_bot (i, naji) + function bot_info (i, naji) + redis:del("botBOT-IDid") + redis:set("botBOT-IDid",naji.id_) + if naji.first_name_ then + redis:del("botBOT-IDfname") + redis:set("botBOT-IDfname",naji.first_name_) + end + if naji.last_name_ then + redis:del("botBOT-IDlanme") + redis:set("botBOT-IDlanme",naji.last_name_) + else + redis:del("botBOT-IDlname") + end + redis:del("botBOT-IDnum") + redis:set("botBOT-IDnum",naji.phone_number_) + return naji.id_ + end + tdcli_function ({ID = "GetMe",}, bot_info, nil) +end + +function writefile(filename, input) + local file = io.open(filename, "w") + file:write(input) + file:flush() + file:close() + return true +end + +function process_link(text) + if text:match("https://telegram.me/joinchat/%S+") or text:match("https://t.me/joinchat/%S+") then + local text = text:gsub("t.me", "telegram.me") + local matches = {text:match("(https://telegram.me/joinchat/%S+)")} + for i, v in pairs(matches) do + tdcli_function({ID = "CheckChatInviteLink",invite_link_ = v}, + function (i, naji) + if naji.is_group_ or naji.is_supergroup_channel_ then + redis:sadd("botBOT-IDsavedlinks", i.link) + tdcli_function ({ID = "ImportChatInviteLink",invite_link_ = i.link}, dl_cb, nil) + end + end, + {link = v}) + return true + end + end +end +function add(id) + local Id = tostring(id) + if not redis:sismember("botBOT-IDall", id) then + if Id:match("^(%d+)$") then + redis:sadd("botBOT-IDusers", id) + redis:sadd("botBOT-IDall", id) + elseif Id:match("^-100") then + redis:sadd("botBOT-IDsupergroups", id) + redis:sadd("botBOT-IDall", id) + else + redis:sadd("botBOT-IDgroups", id) + redis:sadd("botBOT-IDall", id) + end + end + return true +end +function rem(id) + local Id = tostring(id) + if redis:sismember("botBOT-IDall", id) then + if Id:match("^(%d+)$") then + redis:srem("botBOT-IDusers", id) + redis:srem("botBOT-IDall", id) + elseif Id:match("^-100") then + redis:srem("botBOT-IDsupergroups", id) + redis:srem("botBOT-IDall", id) + else + redis:srem("botBOT-IDgroups", id) + redis:srem("botBOT-IDall", id) + end + end + return true +end +function send(chat_id, msg_id, text) + tdcli_function ({ + ID = "SendMessage", + chat_id_ = chat_id, + reply_to_message_id_ = msg_id, + disable_notification_ = 1, + from_background_ = 1, + reply_markup_ = nil, + input_message_content_ = { + ID = "InputMessageText", + text_ = text, + disable_web_page_preview_ = 1, + clear_draft_ = 0, + entities_ = {}, + parse_mode_ = {ID = "TextParseModeHTML"}, + }, + }, dl_cb, nil) +end +get_admin() +function tdcli_update_callback(data) + if data.ID == "UpdateNewMessage" then + local msg = data.message_ + local realm = redis:get('botBOT-IDrealm') + local admin = redis:get('botBOT-IDadmin') + local bot_id = redis:get("botBOT-IDid") or get_bot() + if msg.sender_user_id_ == 777000 then + return tdcli_function({ + ID = "ForwardMessages", + chat_id_ = realm or admin, + from_chat_id_ = msg.chat_id_, + message_ids_ = {[0] = msg.id_}, + disable_notification_ = 0, + from_background_ = 1 + }, dl_cb, nil) + end + if tostring(msg.chat_id_):match("^(%d+)") then + if not redis:sismember("botBOT-IDall", msg.chat_id_) then + redis:sadd("botBOT-IDusers", msg.chat_id_) + redis:sadd("botBOT-IDall", msg.chat_id_) + end + end + add(msg.chat_id_) + if msg.content_.ID == "MessageText" then + local text = msg.content_.text_ + process_link(text) + if msg.sender_user_id_ == tonumber(admin) then + if text:match("^حذف گروه مدیریت$") then + redis:del('botBOT-IDrealm') + send(msg.chat_id_, msg.id_, "گروه مدیریتی حذف شد") + elseif text:match("^(تنظیم مدیر) (%d+)$") then + local matches = {string.match(text, "^(افزودن مدیر) (%d+)$")} + redis:set("botBOT-IDadmin", matches[2]) + send(msg.chat_id_, msg.id_, "ادمین ربات با موفقیت تغییر کرد") + elseif text:match("^(/reload)$") then + loadfile("./bot-BOT-ID.lua")() + send(msg.chat_id_, msg.id_, "بارگذاری مجدد انجام شد") + elseif text:match("^(ترک کردن) (.*)$") then + local matches = {string.match(text, "^(ترک گروه) (.*)$")} + send(msg.chat_id_, msg.id_, 'گروه ترک شد') + tdcli_function ({ + ID = "ChangeChatMemberStatus", + chat_id_ = matches[2], + user_id_ = bot_id, + status_ = {ID = "ChatMemberStatusLeft"}, + }, dl_cb, nil) + rem(matches[2]) + elseif text:match("^بروزرسانی ربات$") then + io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian"):read("*all") + local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) + io.open("bot-BOT-ID.lua",'w'):write(text):close() + loadfile("./bot-BOT-ID.lua")() + send(msg.chat_id_, msg.id_, "تبلیغ گر با موفقیت بروزرسانی شد") + elseif text:match("^همگام سازی با تبچی$") then + local botid = BOT-ID - 1 + --redis:del("botBOT-IDall") + redis:sunionstore("botBOT-IDall","tabchi:"..tostring(botid)..":all") + --redis:del("botBOT-IDusers") + redis:sunionstore("botBOT-IDusers","tabchi:"..tostring(botid)..":pvis") + --redis:del("botBOT-IDgroups") + redis:sunionstore("bot1groups","tabchi:"..tostring(botid)..":groups") + --redis:del("bot1supergroups") + redis:sunionstore("bot1supergroups","tabchi:"..tostring(botid)..":channels") + --redis:del("bot1savedlinks") + redis:sunionstore("bot1savedlinks","tabchi:"..tostring(botid)..":savedlinks") + send(msg.chat_id_, msg.id_, "همگام سازی اطلاعات با تبچی شماره "..tostring(botid).." انجام شد.") + end + if tostring(msg.chat_id_):match("^-") then + if text:match("^(افزودن گروه مدیریت)$") then + redis:set('botBOT-IDrealm', msg.chat_id_) + send(msg.chat_id_, msg.id_, 'گروه مدیریتی ثبت شد') + elseif text:match("^(ترک کردن)$") then + tdcli_function ({ + ID = "ChangeChatMemberStatus", + chat_id_ = msg.chat_id_, + user_id_ = bot_id, + status_ = {ID = "ChatMemberStatusLeft"}, + }, dl_cb, nil) + rem(msg.chat_id_) + end + end + end + if tostring(msg.chat_id_) == realm or tostring(msg.sender_user_id_) == admin then + if text:match("^(لیست) (.*)$") then + local matches = {text:match("^(لیست) (.*)$")} + if matches[2] == "مخاطبین" then + return tdcli_function({ + ID = "SearchContacts", + query_ = nil, + limit_ = 999999999 + }, + function (I, Naji) + local count = Naji.total_count_ + local text = "مخاطب های ذخیره شده : \n" + for i = 0, tonumber(count) - 1 do + local user = Naji.users_[i] + local firstname = user.first_name_ or "" + local lastname = user.last_name_ or "" + local fullname = firstname .. " " .. lastname + text = tostring(text) .. tostring(i) .. ". " .. tostring(fullname) .. " [" .. tostring(user.id_) .. "] = " .. tostring(user.phone_number_) .. " \n" + end + writefile("botBOT-ID_contacts.txt", text) + tdcli_function ({ + ID = "SendMessage", + chat_id_ = I.chat_id, + reply_to_message_id_ = 0, + disable_notification_ = 0, + from_background_ = 1, + reply_markup_ = nil, + input_message_content_ = {ID = "InputMessageDocument", + document_ = {ID = "InputFileLocal", + path_ = "botBOT-ID_contacts.txt"}, + caption_ = "مخاطبین تبلیغ گر شماره BOT-ID"} + }, dl_cb, nil) + return io.popen("rm -rf botBOT-ID_contacts.txt"):read("*all") + end, {chat_id = msg.chat_id_}) + end + elseif text:match("^(وضعیت مشاهده) (.*)$") then + local matches = {text:match("^(وضعیت پیام) (.*)$")} + if matches[2] == "روشن" then + redis:set("botBOT-IDmarkread", true) + send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده شده ✔️✔️\n(تیک دوم فعال)") + elseif matches[2] == "خاموش" then + redis:del("botBOT-IDmarkread") + send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده نشده ✔️\n(بدون تیک دوم)") + end + elseif text:match("^(افزودن با پیام) (.*)$") then + local matches = {text:match("(افزودن با پیام) (.*)$")} + if matches[2] == "روشن" then + redis:set("botBOT-IDaddmsg", true) + return send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب فعال شد") + elseif matches[2] == "خاموش" then + redis:del("botBOT-IDaddmsg") + return send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب غیرفعال شد") + end + elseif text:match("^(افزودن با شماره) (.*)$") then + local matches = {text:match("(افزودن با شماره) (.*)$")} + if matches[2] == "روشن" then + redis:set("botBOT-IDaddcontact", true) + return send(msg.chat_id_, msg.id_, "ارسال شماره هنگام افزودن مخاطب فعال شد") + elseif matches[2] == "خاموش" then + redis:del("botBOT-IDaddcontact") + return send(msg.chat_id_, msg.id_, "ارسال شماره هنگام افزودن مخاطب غیرفعال شد") + end + elseif text:match("^(تنظیم پیام افزودن مخاطب) (.*)") then + local matches = {text:match("^(تنظیم پیام افزودن مخاطب) (.*)")} + redis:set("botBOT-IDaddmsgtext", matches[2]) + send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب ثبت شد :\n🔹 "..matches[2].." 🔹") + elseif text:match("^(امار)$") or text:match("^(آمار)$") then + local gps = redis:scard("botBOT-IDgroups") + local sgps = redis:scard("botBOT-IDsupergroups") + local usrs = redis:scard("botBOT-IDusers") + local links = redis:scard("botBOT-IDsavedlinks") + local contacts = redis:scard("botBOT-IDaddedcontacts") + local text = [[ +📈 وضعیت و آمار تبلیغ گر 📊 + +👤 گفت و گو های شخصی : +]] .. tostring(usrs) .. [[ +👥 گروها : +]] .. tostring(gps) .. [[ +🌐 سوپر گروه ها : +]] .. tostring(sgps) .. [[ +📖 مخاطبین دخیره شده : +]] .. tostring(contacts)..[[ +📂 لینک های ذخیره شده : +]] .. tostring(links)..[[ + 😼 سازنده : @i_naji]] + send(msg.chat_id_, 0, text) + elseif (text:match("^(ارسال به) (.*)$") and msg.reply_to_message_id_ ~= 0) then + local matches = {text:match("^(ارسال به) (.*)$")} + local naji + if matches[2]:match("^(همه)$") then + naji = "botBOT-IDall" + elseif matches[2]:match("^(خصوصی)") then + naji = "botBOT-IDusers" + elseif matches[2]:match("^(گروه)") then + naji = "botBOT-IDgroups" + elseif matches[2]:match("^(سوپرگروه)") then + naji = "botBOT-IDsupergroups" + else + return true + end + local list = redis:smembers(naji) + local id = msg.reply_to_message_id_ + for i, v in pairs(list) do + tdcli_function({ + ID = "ForwardMessages", + chat_id_ = v, + from_chat_id_ = msg.chat_id_, + message_ids_ = {[0] = id}, + disable_notification_ = 1, + from_background_ = 1 + }, dl_cb, nil) + end + send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") + elseif text:match("^(مسدودیت) (%d+)$") then + local matches = {text:match("^(مسدود کردن) (%d+)$")} + rem(tonumber(matches[2])) + redis:sadd("botBOT-IDblockedusers",matches[2]) + tdcli_function ({ + ID = "BlockUser", + user_id_ = tonumber(matches[2]) + }, dl_cb, nil) + send(msg.chat_id_, msg.id_, "کاربر مورد نظر مسدود شد") + elseif text:match("^(رفع مسدودیت) (%d+)$") then + local matches = {text:match("^(رفع مسدودیت) (%d+)$")} + add(tonumber(matches[2])) + redis:srem("botBOT-IDblockedusers",matches[2]) + tdcli_function ({ + ID = "UnblockUser", + user_id_ = tonumber(matches[2]) + }, dl_cb, nil) + send(msg.chat_id_, msg.id_, "مسدودیت کاربر مورد نظر رفع شد.") + elseif text:match('^(تنظیم نام) "(.*)" (.*)') then + local matches = {text:match('^(تنظیم نام) "(.*)" (.*)')} + tdcli_function ({ + ID = "ChangeName", + first_name_ = matches[2], + last_name_ = matches[3] + }, dl_cb, nil) + send(msg.chat_id_, 0, "تنظیم نام با موفقیت انجام شد") + elseif text:match("^(تنظیم نام کاربری) (.*)") then + local matches = {text:match("^(تنظیم نام کاربری) (.*)")} + tdcli_function ({ + ID = "ChangeUsername", + username_ = tostring(matches[2]) + }, dl_cb, nil) + send(msg.chat_id_, 0, 'تلاش برای تنظیم نام کاربری...') + elseif text:match("^(حذف نام کاربری)$") then + tdcli_function ({ + ID = "ChangeUsername", + username_ = "" + }, dl_cb, nil) + send(msg.chat_id_, 0, 'نام کاربری با موفقیت حذف شد.') + elseif text:match("^(ارسال کن) '(.*)' (.*)") then + local matches = {string.match(text, "^(ارسال کن) '(.*)' (.*)")} + send(tostring(matches[2]), 0, matches[3]) + return send(msg.chat_id_, 0, "ارسال شد") + elseif text:match("^(بگو) (.*)") then + local matches = {string.match(text, "^(بگو) (.*)")} + return send(msg.chat_id_, 0, matches[2]) + elseif text:match("^(شناسه مدیر)$") then + return send(msg.chat_id_, 0, "" .. admin .."") + elseif text:match("^(شناسه من)$") then + return send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") + end + end + end + elseif msg.content_.ID == "MessageContact" then + local first = msg.content_.contact_.first_name_ or "-" + local last = msg.content_.contact_.last_name_ or "-" + local phone = msg.content_.contact_.phone_number_ + local id = msg.content_.contact_.user_id_ + tdcli_function ({ + ID = "ImportContacts", + contacts_ = {[0] = { + phone_number_ = tostring(phone), + first_name_ = tostring(first), + last_name_ = tostring(last), + user_id_ = id + }, + }, + }, dl_cb, nil) + if not redis:sismember("botBOT-IDaddedcontacts",id) then + redis:sadd("botBOT-IDaddedcontacts",id) + end + if redis:get("botBOT-IDaddmsg") then + local answer = redis:get("botBOT-IDaddmsgtext") or "اددی گلم خصوصی پیام بده" + send(msg.chat_id_, 0, answer) + end + if redis:get("botBOT-IDaddcontact") and msg.sender_user_id_ ~= bot_id then + local fname = redis:get("botBOT-IDfname") + local lnasme = redis:get("botBOT-IDlname") or "" + local num = redis:get("botBOT-IDnum") + tdcli_function ({ + ID = "SendMessage", + chat_id_ = msg.chat_id_, + reply_to_message_id_ = 0, + disable_notification_ = 1, + from_background_ = 1, + reply_markup_ = nil, + input_message_content_ = { + ID = "InputMessageContact", + contact_ = { + ID = "Contact", + phone_number_ = num, + first_name_ = fname, + last_name_ = lname, + user_id_ = bot_id + }, + }, + }, dl_cb, nil) + end + elseif msg.content_.ID == "MessageChatDeleteMember" and msg.content_.id_ == bot_id then + return rem(msg.chat_id_) + elseif msg.content_.ID == "MessageChatJoinByLink" and msg.sender_user_id_ == bot_id then + return add(msg.chat_id_) + elseif msg.content_.ID == "MessageChatAddMembers" then + for i = 0, #msg.content_.members_ do + if msg.content_.members_[i].id_ == bot_id then + add(msg.chat_id_) + end + end + elseif msg.content_.caption_ then + return process_link(msg.content_.caption_) + end + if redis:get("botBOT-IDmarkread") then + tdcli_function ({ + ID = "ViewMessages", + chat_id_ = msg.chat_id_, + message_ids_ = {[0] = msg.id_} + }, dl_cb, nil) + end + elseif data.ID == "UpdateOption" and data.name_ == "my_id" then + tdcli_function ({ + ID = "GetChats", + offset_order_ = 9223372036854775807, + offset_chat_id_ = 0, + limit_ = 20 + }, dl_cb, nil) + end +end From 1c06681aeca9fd7424eb15ceb0a7d8c2862c247b Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:14:08 +0330 Subject: [PATCH 03/36] V 0.85 --- bot | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 bot diff --git a/bot b/bot new file mode 100644 index 0000000..75a228d --- /dev/null +++ b/bot @@ -0,0 +1,176 @@ +#!/usr/bin/env bash + +## VARIABLES +THIS_DIR=$(cd "$(dirname "$0")"; pwd) +TDCLI='https://valtman.name/files/telegram-cli-1222' + +## Print Colorful +# Print text in red +prtred() { + printf '\e[1;31m%s\n\e[0;39;49m' "$@" +} +# Print text in green +prtgrn() { + printf '\e[1;32m%s\n\e[0;39;49m' "$@" +} +# Print text in brown +prtbrown() { + printf '\e[1;33m%s\n\e[0;39;49m' "$@" +} +# update data to the last version +update() { + git pull -f + prtgrn " + بروزرسانی اطلاعات با موفقیت انجام شد << + >> Bot's source successfully updated +" +} +# Create a new Bot +create() { + name=bot + if [[ -e $name.lua ]] ; then + i=1 + while [[ -e $name-$i.lua ]] ; do + let i++ + done + name=$name-$i + fi + cat bot.lua >> "$name".lua + sed -i 's/BOTID/'$i'/g' "$name".lua + prtgrn " + ربات شماره "$1" ساخته شد << + : رباتتان را با فرمان زیر اجرا کنید +>> new bot seccessfuly created + bot number "$i" + run your bot by :" +prtred " + ./bot "$i" +" +} +# Reset data to the last update +fix() { + git reset --hard FETCH_HEAD + prtgrn ' + بازیابی اطلاعات به آخرین آپدیت انجام شد << + >> Database Reseted and Fixed +' +} +# install Bot +install() { + prtgrn ' + آیا قصد نصب پیش نیاز های ربات تبلیغگر را دارید؟ بله|خیر << + >> Do you want to install Essentials of Tabchi bot? (Y/N): +' + read -rp ' ' install + case "$install" in + Y|y|بله) + prtgrn " + telegram-cli بارگیری << + >> Fetching $TDCLI +" + wget "$TDCLI" -O telegram-cli + sudo chmod +x telegram-cli + prtgrn " + ارتقای اطلاعات قدیمی << + >> Updating old packages +" + sudo apt-get -y update && sudo apt-get -y upgrade + prtgrn " + نصب بسته های پیش نیازی << + >> Installing Essentials packages +" + sudo apt-get --force-yes install git wget screen tmux libconfig9 libevent-dev libjansson4 libstdc++6 lua-socket lua5.2 liblua5.2 make unzip redis-server software-properties-common g++ + sudo apt-get -y update && sudo apt-get -y upgrade + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test && sudo apt-get update && sudo apt-get install -y gcc-4.9 g++-4.9 && sudo update-alternatives —install /usr/bin/gcc gcc /usr/bin/gcc-4.9 60 —slave /usr/bin/g++ g++ /usr/bin/g++-4.9 + prtgrn " + ارتقای بسته های نصب شده << + >> Updating packages +" + sudo apt-get -y update && sudo apt-get -y upgrade && sudo apt-get -y dist-upgrade && sudo apt-get -y autoremove + prtgrn " + redis راه اندازی مجدد << + >> Restarting redis service +" + sudo service redis-server restart + prtgrn ' + همگام سازی با جدیدترین نسخه تبلیغگر << + >> Fetching latest Bot source code + ' + git pull + prtgrn ' + نصب پیش نیاز های ربات تبلیغگر با موفقیت انجام شد << + >> Essentials of Tablighgar Bot successfully installed! + ' + printf '\e[1;33mبسازید\e[1;32m ./bot create \e[1;33mربات تبلیغگر خود را با دستور <<\e[1;33m%s\n >>Create Your bot with\e[1;32m ./bot create\e[0;39;49m%s\n' + ;; + N|n|خیر) + prtbrown ' + لغو عملیات + Canceling the operation + ' + ;; + *) + prtred ' + دستور اشتباه + Wrong command + ' + install + ;; + esac +} +# How to use this script +usage() { +printf "\e[1;36m" + cat <> Usage: $0 [options] + Options: + unmber Start bot whit this ID number + install Install of Tabchi Bot + create Create a new Tabchi Bot + update Update bot source code + help Print this message + fix Reseting data +EOF +printf "%s\n\e[0;39;49m" +} +## MAIN ------------------------------------------------------------------------ +# Make sure this script run inside Bot directory +cd "$THIS_DIR" || exit + +case $1 in + update) + update + ;; + create) + create + ;; + install) + install + ;; + fix) + fix + ;; + help) + usage + ;; + *) + if [ -a "$THIS_DIR"/bot-"$1".lua ]; then + sudo service redis-server restart + #while true; do + ./telegram-cli -p bot-"$1" -s bot-"$1".lua + #done + else + usage + fi + ;; +esac From 4ca9240ac7650b79699a01431b5ecb8701af2213 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:24:06 +0330 Subject: [PATCH 04/36] V 0.85 --- bot.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot.lua b/bot.lua index d869c96..b51a45f 100644 --- a/bot.lua +++ b/bot.lua @@ -8,8 +8,8 @@ function get_admin () if redis:get('botBOT-IDadmin') then admin = redis:get('botBOT-IDadmin') else - print("\n\27[32m لازمه کارکرد صحیح ، فرامین و امورات مدیریتی ربات تبلیغ گر <<\n تعریف کاربری به عنوان مدیر است\n\27[34m ایدی خود را به عنوان مدیر وارد کنید\n\27[32m شما می توانید از ربات زیر شناسه عددی خود را بدست اورید\n\27[34m ربات: @info_ProBot") - print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @info_ProBot") + print("\n\27[32m لازمه کارکرد صحیح ، فرامین و امورات مدیریتی ربات تبلیغ گر <<\n تعریف کاربری به عنوان مدیر است\n\27[34m ایدی خود را به عنوان مدیر وارد کنید\n\27[32m شما می توانید از ربات زیر شناسه عددی خود را بدست اورید\n\27[34m ربات: @id_ProBot") + print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @id_ProBot") print("\n\27[36m : شناسه عددی ادمین را وارد کنید << \n >> Imput the Admin ID :\n\27[31m ") admin=io.read() redis:set("botBOT-IDadmin", admin) @@ -362,7 +362,6 @@ function tdcli_update_callback(data) return send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") end end - end elseif msg.content_.ID == "MessageContact" then local first = msg.content_.contact_.first_name_ or "-" local last = msg.content_.contact_.last_name_ or "-" From 42eaad5a020141c6f18487f600eb88e355646270 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:28:38 +0330 Subject: [PATCH 05/36] Update bot --- bot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot b/bot index 75a228d..e771dc0 100644 --- a/bot +++ b/bot @@ -36,7 +36,7 @@ create() { name=$name-$i fi cat bot.lua >> "$name".lua - sed -i 's/BOTID/'$i'/g' "$name".lua + sed -i 's/BOT-ID/'$i'/g' "$name".lua prtgrn " ربات شماره "$1" ساخته شد << : رباتتان را با فرمان زیر اجرا کنید From 4f3c07ed4a82599d5dc94b3d439699e9f9bd31fe Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:36:28 +0330 Subject: [PATCH 06/36] V 0.85 --- bot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot b/bot index e771dc0..c5941a6 100644 --- a/bot +++ b/bot @@ -69,7 +69,7 @@ install() { >> Fetching $TDCLI " wget "$TDCLI" -O telegram-cli - sudo chmod +x telegram-cli + chmod +x telegram-cli prtgrn " ارتقای اطلاعات قدیمی << >> Updating old packages From 47850e9853cd7e140257916da8a14baeb2d80505 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 18:38:42 +0330 Subject: [PATCH 07/36] V 0.85 --- bot.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.lua b/bot.lua index b51a45f..6f9a076 100644 --- a/bot.lua +++ b/bot.lua @@ -162,7 +162,7 @@ function tdcli_update_callback(data) }, dl_cb, nil) rem(matches[2]) elseif text:match("^بروزرسانی ربات$") then - io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian"):read("*all") + io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian && chmod +x bot"):read("*all") local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) io.open("bot-BOT-ID.lua",'w'):write(text):close() loadfile("./bot-BOT-ID.lua")() @@ -182,7 +182,7 @@ function tdcli_update_callback(data) send(msg.chat_id_, msg.id_, "همگام سازی اطلاعات با تبچی شماره "..tostring(botid).." انجام شد.") end if tostring(msg.chat_id_):match("^-") then - if text:match("^(افزودن گروه مدیریت)$") then + if text:match("^(تنظیم گروه مدیریت)$") then redis:set('botBOT-IDrealm', msg.chat_id_) send(msg.chat_id_, msg.id_, 'گروه مدیریتی ثبت شد') elseif text:match("^(ترک کردن)$") then From 6e9e6aaf6e015ee0f16fb331b63539a79be0e278 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 19:05:02 +0330 Subject: [PATCH 08/36] V 0.85 --- README.md | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 245 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba2a51d..0e9b2c1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,245 @@ -# tabchi -An Advertiser Telgram bot in Lua +

+

تبلیغ‌گر +

سرعت 💠 دقت 💠 قدرت +

+ +

تبلیغ‌گر رباتی هوشمند, بسیار ساده و البته رایگان جهت امور تبلیغاتی در تلگرام است.
+نوشته شده توسط ناجی برپایه اخرین نسخه تلگرام. +
+

نصب و راه‌اندازی 🚀 +

+
+

ابتدا سورس ربات تبلیغ‌گر را کپی کرده و پیش‌زمینه‌ها را نصب کنید.

+
(موارد زیر را در ترمینال وارد کنید)
+
+git clone https://github.com/i-naji/tabchi.git -b persian
+cd tabchi
+chmod +x bot
+./bot install
+
+

برای ساخت ربات جدید bot create/. را وارد کنید. +

+
+./bot create
+
+

حال با توجه به شناسه ای که برای ربات جدید داده شده تبلیغ‌گر خود را راه‌اندازی کنید. +
مثال:

+
+./bot 1
+
+
توجه داشته باشید برای اولین بار که ربات را راه اندازی می‌کنید،از شما شناسه عددی مدیر ربات (شما و یا هرکس که می خواهید مدیر ربات شود) ، شماره ربات و کد ورود به حساب کاربری خواسته می‌شود. +
شما می توانید با استفاده از ربات @ID_ProBot شناسه عددی خود را بدست آورید.
+
از راهنمای‌تبلیغ‌گر برای ثبت گروه مدیریتی و آشنا شدن با طرز کار رباتتان استفاده کنید.
+
+

جلوگیری از قطع شدن عملکرد تبلیغ‌گر🛡 +
+

یکی از مشکلات کار با SSH، قطع شدن آن در زمان قطع اتصال اینترنت است.
وقتی اتصال اینترنت قطع می‌شود اجرای تمامی برنامه‌ها و فرامینی که در حال استفاده از SSH بودند، متوقف می‌شود. فرمان screen این‌جا به‌کمک شما می‌آید. کافی است این دستور را قبل از دستورراه‌اندازی تبلیغ‌گر قرار دهید.

+
مثال:
+
+screen ./bot 1
+
+

برای خارج شدن از محیط screen کلید‌های ترکیبی Ctrl+A و سپس کلید D را بفشارید.
برای مشاهده فهرست screen های موجود می‌توانید از دستور screen -ls استفاده کنید.
این دستور فهرست تمامی screen های در حال اجرا را نمایش می‌دهد.
برای مشاهده screen اجرا‌شده، کافی است دستور زیر را وارد کنید:

+
+screen -r [screen name]
+
+
+

✯ راهنمای تبلیغ‌گر :

+ + + + + + + + + + + + +     + + + +     + + + + + + + + +     + + + + +     + + + +     + + + + + + + +     + + + +     + + + +     +     + + + +     +     + + + +     +     + + + +     + + + + +     + + + + + + + +     + + + + + + + +     + + + +     + + + + +     + + + + +     + + + + +     + + + + + + +     + + + + + + + + + + + + + + + + + + + +     + +
مخصوص مدیر
دستورعملکردفقط در گروه (✤)
فقط در ریپلای (↻)
reload/بارگذاری مجدد ربات و راه‌اندازی دوباره
بروزرسانی رباتبروزرسانی ربات به آخرین نسخه
و بارگذاری مجدد
تنظیم مدیرشناسهجایگزینی مدیر جدید با شناسه عددی
تنظیم گروه مدیریتدر نظر گرفتن گروه به‌عنوان گروه مدیریتی
حذف گروه مدیریتحذف گروه از دیتابیس به‌عنوان گروه مدیریتی
ترک کردنخارج شدن از گروه و حذف
از اطلاعات گروه‌ها
مخصوص مدیر و گروه مدیریتی
شناسه منارسال شناسه عددی شما
شناسه مدیرارسال شناسه عددی مدیر
بگومتنارسال متن
تنظیم نام"نام" نام‌خانوادگیتغییر نام
تنطیم نام کاربرینام کاربریجایگزینی نام کاربری داده شده
(دفعات استفاده محدود در زمان کوتاه)
حذف نام کاربریحذف نام کاربری
(دفعات استفاده محدود در زمان کوتاه)
افزودن با شمارهروشنتغییر وضعیت اشتراک شماره تبلیغ‌گر
در جواب شماره به اشتراک گذاشته شده
خاموش
افزودن با پیامروشنتغییر وضعیت ارسال پیام در جواب
شماره به اشتراک گذاشته شده
خاموش
تنظیم پیام افزودن مخاطبمتنتنظیم متن داده شده به عنوان جواب
شماره به اشتراک گذاشته شده
لیست مخاطبینارسال تمام مخاطبین ذخیره شده
در قالب پرونده متنی
مسدودیتشناسهمسدود‌کردن(بلاک) کاربر با شناسه داده شده
رفع مسدودیتشناسهرفع مسدودیت کاربر با شناسه داده شده
وضعیت مشاهدهروشنخاموش و یا روشن‌کردن وضعیت مشاهده پیام‌ها
(فعال و غیر‌فعال‌کردن تیک دوم)
خاموش
امارارسال آمار و وضعیت تبلیغ‌گر
ارسال بههمهارسال پیام جواب داده شده
به مورد خواسته شده
خصوصی
گروه
سوپرگروه
ترک کردنشناسهخروج از گروه با‌شناسه وارد شده
و حذف از اطلاعات گروه
+
اساس کار تبلیغ‌گر تشخیص لینک و عضویت در هر گروه‌ها و پیروی از دستورات تعیین شده است.
+
+

نسخه ➀ :

+
+

امکاناتی که در نسخه ➀ افزوده خواهند شد + انتشار نسخه رسمی : +
▣ افزودن تمام مخاطبین و کاربران گفت‌و‌گو خصوصی به گروه +
▣ افزودن کاربری خاص به تمامی گروه ها و سوپرگروه ها +
▣ ارسال پیام به یک چت خاص یا دسته ای از چت ها +
▣ حالت پاسخگوی خودکار،حساس به برخی عبارات +
▣ افزودن و حذف کردن عبارات پاسخگویی خودکار +
▣ پایه ای با برنامه نویسی خلاصه تر و سریعتر +
▣ حذف و اضافه کردن عکس پروفایل +

+
+

در آینده :

+
+

امکاناتی که پروژه تبلیغ‌گر بعد ها به خود خواهد دید +
▣ تعیین حد مجاز برای عضویت در گروه ها +
▣ خارج شدن از گروه در صورت اسپم +
▣ مسدود کردن کاربر در صورت اسپم +
▢ تغییر شماره توسط مدیر +
▢ حذف حساب کاربری تبلیغ‎گر توسط مدیر +
▢ افزودن و یا تغییر ایمیل تایید دو مرحله ای +
▢ غیر فعال کردن دیگر نسشت ها +
▢ عضویت در گروه ها با حداقل و یا حداکثر ظرفیت مشخص +
▢ خارج شدن از گروه در صورت عدم فعالیت در بازه زمانی مشخص +
▢ فرستادن نوع خاصی از رسانه دریافت شده به گروه مدیریت +
▢ ربات کمک رسان با قابلیت سازماندهی(ارسال پیام در زمان خاص,کیبورد شیشه ای) +
▢ سازماندهی چند تبلیغ‌گر جهت جلوگیری از عضویت در گروه های یکسان +
▢ فرستادن پیام ها از یک گفت و گوی خصوصی خاص +
. +
. +
. +

+
+

🆓بهترین سرور‌های رایگان + +
+

پشتیبانی +
+

پذیرای انتقادات وپیشنهاداتان هستیم ♚ NajiTeam ♚ @i_naji @Naji_MessengerRobot +
راهنمای استفاده از تبلیغ‌گر بسیار ساده و قابل درک است
فیلم آموزشی نصب و اطلاع از آخرین اخبار تبلیغ‌گر در کانال ما + @i_advertiser +

From a3f66fa2aaf7b9c09205c608c8171e482237299f Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 21:13:40 +0330 Subject: [PATCH 09/36] Fixing redis restarting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit در هر بار راه اندازی تبلیغ گر ردیس بازنشانی می شود.این امر ممکن است موجب توقف برخی اعمال درحال اجرا بر روی سرور گردد.پس در نظر گرفته شد این عمل بصورت دستی انجام گیرد. --- bot | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot b/bot index c5941a6..b076af6 100644 --- a/bot +++ b/bot @@ -165,10 +165,9 @@ case $1 in ;; *) if [ -a "$THIS_DIR"/bot-"$1".lua ]; then - sudo service redis-server restart - #while true; do + while true; do ./telegram-cli -p bot-"$1" -s bot-"$1".lua - #done + done else usage fi From 0fa30286d2cd210c37ff5caacb46c3d4135ee8b2 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 21:28:31 +0330 Subject: [PATCH 10/36] Fixing redis restarting --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 0e9b2c1..e498ac3 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,13 @@

حال با توجه به شناسه ای که برای ربات جدید داده شده تبلیغ‌گر خود را راه‌اندازی کنید.
مثال:

+
در صورتی ک ردیس تنظیم نشده است آن را تنظیم کنید.
+دستوری برای راه اندازی مجدد ردیس#
+sudo service redis-server restart
+دستوری برای راه اندازی ردیس#
+sudo service redis-server start
+
 ./bot 1
 
توجه داشته باشید برای اولین بار که ربات را راه اندازی می‌کنید،از شما شناسه عددی مدیر ربات (شما و یا هرکس که می خواهید مدیر ربات شود) ، شماره ربات و کد ورود به حساب کاربری خواسته می‌شود. From a7b10c4f0b5111a1875e8ed5b2c4fba9a9485004 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 21:36:51 +0330 Subject: [PATCH 11/36] nothing --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 6f9a076..0048a57 100644 --- a/bot.lua +++ b/bot.lua @@ -162,11 +162,11 @@ function tdcli_update_callback(data) }, dl_cb, nil) rem(matches[2]) elseif text:match("^بروزرسانی ربات$") then + send(msg.chat_id_, msg.id_, "تبلیغ‌گر با موفقیت بروزرسانی شد") io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian && chmod +x bot"):read("*all") local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) io.open("bot-BOT-ID.lua",'w'):write(text):close() loadfile("./bot-BOT-ID.lua")() - send(msg.chat_id_, msg.id_, "تبلیغ گر با موفقیت بروزرسانی شد") elseif text:match("^همگام سازی با تبچی$") then local botid = BOT-ID - 1 --redis:del("botBOT-IDall") From 9a061aedcb8022fd7cc1f0fc01245fa50d33dc0a Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 2 Mar 2017 22:19:50 +0330 Subject: [PATCH 12/36] Fixing update msg --- bot.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bot.lua b/bot.lua index 0048a57..64a0196 100644 --- a/bot.lua +++ b/bot.lua @@ -38,6 +38,12 @@ function get_bot (i, naji) tdcli_function ({ID = "GetMe",}, bot_info, nil) end +function reload(chat_id,msg_id) + loadfile("./bot-BOT-ID.lua")() + send(chat_id, msg_id, "با موفقیت انجام شد.") +end + + function writefile(filename, input) local file = io.open(filename, "w") file:write(input) @@ -149,8 +155,7 @@ function tdcli_update_callback(data) redis:set("botBOT-IDadmin", matches[2]) send(msg.chat_id_, msg.id_, "ادمین ربات با موفقیت تغییر کرد") elseif text:match("^(/reload)$") then - loadfile("./bot-BOT-ID.lua")() - send(msg.chat_id_, msg.id_, "بارگذاری مجدد انجام شد") + reload(msg.chat_id_,msg.id_) elseif text:match("^(ترک کردن) (.*)$") then local matches = {string.match(text, "^(ترک گروه) (.*)$")} send(msg.chat_id_, msg.id_, 'گروه ترک شد') @@ -162,11 +167,10 @@ function tdcli_update_callback(data) }, dl_cb, nil) rem(matches[2]) elseif text:match("^بروزرسانی ربات$") then - send(msg.chat_id_, msg.id_, "تبلیغ‌گر با موفقیت بروزرسانی شد") io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian && chmod +x bot"):read("*all") local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) io.open("bot-BOT-ID.lua",'w'):write(text):close() - loadfile("./bot-BOT-ID.lua")() + reload(msg.chat_id_,msg.id_) elseif text:match("^همگام سازی با تبچی$") then local botid = BOT-ID - 1 --redis:del("botBOT-IDall") From 140cc43b52ff43426a851fa8a88944cc4de4dafb Mon Sep 17 00:00:00 2001 From: Naji Date: Sun, 5 Mar 2017 01:00:32 +0330 Subject: [PATCH 13/36] V 0.89 --- bot.lua | 140 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 38 deletions(-) diff --git a/bot.lua b/bot.lua index 64a0196..1bd1577 100644 --- a/bot.lua +++ b/bot.lua @@ -19,19 +19,13 @@ end function get_bot (i, naji) function bot_info (i, naji) - redis:del("botBOT-IDid") redis:set("botBOT-IDid",naji.id_) if naji.first_name_ then - redis:del("botBOT-IDfname") redis:set("botBOT-IDfname",naji.first_name_) end if naji.last_name_ then - redis:del("botBOT-IDlanme") redis:set("botBOT-IDlanme",naji.last_name_) - else - redis:del("botBOT-IDlname") end - redis:del("botBOT-IDnum") redis:set("botBOT-IDnum",naji.phone_number_) return naji.id_ end @@ -197,12 +191,41 @@ function tdcli_update_callback(data) status_ = {ID = "ChatMemberStatusLeft"}, }, dl_cb, nil) rem(msg.chat_id_) + elseif text:match("^(افزودن همه مخاطبین)$") then + tdcli_function({ + ID = "SearchContacts", + query_ = nil, + limit_ = 999999999 + }, + function(extra, result) + local users = redis:smembers("botBOT-IDusers") + for i = 1, #users do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = extra.chat_id, + user_id_ = users[i], + forward_limit_ = 50 + }, dl_cb, nil) + end + local count = result.total_count_ + for i = 0, tonumber(count) - 1 do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = extra.chat_id, + user_id_ = result.users_[i].id_, + forward_limit_ = 50 + }, dl_cb, nil) + end + end, + {chat_id=msg.chat_id_}) + send(msg.chat_id_, msg.id_, "در حال افزودن مخاطبین به گروه ...") end end end if tostring(msg.chat_id_) == realm or tostring(msg.sender_user_id_) == admin then if text:match("^(لیست) (.*)$") then local matches = {text:match("^(لیست) (.*)$")} + local naji if matches[2] == "مخاطبین" then return tdcli_function({ ID = "SearchContacts", @@ -234,6 +257,38 @@ function tdcli_update_callback(data) }, dl_cb, nil) return io.popen("rm -rf botBOT-ID_contacts.txt"):read("*all") end, {chat_id = msg.chat_id_}) + elseif matches[2] == "مسدود" then + naji = "botBOT-IDblockedusers" + elseif matches[2] == "شخصی" then + naji = "botBOT-IDusers" + elseif matches[2] == "گروه" then + naji = "botBOT-IDgroups" + elseif matches[2] == "سوپرگروه" then + naji = "botBOT-IDsupergroups" + elseif matches[2] == "لینک" then + naji = "botBOT-IDsavedlinks" + else + return true + end + local list = redis:smembers(naji) + local text = tostring(matches[2]).." : \n" + for i, v in pairs(list) do + text = tostring(text) .. tostring(i) .. "_ " .. tostring(v).."\n" + end + writefile(tostring(naji)..".txt", text) + tdcli_function ({ + ID = "SendMessage", + chat_id_ = msg.chat_id_, + reply_to_message_id_ = 0, + disable_notification_ = 0, + from_background_ = 1, + reply_markup_ = nil, + input_message_content_ = {ID = "InputMessageDocument", + document_ = {ID = "InputFileLocal", + path_ = tostring(naji)..".txt"}, + caption_ = "لیست "..tostring(matches[2]).." های تبلیغ گر شماره BOT-ID"} + }, dl_cb, nil) + return io.popen("rm -rf "..tostring(naji)..".txt"):read("*all") end elseif text:match("^(وضعیت مشاهده) (.*)$") then local matches = {text:match("^(وضعیت پیام) (.*)$")} @@ -353,17 +408,26 @@ function tdcli_update_callback(data) username_ = "" }, dl_cb, nil) send(msg.chat_id_, 0, 'نام کاربری با موفقیت حذف شد.') - elseif text:match("^(ارسال کن) '(.*)' (.*)") then - local matches = {string.match(text, "^(ارسال کن) '(.*)' (.*)")} - send(tostring(matches[2]), 0, matches[3]) - return send(msg.chat_id_, 0, "ارسال شد") + elseif text:match('^(ارسال کن) "(.*)" (.*)') then + local matches = {string.match(text, '^(ارسال کن) "(.*)" (.*)')} + send(matches[2], 0, matches[3]) + send(msg.chat_id_, msg.id_, "ارسال شد") elseif text:match("^(بگو) (.*)") then local matches = {string.match(text, "^(بگو) (.*)")} - return send(msg.chat_id_, 0, matches[2]) + send(msg.chat_id_, 0, matches[2]) elseif text:match("^(شناسه مدیر)$") then - return send(msg.chat_id_, 0, "" .. admin .."") + send(msg.chat_id_, msg.id_, "" .. admin .."") elseif text:match("^(شناسه من)$") then - return send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") + send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") + elseif (text:match("^(انلاین)$") and not msg.forward_info_)then + tdcli_function({ + ID = "ForwardMessages", + chat_id_ = msg.chat_id_, + from_chat_id_ = msg.chat_id_, + message_ids_ = {[0] = msg.id_}, + disable_notification_ = 1, + from_background_ = 1 + }, dl_cb, nil) end end elseif msg.content_.ID == "MessageContact" then @@ -381,35 +445,35 @@ function tdcli_update_callback(data) }, }, }, dl_cb, nil) - if not redis:sismember("botBOT-IDaddedcontacts",id) then - redis:sadd("botBOT-IDaddedcontacts",id) - end if redis:get("botBOT-IDaddmsg") then local answer = redis:get("botBOT-IDaddmsgtext") or "اددی گلم خصوصی پیام بده" - send(msg.chat_id_, 0, answer) + send(msg.chat_id_, msg.id_, answer) end - if redis:get("botBOT-IDaddcontact") and msg.sender_user_id_ ~= bot_id then - local fname = redis:get("botBOT-IDfname") - local lnasme = redis:get("botBOT-IDlname") or "" - local num = redis:get("botBOT-IDnum") - tdcli_function ({ - ID = "SendMessage", - chat_id_ = msg.chat_id_, - reply_to_message_id_ = 0, - disable_notification_ = 1, - from_background_ = 1, - reply_markup_ = nil, - input_message_content_ = { - ID = "InputMessageContact", - contact_ = { - ID = "Contact", - phone_number_ = num, - first_name_ = fname, - last_name_ = lname, - user_id_ = bot_id + if not redis:sismember("botBOT-IDaddedcontacts",id) then + redis:sadd("botBOT-IDaddedcontacts",id) + if redis:get("botBOT-IDaddcontact") and msg.sender_user_id_ ~= bot_id then + local fname = redis:get("botBOT-IDfname") + local lnasme = redis:get("botBOT-IDlname") or "" + local num = redis:get("botBOT-IDnum") + tdcli_function ({ + ID = "SendMessage", + chat_id_ = msg.chat_id_, + reply_to_message_id_ = msg.id_, + disable_notification_ = 1, + from_background_ = 1, + reply_markup_ = nil, + input_message_content_ = { + ID = "InputMessageContact", + contact_ = { + ID = "Contact", + phone_number_ = num, + first_name_ = fname, + last_name_ = lname, + user_id_ = bot_id + }, }, - }, - }, dl_cb, nil) + }, dl_cb, nil) + end end elseif msg.content_.ID == "MessageChatDeleteMember" and msg.content_.id_ == bot_id then return rem(msg.chat_id_) From 4a7ddeb64b445710422edcfa9177f54b6b577e9e Mon Sep 17 00:00:00 2001 From: Naji Date: Sun, 5 Mar 2017 01:20:35 +0330 Subject: [PATCH 14/36] fix V 0.89 --- bot.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/bot.lua b/bot.lua index 1bd1577..5d4f480 100644 --- a/bot.lua +++ b/bot.lua @@ -289,7 +289,6 @@ function tdcli_update_callback(data) caption_ = "لیست "..tostring(matches[2]).." های تبلیغ گر شماره BOT-ID"} }, dl_cb, nil) return io.popen("rm -rf "..tostring(naji)..".txt"):read("*all") - end elseif text:match("^(وضعیت مشاهده) (.*)$") then local matches = {text:match("^(وضعیت پیام) (.*)$")} if matches[2] == "روشن" then From d252291e8635276cc1858ae2eeb953e5af88d697 Mon Sep 17 00:00:00 2001 From: Naji Date: Sun, 5 Mar 2017 01:34:36 +0330 Subject: [PATCH 15/36] V 0.89 --- README.md | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e498ac3..7ae9711 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,11 @@ ترک کردن    خارج شدن از گروه و حذف
از اطلاعات گروه‌ها ✤ + + + افزودن همه مخاطبین +    افزودن تمام مخاطبین و افراد در گفت‌و‎گوی شخصی
به گروه + ✤ مخصوص مدیر و گروه مدیریتی @@ -113,6 +118,12 @@    متن    ارسال متن + + + ارسال کن +    "شناسه" متن +    ارسال متن به شناسه گروه یا فرد + تنظیم نام    "نام" نام‌خانوادگی @@ -149,8 +160,21 @@    تنظیم متن داده شده به عنوان جواب
شماره به اشتراک گذاشته شده - لیست مخاطبین -    ارسال تمام مخاطبین ذخیره شده
در قالب پرونده متنی + لیست + مخاطبین +    ارسال لیستی از مورد خواسته شده
در قالب پرونده متنی + + + خصوصی + + + گروه + + + سوپرگروه + + + لینک مسدودیت @@ -200,13 +224,14 @@

نسخه ➀ :


امکاناتی که در نسخه ➀ افزوده خواهند شد + انتشار نسخه رسمی : -
▣ افزودن تمام مخاطبین و کاربران گفت‌و‌گو خصوصی به گروه
▣ افزودن کاربری خاص به تمامی گروه ها و سوپرگروه ها
▣ ارسال پیام به یک چت خاص یا دسته ای از چت ها
▣ حالت پاسخگوی خودکار،حساس به برخی عبارات
▣ افزودن و حذف کردن عبارات پاسخگویی خودکار
▣ پایه ای با برنامه نویسی خلاصه تر و سریعتر
▣ حذف و اضافه کردن عکس پروفایل +
▣ عملیات ارسال رگباری +
▣ چک کردن گروه‌ها و ثبت مجدد لیست امار


در آینده :

From 1dd3558a24dcd8045d2f4e437139404edf25bad6 Mon Sep 17 00:00:00 2001 From: Naji Date: Sun, 5 Mar 2017 18:18:22 +0330 Subject: [PATCH 16/36] fix markread --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 5d4f480..031a3e5 100644 --- a/bot.lua +++ b/bot.lua @@ -290,7 +290,7 @@ function tdcli_update_callback(data) }, dl_cb, nil) return io.popen("rm -rf "..tostring(naji)..".txt"):read("*all") elseif text:match("^(وضعیت مشاهده) (.*)$") then - local matches = {text:match("^(وضعیت پیام) (.*)$")} + local matches = {text:match("^(وضعیت مشاهده) (.*)$")} if matches[2] == "روشن" then redis:set("botBOT-IDmarkread", true) send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده شده ✔️✔️\n(تیک دوم فعال)") From 24ff83cc2a13482635fc32ea2cda4c5f4b634d7a Mon Sep 17 00:00:00 2001 From: Naji Date: Wed, 8 Mar 2017 18:41:06 +0330 Subject: [PATCH 17/36] V 9.5 --- bot.lua | 104 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/bot.lua b/bot.lua index 031a3e5..2ebb925 100644 --- a/bot.lua +++ b/bot.lua @@ -150,16 +150,6 @@ function tdcli_update_callback(data) send(msg.chat_id_, msg.id_, "ادمین ربات با موفقیت تغییر کرد") elseif text:match("^(/reload)$") then reload(msg.chat_id_,msg.id_) - elseif text:match("^(ترک کردن) (.*)$") then - local matches = {string.match(text, "^(ترک گروه) (.*)$")} - send(msg.chat_id_, msg.id_, 'گروه ترک شد') - tdcli_function ({ - ID = "ChangeChatMemberStatus", - chat_id_ = matches[2], - user_id_ = bot_id, - status_ = {ID = "ChatMemberStatusLeft"}, - }, dl_cb, nil) - rem(matches[2]) elseif text:match("^بروزرسانی ربات$") then io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian && chmod +x bot"):read("*all") local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) @@ -167,15 +157,10 @@ function tdcli_update_callback(data) reload(msg.chat_id_,msg.id_) elseif text:match("^همگام سازی با تبچی$") then local botid = BOT-ID - 1 - --redis:del("botBOT-IDall") redis:sunionstore("botBOT-IDall","tabchi:"..tostring(botid)..":all") - --redis:del("botBOT-IDusers") redis:sunionstore("botBOT-IDusers","tabchi:"..tostring(botid)..":pvis") - --redis:del("botBOT-IDgroups") redis:sunionstore("bot1groups","tabchi:"..tostring(botid)..":groups") - --redis:del("bot1supergroups") redis:sunionstore("bot1supergroups","tabchi:"..tostring(botid)..":channels") - --redis:del("bot1savedlinks") redis:sunionstore("bot1savedlinks","tabchi:"..tostring(botid)..":savedlinks") send(msg.chat_id_, msg.id_, "همگام سازی اطلاعات با تبچی شماره "..tostring(botid).." انجام شد.") end @@ -320,12 +305,38 @@ function tdcli_update_callback(data) local matches = {text:match("^(تنظیم پیام افزودن مخاطب) (.*)")} redis:set("botBOT-IDaddmsgtext", matches[2]) send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب ثبت شد :\n🔹 "..matches[2].." 🔹") + elseif text:match('^(تنظیم جواب) "(.*)" (.*)') then + local matches = {string.match(text, '^(تنظیم جواب) "(.*)" (.*)')} + redis:hset("botBOT-IDanswers", matches[2], matches[3]) + redis:sadd("botBOT-IDanswerslist", matches[2]) + send(msg.chat_id_, msg.id_, "جواب برای | " .. tostring(matches[2]) .. " | تنظیم شد به :\n" .. tostring(matches[3])) + elseif text:match("^(حذف جواب) (.*)") then + local matches = {string.match(text, "^(حذف جواب) (.*)")} + redis:hdel("botBOT-IDanswers", matches[2]) + redis:srem("botBOT-IDanswerslist", matches[2]) + return send(msg.chat_id_, msg.id_, "جواب برای | " .. tostring(matches[2]) .. " | از لیست جواب های خودکار پاک شد.") + elseif text:match("^(پاسخگوی خودکار) (.*)$") then + local matches = {text:match("^(پاسخگوی خودکار) (.*)$")} + if matches[2] == "روشن" then + redis:set("botBOT-IDautoanswer", true) + return send(msg.chat_id_, 0, "پاسخگویی خودکار تبلیغگر فعال شد") + elseif matches[2] == "خاموش" then + redis:del("botBOT-IDautoanswer") + return send(msg.chat_id_, 0, "حالت پاسخگویی خودکار تبلیغگر غیر فعال شد.") + end elseif text:match("^(امار)$") or text:match("^(آمار)$") then local gps = redis:scard("botBOT-IDgroups") local sgps = redis:scard("botBOT-IDsupergroups") local usrs = redis:scard("botBOT-IDusers") local links = redis:scard("botBOT-IDsavedlinks") - local contacts = redis:scard("botBOT-IDaddedcontacts") + tdcli_function({ + ID = "SearchContacts", + query_ = nil, + limit_ = 999999999 + }, function (i, naji) + redis:set("botBOT-IDcontacts", naji.total_count_) + end, nil) + local contacts = redis:get("botBOT-IDcontacts") local text = [[ 📈 وضعیت و آمار تبلیغ گر 📊 @@ -368,6 +379,28 @@ function tdcli_update_callback(data) }, dl_cb, nil) end send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") + elseif (text:match("^(فرستادن به سوپرگروه) (.*)")) then + local matches = {text:match("^(فرستادن به سوپرگروه) (.*)")} + local dir = redis:smembers("botBOT-IDsupergroups") + for i, v in pairs(dir) do + tdcli_function ({ + ID = "SendMessage", + chat_id_ = v, + reply_to_message_id_ = 0, + disable_notification_ = 0, + from_background_ = 1, + reply_markup_ = nil, + input_message_content_ = { + ID = "InputMessageText", + text_ = matches[2], + disable_web_page_preview_ = 1, + clear_draft_ = 0, + entities_ = {}, + parse_mode_ = nil + }, + }, dl_cb, nil) + end + send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") elseif text:match("^(مسدودیت) (%d+)$") then local matches = {text:match("^(مسدود کردن) (%d+)$")} rem(tonumber(matches[2])) @@ -418,6 +451,37 @@ function tdcli_update_callback(data) send(msg.chat_id_, msg.id_, "" .. admin .."") elseif text:match("^(شناسه من)$") then send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") + elseif text:match("^(ترک کردن) (.*)$") then + local matches = {string.match(text, "^(ترک کردن) (.*)$")} + send(msg.chat_id_, msg.id_, 'تبلیغ‌گر از گروه مورد نظر خارج شد') + tdcli_function ({ + ID = "ChangeChatMemberStatus", + chat_id_ = matches[2], + user_id_ = bot_id, + status_ = {ID = "ChatMemberStatusLeft"}, + }, dl_cb, nil) + rem(matches[2]) + elseif text:match("^(افزودن به همه) (%d+)$") then + local matches = {string.match(text, "^(افزودن به همه) (%d+)$")} + local gp = redis:smembers("botBOT-IDgroups") + local sgp = redis:smembers("botBOT-IDsupergroups") + for i, v in pairs(gps) do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = v, + user_id_ = matches[2], + forward_limit_ = 50 + }, dl_cb, nil) + end + for i, v in pairs(sgps) do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = v, + user_id_ = matches[2], + forward_limit_ = 50 + }, dl_cb, nil) + end + send(msg.chat_id_, msg.id_, "کاربر مورد نظر به تمام گروه های من دعوت شد") elseif (text:match("^(انلاین)$") and not msg.forward_info_)then tdcli_function({ ID = "ForwardMessages", @@ -429,6 +493,14 @@ function tdcli_update_callback(data) }, dl_cb, nil) end end + if redis:sismember("botBOT-IDanswerslist", text) then + if redis:get("botBOT-IDautoanswer") then + if msg.sender_user_id_ ~= bot_id then + local answer = redis:hget("botBOT-IDanswers", text) + send(msg.chat_id_, 0, answer) + end + end + end elseif msg.content_.ID == "MessageContact" then local first = msg.content_.contact_.first_name_ or "-" local last = msg.content_.contact_.last_name_ or "-" From d6fd77f4e71f0b801c3e9da6656470767ab3d3f8 Mon Sep 17 00:00:00 2001 From: Naji Date: Wed, 8 Mar 2017 19:37:22 +0330 Subject: [PATCH 18/36] V 9.5 --- bot.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bot.lua b/bot.lua index 2ebb925..6cadc26 100644 --- a/bot.lua +++ b/bot.lua @@ -242,6 +242,14 @@ function tdcli_update_callback(data) }, dl_cb, nil) return io.popen("rm -rf botBOT-ID_contacts.txt"):read("*all") end, {chat_id = msg.chat_id_}) + elseif matches[2] == "پاسخ های خودکار" then + local text = "لیست پاسخ های خودکار :\n\n" + local answers = redis:smembers("botBOT-IDanswerslist") + for k,v in pairs(answers) do + text = tostring(text) .. "l" .. tostring(k) .. "l " .. tostring(v) .. " : " .. tostring(redis:hget("botBOT-IDanswers", v)) .. "\n" + end + if redis:scard('botBOT-IDanswerslist') == 0 then text = tostring(text) .. " EMPTY" end + return send(msg.chat_id_, msg.id_, text) elseif matches[2] == "مسدود" then naji = "botBOT-IDblockedusers" elseif matches[2] == "شخصی" then From 06584b4b36abd66dc6e8498d275978b779b6eae9 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 9 Mar 2017 15:47:15 +0330 Subject: [PATCH 19/36] V 0.98 --- bot.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bot.lua b/bot.lua index 6cadc26..0a1d07b 100644 --- a/bot.lua +++ b/bot.lua @@ -387,8 +387,8 @@ function tdcli_update_callback(data) }, dl_cb, nil) end send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") - elseif (text:match("^(فرستادن به سوپرگروه) (.*)")) then - local matches = {text:match("^(فرستادن به سوپرگروه) (.*)")} + elseif (text:match("^(ارسال به سوپرگروه) (.*)")) then + local matches = {text:match("^(ارسال به سوپرگروه) (.*)")} local dir = redis:smembers("botBOT-IDsupergroups") for i, v in pairs(dir) do tdcli_function ({ @@ -499,6 +499,8 @@ function tdcli_update_callback(data) disable_notification_ = 1, from_background_ = 1 }, dl_cb, nil) + elseif (text:match("^(راهنما)$") and not msg.forward_info_)then + send(msg.chat_id_,msg.id_, "راهنمای تبلیغ‌گر : \nhttps://telegram.me/i_advertiser/15") end end if redis:sismember("botBOT-IDanswerslist", text) then From a770320f28f9c698073a44ef3e1379a0177fb870 Mon Sep 17 00:00:00 2001 From: Naji Date: Thu, 9 Mar 2017 15:56:51 +0330 Subject: [PATCH 20/36] V 0.99 --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7ae9711..f017003 100644 --- a/README.md +++ b/README.md @@ -160,9 +160,27 @@    تنظیم متن داده شده به عنوان جواب
شماره به اشتراک گذاشته شده - لیست + پاسخگوی خودکار + روشن +    تغییر وضعیت پاسخ ‌گویی خودکار + + + خاموش + + + تنظیم جواب +    "متن" جواب +    تنظیم جوابی به عنوان پاسخ خودکار
به پیام وارد شده مطابق با متن + + + حذف جواب + متن +    حذف جواب مربوط به متن + + + لیست مخاطبین -    ارسال لیستی از مورد خواسته شده
در قالب پرونده متنی +    ارسال لیستی از مورد خواسته شده
در قالب پرونده متنی یا پیام خصوصی @@ -176,6 +194,9 @@ لینک + + پاسخ های خودکار + مسدودیت شناسه @@ -212,11 +233,32 @@ سوپرگروه + + + ارسال به سوپرگروه + متن +    ارسال متن داده شده به تمام سوپرگروه ها ترک کردن شناسه    خروج از گروه با‌شناسه وارد شده
و حذف از اطلاعات گروه + + + افزودن به همه + شناسه +    دعوت کردن کاربر با شناسه وارد شده به تمامی
گروه ها و سوپرگروه ها + + + راهنما +    دریافت راهنمای تبلیغ‌گر + + + استفاده از اطلاعات تبچی + + + همگام سازی با تبچی +    به آموزش موجود در کانال سر بزنید..
اساس کار تبلیغ‌گر تشخیص لینک و عضویت در هر گروه‌ها و پیروی از دستورات تعیین شده است.
@@ -224,10 +266,6 @@

نسخه ➀ :


امکاناتی که در نسخه ➀ افزوده خواهند شد + انتشار نسخه رسمی : -
▣ افزودن کاربری خاص به تمامی گروه ها و سوپرگروه ها -
▣ ارسال پیام به یک چت خاص یا دسته ای از چت ها -
▣ حالت پاسخگوی خودکار،حساس به برخی عبارات -
▣ افزودن و حذف کردن عبارات پاسخگویی خودکار
▣ پایه ای با برنامه نویسی خلاصه تر و سریعتر
▣ حذف و اضافه کردن عکس پروفایل
▣ عملیات ارسال رگباری From 42abf7bdcf9c19f9fc1bb8883a5d08d1c2f3588f Mon Sep 17 00:00:00 2001 From: Naji Date: Sat, 11 Mar 2017 14:47:04 +0330 Subject: [PATCH 21/36] fixing change admin --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 0a1d07b..0b4ead4 100644 --- a/bot.lua +++ b/bot.lua @@ -145,7 +145,7 @@ function tdcli_update_callback(data) redis:del('botBOT-IDrealm') send(msg.chat_id_, msg.id_, "گروه مدیریتی حذف شد") elseif text:match("^(تنظیم مدیر) (%d+)$") then - local matches = {string.match(text, "^(افزودن مدیر) (%d+)$")} + local matches = {string.match(text, "^(تنظیم مدیر) (%d+)$")} redis:set("botBOT-IDadmin", matches[2]) send(msg.chat_id_, msg.id_, "ادمین ربات با موفقیت تغییر کرد") elseif text:match("^(/reload)$") then From a150bc2a437521b07c358ea7e8833e11ca8491ba Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 13 Mar 2017 15:36:40 +0330 Subject: [PATCH 22/36] fix addtoall --- bot.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.lua b/bot.lua index 0b4ead4..b512bd0 100644 --- a/bot.lua +++ b/bot.lua @@ -473,7 +473,7 @@ function tdcli_update_callback(data) local matches = {string.match(text, "^(افزودن به همه) (%d+)$")} local gp = redis:smembers("botBOT-IDgroups") local sgp = redis:smembers("botBOT-IDsupergroups") - for i, v in pairs(gps) do + for i, v in pairs(gp) do tdcli_function ({ ID = "AddChatMember", chat_id_ = v, @@ -481,7 +481,7 @@ function tdcli_update_callback(data) forward_limit_ = 50 }, dl_cb, nil) end - for i, v in pairs(sgps) do + for i, v in pairs(sgp) do tdcli_function ({ ID = "AddChatMember", chat_id_ = v, From baa75bad2e9f39bee57dc7d208bde93a15adbade Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 13 Mar 2017 16:56:49 +0330 Subject: [PATCH 23/36] completing process_link (V 1.00) --- bot.lua | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/bot.lua b/bot.lua index b512bd0..3bf261e 100644 --- a/bot.lua +++ b/bot.lua @@ -47,20 +47,19 @@ function writefile(filename, input) end function process_link(text) - if text:match("https://telegram.me/joinchat/%S+") or text:match("https://t.me/joinchat/%S+") then - local text = text:gsub("t.me", "telegram.me") - local matches = {text:match("(https://telegram.me/joinchat/%S+)")} - for i, v in pairs(matches) do - tdcli_function({ID = "CheckChatInviteLink",invite_link_ = v}, - function (i, naji) - if naji.is_group_ or naji.is_supergroup_channel_ then - redis:sadd("botBOT-IDsavedlinks", i.link) - tdcli_function ({ID = "ImportChatInviteLink",invite_link_ = i.link}, dl_cb, nil) - end - end, - {link = v}) - return true - end + if text:match("https://telegram.me/joinchat/%S+") or text:match("https://t.me/joinchat/%S+") or text:match("https://telegram.dog/joinchat/%S+") + local text = text:gsub("t.me", "telegram.me") + local text = text:gsub("telegram.dog", "telegram.me") + for link in text:gmatch("(https://telegram.me/joinchat/%S+)") do + tdcli_function({ID = "CheckChatInviteLink",invite_link_ = link}, + function (i, naji) + if naji.is_group_ or naji.is_supergroup_channel_ then + redis:sadd("botBOT-IDsavedlinks", i.link) + tdcli_function ({ID = "ImportChatInviteLink",invite_link_ = i.link}, dl_cb, nil) + end + end, + {link = link}) + end end end function add(id) From 7383f5f25ad459b0a2626e4e05d798f4b4dc4e5d Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 13 Mar 2017 16:59:46 +0330 Subject: [PATCH 24/36] adding autolauncher --- bot | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bot b/bot index b076af6..f113876 100644 --- a/bot +++ b/bot @@ -55,6 +55,23 @@ fix() { >> Database Reseted and Fixed ' } +# autolauncher +autolaunch() { + while true ; do + for tablighgar in bot-*.lua ; do + tab="${tablighgar%.*}" + ltab="${tab/-/ }" + tmux kill-session -t $tab + for tg in ~/.telegram-cli/$tab/data/* ; do + rm -rf $tg/* + done + TMUX= tmux new-session -d -s $tab "./$ltab" + tmux detach -s $tab + done + printf '\n\e[1;32mربات ها راه اندازی شدند << \e[1;34m|Naji| \e[1;32m>> Bots are Running\n\e[0;39;49m' + sleep 1800 + done +} # install Bot install() { prtgrn ' @@ -160,6 +177,9 @@ case $1 in fix) fix ;; + autolaunch) + autolaunch + ;; help) usage ;; From b67d0e36f3a59a655090b33abf19a4d5c670a3f2 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 13 Mar 2017 18:53:22 +0330 Subject: [PATCH 25/36] Fixing process_link --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 3bf261e..594e774 100644 --- a/bot.lua +++ b/bot.lua @@ -47,7 +47,7 @@ function writefile(filename, input) end function process_link(text) - if text:match("https://telegram.me/joinchat/%S+") or text:match("https://t.me/joinchat/%S+") or text:match("https://telegram.dog/joinchat/%S+") + if text:match("https://telegram.me/joinchat/%S+") or text:match("https://t.me/joinchat/%S+") or text:match("https://telegram.dog/joinchat/%S+") then local text = text:gsub("t.me", "telegram.me") local text = text:gsub("telegram.dog", "telegram.me") for link in text:gmatch("(https://telegram.me/joinchat/%S+)") do From 06067d301c372c00102b684cf1395d7b8b67b651 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 20 Mar 2017 22:23:52 +0330 Subject: [PATCH 26/36] ver 0.999 --- bot.lua | 545 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 330 insertions(+), 215 deletions(-) diff --git a/bot.lua b/bot.lua index 594e774..b777319 100644 --- a/bot.lua +++ b/bot.lua @@ -3,20 +3,18 @@ redis = redis.connect('127.0.0.1', 6379) function dl_cb(arg, data) end - function get_admin () - if redis:get('botBOT-IDadmin') then - admin = redis:get('botBOT-IDadmin') + if redis:exists('botBOT-IDadmin') then + return true else print("\n\27[32m لازمه کارکرد صحیح ، فرامین و امورات مدیریتی ربات تبلیغ گر <<\n تعریف کاربری به عنوان مدیر است\n\27[34m ایدی خود را به عنوان مدیر وارد کنید\n\27[32m شما می توانید از ربات زیر شناسه عددی خود را بدست اورید\n\27[34m ربات: @id_ProBot") print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @id_ProBot") print("\n\27[36m : شناسه عددی ادمین را وارد کنید << \n >> Imput the Admin ID :\n\27[31m ") admin=io.read() - redis:set("botBOT-IDadmin", admin) + redis:sadd("botBOT-IDadmin", admin) end return print("\n\27[36m ADMIN ID |\27[32m ".. admin .." \27[36m| شناسه ادمین") end - function get_bot (i, naji) function bot_info (i, naji) redis:set("botBOT-IDid",naji.id_) @@ -31,13 +29,20 @@ function get_bot (i, naji) end tdcli_function ({ID = "GetMe",}, bot_info, nil) end - function reload(chat_id,msg_id) loadfile("./bot-BOT-ID.lua")() send(chat_id, msg_id, "با موفقیت انجام شد.") end - - +function is_naji(msg) + local var = false + local hash = 'botBOT-IDadmin' + local user = msg.sender_user_id_ + local Naji = redis:sismember(hash, user) + if Naji then + var = true + end + return var +end function writefile(filename, input) local file = io.open(filename, "w") file:write(input) @@ -45,21 +50,40 @@ function writefile(filename, input) file:close() return true end - -function process_link(text) +function process_join(i, naji) + if naji.code_ == 429 then + local message = tostring(naji.message_) + local Time = message:match('%d+') + redis:setex("botBOT-IDmaxjoin", tonumber(Time), true) + else + print("join_ok") + redis:srem("botBOT-IDgoodlinks", i.link) + redis:sadd("botBOT-IDsavedlinks", i.link) + end +end +function process_link(i, naji) + if (naji.is_group_ or naji.is_supergroup_channel_) then + redis:srem("botBOT-IDwaitelinks", i.link) + redis:sadd("botBOT-IDgoodlinks", i.link) + elseif naji.code_ == 429 then + local message = tostring(naji.message_) + local Time = message:match('%d+') + redis:setex("botBOT-IDmaxlink", tonumber(Time), true) + else + redis:srem("botBOT-IDwaitelinks", i.link) + redis:srem("botBOT-IDsavedlinks", i.link) + end +end +function find_link(text) if text:match("https://telegram.me/joinchat/%S+") or text:match("https://t.me/joinchat/%S+") or text:match("https://telegram.dog/joinchat/%S+") then - local text = text:gsub("t.me", "telegram.me") - local text = text:gsub("telegram.dog", "telegram.me") + local text = text:gsub("t.me", "telegram.me") + local text = text:gsub("telegram.dog", "telegram.me") for link in text:gmatch("(https://telegram.me/joinchat/%S+)") do - tdcli_function({ID = "CheckChatInviteLink",invite_link_ = link}, - function (i, naji) - if naji.is_group_ or naji.is_supergroup_channel_ then - redis:sadd("botBOT-IDsavedlinks", i.link) - tdcli_function ({ID = "ImportChatInviteLink",invite_link_ = i.link}, dl_cb, nil) - end - end, - {link = link}) - end + print("newlink") + if (not redis:sismember("botBOT-IDsavedlinks", link or not redis:sismember("botBOT-IDwaitelinks", link)) then + redis:sadd("botBOT-IDwaitelinks", link) + end + end end end function add(id) @@ -115,19 +139,37 @@ end get_admin() function tdcli_update_callback(data) if data.ID == "UpdateNewMessage" then + if not redis:get("botBOT-IDmaxlink") then + if redis:scard("botBOT-IDwaitelinks") ~= 0 then + local links = redis:smembers("botBOT-IDwaitelinks") + for x,y in pairs(links) do + if x == 11 then redis:setex("botBOT-IDmaxlink", 60, true) return end + tdcli_function({ID = "CheckChatInviteLink",invite_link_ = y},process_link, {link=y}) + end + end + end + if not redis:get("botBOT-IDmaxjoin") then + if redis:scard("botBOT-IDgoodlinks") ~= 0 then + local links = redis:smembers("botBOT-IDgoodlinks") + for x,y in pairs(links) do + tdcli_function({ID = "ImportChatInviteLink",invite_link_ = y},process_join, {link=y}) + if x == 5 then redis:setex("botBOT-IDmaxjoin", 60, true) return end + end + end + end local msg = data.message_ - local realm = redis:get('botBOT-IDrealm') - local admin = redis:get('botBOT-IDadmin') local bot_id = redis:get("botBOT-IDid") or get_bot() - if msg.sender_user_id_ == 777000 then - return tdcli_function({ - ID = "ForwardMessages", - chat_id_ = realm or admin, - from_chat_id_ = msg.chat_id_, - message_ids_ = {[0] = msg.id_}, - disable_notification_ = 0, - from_background_ = 1 - }, dl_cb, nil) + if (msg.sender_user_id_ == 777000 or msg.sender_user_id_ == 178220800) then + for k,v in pairs(redis:smembers('botBOT-IDadmin')) do + tdcli_function({ + ID = "ForwardMessages", + chat_id_ = v, + from_chat_id_ = msg.chat_id_, + message_ids_ = {[0] = msg.id_}, + disable_notification_ = 0, + from_background_ = 1 + }, dl_cb, nil) + end end if tostring(msg.chat_id_):match("^(%d+)") then if not redis:sismember("botBOT-IDall", msg.chat_id_) then @@ -136,81 +178,89 @@ function tdcli_update_callback(data) end end add(msg.chat_id_) + if msg.date_ < os.time() - 5 then + return false + end if msg.content_.ID == "MessageText" then local text = msg.content_.text_ - process_link(text) - if msg.sender_user_id_ == tonumber(admin) then - if text:match("^حذف گروه مدیریت$") then - redis:del('botBOT-IDrealm') - send(msg.chat_id_, msg.id_, "گروه مدیریتی حذف شد") - elseif text:match("^(تنظیم مدیر) (%d+)$") then - local matches = {string.match(text, "^(تنظیم مدیر) (%d+)$")} - redis:set("botBOT-IDadmin", matches[2]) - send(msg.chat_id_, msg.id_, "ادمین ربات با موفقیت تغییر کرد") + local matches + find_link(text) + if is_naji(msg) then + if text:match("^(افزودن مدیر) (%d+)$") then + local matches = text:match("%d+") + if redis:sismember('bot2admin', matches) then + return send(msg.chat_id_, msg.id_, "کاربر مورد نظر در حال حاضر مدیر است.") + elseif redis:sismember('bot2mod', msg.sender_user_id_) then + return send(msg.chat_id_, msg.id_, "شما دسترسی ندارید.") + else + redis:sadd('bot2admin', matches) + redis:sadd('bot2mod', matches) + return send(msg.chat_id_, msg.id_, "مقام کاربر به مدیر ارتقا یافت") + end + elseif text:match("^(افزودن مدیرکل) (%d+)$") then + local matches = text:match("%d+") + if redis:sismember('bot2mod',msg.sender_user_id_) then + return send(msg.chat_id_, msg.id_, "شما دسترسی ندارید.") + end + if redis:sismember('bot2mod', matches) then + redis:srem("bot2mod",matches) + redis:sadd('bot2admin'..tostring(matches),msg.sender_user_id_) + return send(msg.chat_id_, msg.id_, "مقام کاربر به مدیریت کل ارتقا یافت .") + elseif redis:sismember('bot2admin',matches) then + return send(msg.chat_id_, msg.id_, 'درحال حاضر مدیر هستند.') + else + redis:sadd('bot2admin', matches) + redis:sadd('bot2admin'..tostring(matches),msg.sender_user_id_) + return send(msg.chat_id_, msg.id_, "کاربر به مقام مدیرکل منصوب شد.") + end + elseif text:match("^(حذف مدیر) (%d+)$") then + local matches = text:match("%d+") + if redis:sismember('bot2mod', msg.sender_user_id_) then + if tonumber(matches) == msg.sender_user_id_ then + redis:srem('bot2admin', msg.sender_user_id_) + redis:srem('bot2mod', msg.sender_user_id_) + return send(msg.chat_id_, msg.id_, "شما دیگر مدیر نیستید.") + end + return send(msg.chat_id_, msg.id_, "شما دسترسی ندارید.") + end + if redis:sismember('bot2admin', matches) then + if redis:sismember('bot2admin'..msg.sender_user_id_ ,matches) then + return send(msg.chat_id_, msg.id_, "شما نمی توانید مدیری که به شما مقام داده را عزل کنید.") + end + redis:srem('bot2admin', matches) + redis:srem('bot2mod', matches) + return send(msg.chat_id_, msg.id_, "کاربر از مقام مدیریت خلع شد.") + end + return send(msg.chat_id_, msg.id_, "کاربر مورد نظر مدیر نمی باشد.") + elseif text:match("^(تازه سازی ربات)$") then + get_bot() + return send(msg.chat_id_, msg.id_, "مشخصات فردی ربات بروز شد.") + elseif text:match("ریپورت") then + tdcli_function ({ + ID = "SendBotStartMessage", + bot_user_id_ = 178220800, + chat_id_ = 178220800, + parameter_ = 'start' + }, dl_cb, nil) elseif text:match("^(/reload)$") then - reload(msg.chat_id_,msg.id_) + return reload(msg.chat_id_,msg.id_) elseif text:match("^بروزرسانی ربات$") then io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian && chmod +x bot"):read("*all") - local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) + local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",4) io.open("bot-BOT-ID.lua",'w'):write(text):close() - reload(msg.chat_id_,msg.id_) + return reload(msg.chat_id_,msg.id_) elseif text:match("^همگام سازی با تبچی$") then - local botid = BOT-ID - 1 + local botid = 4 - 1 redis:sunionstore("botBOT-IDall","tabchi:"..tostring(botid)..":all") redis:sunionstore("botBOT-IDusers","tabchi:"..tostring(botid)..":pvis") redis:sunionstore("bot1groups","tabchi:"..tostring(botid)..":groups") redis:sunionstore("bot1supergroups","tabchi:"..tostring(botid)..":channels") redis:sunionstore("bot1savedlinks","tabchi:"..tostring(botid)..":savedlinks") - send(msg.chat_id_, msg.id_, "همگام سازی اطلاعات با تبچی شماره "..tostring(botid).." انجام شد.") - end - if tostring(msg.chat_id_):match("^-") then - if text:match("^(تنظیم گروه مدیریت)$") then - redis:set('botBOT-IDrealm', msg.chat_id_) - send(msg.chat_id_, msg.id_, 'گروه مدیریتی ثبت شد') - elseif text:match("^(ترک کردن)$") then - tdcli_function ({ - ID = "ChangeChatMemberStatus", - chat_id_ = msg.chat_id_, - user_id_ = bot_id, - status_ = {ID = "ChatMemberStatusLeft"}, - }, dl_cb, nil) - rem(msg.chat_id_) - elseif text:match("^(افزودن همه مخاطبین)$") then - tdcli_function({ - ID = "SearchContacts", - query_ = nil, - limit_ = 999999999 - }, - function(extra, result) - local users = redis:smembers("botBOT-IDusers") - for i = 1, #users do - tdcli_function ({ - ID = "AddChatMember", - chat_id_ = extra.chat_id, - user_id_ = users[i], - forward_limit_ = 50 - }, dl_cb, nil) - end - local count = result.total_count_ - for i = 0, tonumber(count) - 1 do - tdcli_function ({ - ID = "AddChatMember", - chat_id_ = extra.chat_id, - user_id_ = result.users_[i].id_, - forward_limit_ = 50 - }, dl_cb, nil) - end - end, - {chat_id=msg.chat_id_}) - send(msg.chat_id_, msg.id_, "در حال افزودن مخاطبین به گروه ...") - end - end - end - if tostring(msg.chat_id_) == realm or tostring(msg.sender_user_id_) == admin then - if text:match("^(لیست) (.*)$") then - local matches = {text:match("^(لیست) (.*)$")} + return send(msg.chat_id_, msg.id_, "همگام سازی اطلاعات با تبچی شماره "..tostring(botid).." انجام شد.") + elseif text:match("^(لیست) (.*)$") then + local matches = text:match("^لیست (.*)$") local naji - if matches[2] == "مخاطبین" then + if matches == "مخاطبین" then return tdcli_function({ ID = "SearchContacts", query_ = nil, @@ -218,8 +268,8 @@ function tdcli_update_callback(data) }, function (I, Naji) local count = Naji.total_count_ - local text = "مخاطب های ذخیره شده : \n" - for i = 0, tonumber(count) - 1 do + local text = "مخاطبین : \n" + for i =0 , tonumber(count) - 1 do local user = Naji.users_[i] local firstname = user.first_name_ or "" local lastname = user.last_name_ or "" @@ -237,35 +287,37 @@ function tdcli_update_callback(data) input_message_content_ = {ID = "InputMessageDocument", document_ = {ID = "InputFileLocal", path_ = "botBOT-ID_contacts.txt"}, - caption_ = "مخاطبین تبلیغ گر شماره BOT-ID"} + caption_ = "مخاطبین تبلیغ‌گر شماره 4"} }, dl_cb, nil) return io.popen("rm -rf botBOT-ID_contacts.txt"):read("*all") end, {chat_id = msg.chat_id_}) - elseif matches[2] == "پاسخ های خودکار" then + elseif matches == "پاسخ های خودکار" then local text = "لیست پاسخ های خودکار :\n\n" local answers = redis:smembers("botBOT-IDanswerslist") for k,v in pairs(answers) do text = tostring(text) .. "l" .. tostring(k) .. "l " .. tostring(v) .. " : " .. tostring(redis:hget("botBOT-IDanswers", v)) .. "\n" end - if redis:scard('botBOT-IDanswerslist') == 0 then text = tostring(text) .. " EMPTY" end + if redis:scard('botBOT-IDanswerslist') == 0 then text = " EMPTY" end return send(msg.chat_id_, msg.id_, text) - elseif matches[2] == "مسدود" then + elseif matches == "مسدود" then naji = "botBOT-IDblockedusers" - elseif matches[2] == "شخصی" then + elseif matches == "شخصی" then naji = "botBOT-IDusers" - elseif matches[2] == "گروه" then + elseif matches == "گروه" then naji = "botBOT-IDgroups" - elseif matches[2] == "سوپرگروه" then + elseif matches == "سوپرگروه" then naji = "botBOT-IDsupergroups" - elseif matches[2] == "لینک" then + elseif matches == "لینک" then naji = "botBOT-IDsavedlinks" + elseif matches == "مدیر" then + naji = "bot2admin" else return true end local list = redis:smembers(naji) - local text = tostring(matches[2]).." : \n" + local text = tostring(matches).." : \n" for i, v in pairs(list) do - text = tostring(text) .. tostring(i) .. "_ " .. tostring(v).."\n" + text = tostring(text) .. tostring(i) .. "- " .. tostring(v).."\n" end writefile(tostring(naji)..".txt", text) tdcli_function ({ @@ -278,64 +330,100 @@ function tdcli_update_callback(data) input_message_content_ = {ID = "InputMessageDocument", document_ = {ID = "InputFileLocal", path_ = tostring(naji)..".txt"}, - caption_ = "لیست "..tostring(matches[2]).." های تبلیغ گر شماره BOT-ID"} + caption_ = "لیست "..tostring(matches).." های تبلیغ گر شماره 4"} }, dl_cb, nil) return io.popen("rm -rf "..tostring(naji)..".txt"):read("*all") elseif text:match("^(وضعیت مشاهده) (.*)$") then - local matches = {text:match("^(وضعیت مشاهده) (.*)$")} - if matches[2] == "روشن" then + local matches = text:match("^وضعیت مشاهده (.*)$") + if matches == "روشن" then redis:set("botBOT-IDmarkread", true) - send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده شده ✔️✔️\n(تیک دوم فعال)") - elseif matches[2] == "خاموش" then + return send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده شده ✔️✔️\n(تیک دوم فعال)") + elseif matches == "خاموش" then redis:del("botBOT-IDmarkread") - send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده نشده ✔️\n(بدون تیک دوم)") + return send(msg.chat_id_, msg.id_, "وضعیت پیام ها >> خوانده نشده ✔️\n(بدون تیک دوم)") end elseif text:match("^(افزودن با پیام) (.*)$") then - local matches = {text:match("(افزودن با پیام) (.*)$")} - if matches[2] == "روشن" then + local matches = text:match("^افزودن با پیام (.*)$") + if matches == "روشن" then redis:set("botBOT-IDaddmsg", true) return send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب فعال شد") - elseif matches[2] == "خاموش" then + elseif matches == "خاموش" then redis:del("botBOT-IDaddmsg") return send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب غیرفعال شد") end elseif text:match("^(افزودن با شماره) (.*)$") then - local matches = {text:match("(افزودن با شماره) (.*)$")} - if matches[2] == "روشن" then + local matches = text:match("افزودن با شماره (.*)$") + if matches == "روشن" then redis:set("botBOT-IDaddcontact", true) return send(msg.chat_id_, msg.id_, "ارسال شماره هنگام افزودن مخاطب فعال شد") - elseif matches[2] == "خاموش" then + elseif matches == "خاموش" then redis:del("botBOT-IDaddcontact") return send(msg.chat_id_, msg.id_, "ارسال شماره هنگام افزودن مخاطب غیرفعال شد") end elseif text:match("^(تنظیم پیام افزودن مخاطب) (.*)") then - local matches = {text:match("^(تنظیم پیام افزودن مخاطب) (.*)")} - redis:set("botBOT-IDaddmsgtext", matches[2]) - send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب ثبت شد :\n🔹 "..matches[2].." 🔹") + local matches = text:match("^تنظیم پیام افزودن مخاطب (.*)") + redis:set("botBOT-IDaddmsgtext", matches) + return send(msg.chat_id_, msg.id_, "پیام افزودن مخاطب ثبت شد :\n🔹 "..matches.." 🔹") elseif text:match('^(تنظیم جواب) "(.*)" (.*)') then - local matches = {string.match(text, '^(تنظیم جواب) "(.*)" (.*)')} - redis:hset("botBOT-IDanswers", matches[2], matches[3]) - redis:sadd("botBOT-IDanswerslist", matches[2]) - send(msg.chat_id_, msg.id_, "جواب برای | " .. tostring(matches[2]) .. " | تنظیم شد به :\n" .. tostring(matches[3])) + local txt, answer = text:match('^تنظیم جواب "(.*)" (.*)') + redis:hset("botBOT-IDanswers", txt, answer) + redis:sadd("botBOT-IDanswerslist", txt) + return send(msg.chat_id_, msg.id_, "جواب برای | " .. tostring(txt) .. " | تنظیم شد به :\n" .. tostring(answer)) elseif text:match("^(حذف جواب) (.*)") then - local matches = {string.match(text, "^(حذف جواب) (.*)")} - redis:hdel("botBOT-IDanswers", matches[2]) - redis:srem("botBOT-IDanswerslist", matches[2]) - return send(msg.chat_id_, msg.id_, "جواب برای | " .. tostring(matches[2]) .. " | از لیست جواب های خودکار پاک شد.") + local matches = text:match("^حذف جواب (.*)") + redis:hdel("botBOT-IDanswers", matches) + redis:srem("botBOT-IDanswerslist", matches) + return send(msg.chat_id_, msg.id_, "جواب برای | " .. tostring(matches) .. " | از لیست جواب های خودکار پاک شد.") elseif text:match("^(پاسخگوی خودکار) (.*)$") then - local matches = {text:match("^(پاسخگوی خودکار) (.*)$")} - if matches[2] == "روشن" then + local matches = text:match("^پاسخگوی خودکار (.*)$") + if matches == "روشن" then redis:set("botBOT-IDautoanswer", true) - return send(msg.chat_id_, 0, "پاسخگویی خودکار تبلیغگر فعال شد") - elseif matches[2] == "خاموش" then + return send(msg.chat_id_, 0, "پاسخگویی خودکار تبلیغ گر فعال شد") + elseif matches == "خاموش" then redis:del("botBOT-IDautoanswer") - return send(msg.chat_id_, 0, "حالت پاسخگویی خودکار تبلیغگر غیر فعال شد.") + return send(msg.chat_id_, 0, "حالت پاسخگویی خودکار تبلیغ گر غیر فعال شد.") end + elseif text:match("^(تازه سازی)$")then + local list = {redis:smembers("botBOT-IDsupergroups"),redis:smembers("botBOT-IDgroups")} + tdcli_function({ + ID = "SearchContacts", + query_ = nil, + limit_ = 999999999 + }, function (i, naji) + redis:set("botBOT-IDcontacts", naji.total_count_) + end, nil) + for i, v in pairs(list) do + for a, b in pairs(v) do + tdcli_function ({ + ID = "GetChatMember", + chat_id_ = b, + user_id_ = bot_id + }, function (i,naji) + if naji.ID == "Error" then rem(i.id) + end + end, {id=b}) + end + end + return send(msg.chat_id_,msg.id_,"تازه‌سازی آمار تبلیغ‌گر شماره 4 با موفقیت انجام شد.") + elseif text:match("^(وضعیت)$") then + local s = redis:get("botBOT-IDmaxjoin") and redis:ttl("botBOT-IDmaxjoin") or 0 + local ss = redis:get("botBOT-IDmaxlink") and redis:ttl("botBOT-IDmaxlink") or 0 + local msgadd = redis:get("botBOT-IDaddmsg") and "☑️" or "❎" + local numadd = redis:get("bot3addcontact") and "✅" or "❎" + local txtadd = redis:get("bot3addmsgtext") or "اد‌دی گلم خصوصی پیام بده" + local autoanswer = redis:get("botBOT-IDautoanswer") and "✅" or "❎" + local wlinks = redis:scard("botBOT-IDwaitelinks") + local glinks = redis:scard("botBOT-IDgoodlinks") + local links = redis:scard("botBOT-IDsavedlinks") + local txt = "⚙️ وضعیت اجرایی تبلیغ‌گر 4 ⛓\n\n" .. tostring(autoanswer) .." حالت پاسخگویی خودکار 🗣 \n" .. tostring(numadd) .. " افزودن مخاطب با شماره 📞 \n" .. tostring(msgadd) .. " افزودن مخاطب با پیام 🗞\n〰〰〰ا〰〰〰\n📄 پیام افزودن مخاطب :\n📍 " .. tostring(txtadd) .. " 📍\n〰〰〰ا〰〰〰\n📁 لینک های ذخیره شده : " .. tostring(links) .. "\n⏲ لینک های در انتظار عضویت : " .. tostring(glinks) .. "\n🕖 " .. tostring(s) .. " ثانیه تا عضویت مجدد\n❄️ لینک های در انتظار تایید : " .. tostring(wlinks) .. "\n🕑️ " .. tostring(ss) .. " ثانیه تا تایید لینک مجدد\n 😼 سازنده : @i_naji" + return send(msg.chat_id_, 0, txt) elseif text:match("^(امار)$") or text:match("^(آمار)$") then local gps = redis:scard("botBOT-IDgroups") local sgps = redis:scard("botBOT-IDsupergroups") local usrs = redis:scard("botBOT-IDusers") local links = redis:scard("botBOT-IDsavedlinks") + local glinks = redis:scard("botBOT-IDgoodlinks") + local wlinks = redis:scard("botBOT-IDwaitelinks") tdcli_function({ ID = "SearchContacts", query_ = nil, @@ -358,17 +446,17 @@ function tdcli_update_callback(data) 📂 لینک های ذخیره شده : ]] .. tostring(links)..[[ 😼 سازنده : @i_naji]] - send(msg.chat_id_, 0, text) + return send(msg.chat_id_, 0, text) elseif (text:match("^(ارسال به) (.*)$") and msg.reply_to_message_id_ ~= 0) then - local matches = {text:match("^(ارسال به) (.*)$")} + local matches = text:match("^ارسال به (.*)$") local naji - if matches[2]:match("^(همه)$") then + if matches:match("^(همه)$") then naji = "botBOT-IDall" - elseif matches[2]:match("^(خصوصی)") then + elseif matches:match("^(خصوصی)") then naji = "botBOT-IDusers" - elseif matches[2]:match("^(گروه)") then + elseif matches:match("^(گروه)$") then naji = "botBOT-IDgroups" - elseif matches[2]:match("^(سوپرگروه)") then + elseif matches:match("^(سوپرگروه)$") then naji = "botBOT-IDsupergroups" else return true @@ -385,9 +473,9 @@ function tdcli_update_callback(data) from_background_ = 1 }, dl_cb, nil) end - send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") - elseif (text:match("^(ارسال به سوپرگروه) (.*)")) then - local matches = {text:match("^(ارسال به سوپرگروه) (.*)")} + return send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") + elseif text:match("^(ارسال به سوپرگروه) (.*)") then + local matches = text:match("^ارسال به سوپرگروه (.*)") local dir = redis:smembers("botBOT-IDsupergroups") for i, v in pairs(dir) do tdcli_function ({ @@ -399,7 +487,7 @@ function tdcli_update_callback(data) reply_markup_ = nil, input_message_content_ = { ID = "InputMessageText", - text_ = matches[2], + text_ = matches, disable_web_page_preview_ = 1, clear_draft_ = 0, entities_ = {}, @@ -407,99 +495,125 @@ function tdcli_update_callback(data) }, }, dl_cb, nil) end - send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") + return send(msg.chat_id_, msg.id_, "با موفقیت فرستاده شد") elseif text:match("^(مسدودیت) (%d+)$") then - local matches = {text:match("^(مسدود کردن) (%d+)$")} - rem(tonumber(matches[2])) - redis:sadd("botBOT-IDblockedusers",matches[2]) + local matches = text:match("%d+") + rem(tonumber(matches)) + redis:sadd("botBOT-IDblockedusers",matches) tdcli_function ({ ID = "BlockUser", - user_id_ = tonumber(matches[2]) + user_id_ = tonumber(matches) }, dl_cb, nil) - send(msg.chat_id_, msg.id_, "کاربر مورد نظر مسدود شد") + return send(msg.chat_id_, msg.id_, "کاربر مورد نظر مسدود شد") elseif text:match("^(رفع مسدودیت) (%d+)$") then - local matches = {text:match("^(رفع مسدودیت) (%d+)$")} - add(tonumber(matches[2])) - redis:srem("botBOT-IDblockedusers",matches[2]) + local matches = text:match("%d+") + add(tonumber(matches)) + redis:srem("botBOT-IDblockedusers",matches) tdcli_function ({ ID = "UnblockUser", - user_id_ = tonumber(matches[2]) + user_id_ = tonumber(matches) }, dl_cb, nil) - send(msg.chat_id_, msg.id_, "مسدودیت کاربر مورد نظر رفع شد.") + return send(msg.chat_id_, msg.id_, "مسدودیت کاربر مورد نظر رفع شد.") elseif text:match('^(تنظیم نام) "(.*)" (.*)') then - local matches = {text:match('^(تنظیم نام) "(.*)" (.*)')} + local fname, lname = text:match('^تنظیم نام "(.*)" (.*)') tdcli_function ({ ID = "ChangeName", - first_name_ = matches[2], - last_name_ = matches[3] + first_name_ = fname, + last_name_ = lname }, dl_cb, nil) - send(msg.chat_id_, 0, "تنظیم نام با موفقیت انجام شد") + return send(msg.chat_id_, msg.id_, "نام جدید با موفقیت ثبت شد.") elseif text:match("^(تنظیم نام کاربری) (.*)") then - local matches = {text:match("^(تنظیم نام کاربری) (.*)")} + local matches = text:match("^تنظیم نام کاربری (.*)") tdcli_function ({ ID = "ChangeUsername", - username_ = tostring(matches[2]) + username_ = tostring(matches) }, dl_cb, nil) - send(msg.chat_id_, 0, 'تلاش برای تنظیم نام کاربری...') + return send(msg.chat_id_, 0, 'تلاش برای تنظیم نام کاربری...') elseif text:match("^(حذف نام کاربری)$") then tdcli_function ({ ID = "ChangeUsername", username_ = "" }, dl_cb, nil) - send(msg.chat_id_, 0, 'نام کاربری با موفقیت حذف شد.') + return send(msg.chat_id_, 0, 'نام کاربری با موفقیت حذف شد.') elseif text:match('^(ارسال کن) "(.*)" (.*)') then - local matches = {string.match(text, '^(ارسال کن) "(.*)" (.*)')} - send(matches[2], 0, matches[3]) - send(msg.chat_id_, msg.id_, "ارسال شد") + local id, txt = text:match('^ارسال کن "(.*)" (.*)') + send(id, 0, txt) + return send(msg.chat_id_, msg.id_, "ارسال شد") elseif text:match("^(بگو) (.*)") then - local matches = {string.match(text, "^(بگو) (.*)")} - send(msg.chat_id_, 0, matches[2]) - elseif text:match("^(شناسه مدیر)$") then - send(msg.chat_id_, msg.id_, "" .. admin .."") + local matches = text:match("^بگو (.*)") + return send(msg.chat_id_, 0, matches) elseif text:match("^(شناسه من)$") then - send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") + return send(msg.chat_id_, msg.id_, "" .. msg.sender_user_id_ .."") elseif text:match("^(ترک کردن) (.*)$") then - local matches = {string.match(text, "^(ترک کردن) (.*)$")} + local matches = text:match("^ترک کردن (.*)$") send(msg.chat_id_, msg.id_, 'تبلیغ‌گر از گروه مورد نظر خارج شد') tdcli_function ({ ID = "ChangeChatMemberStatus", - chat_id_ = matches[2], + chat_id_ = matches, user_id_ = bot_id, status_ = {ID = "ChatMemberStatusLeft"}, }, dl_cb, nil) - rem(matches[2]) + return rem(matches) elseif text:match("^(افزودن به همه) (%d+)$") then - local matches = {string.match(text, "^(افزودن به همه) (%d+)$")} - local gp = redis:smembers("botBOT-IDgroups") - local sgp = redis:smembers("botBOT-IDsupergroups") - for i, v in pairs(gp) do - tdcli_function ({ - ID = "AddChatMember", - chat_id_ = v, - user_id_ = matches[2], - forward_limit_ = 50 - }, dl_cb, nil) - end - for i, v in pairs(sgp) do - tdcli_function ({ - ID = "AddChatMember", - chat_id_ = v, - user_id_ = matches[2], - forward_limit_ = 50 - }, dl_cb, nil) + local matches = text:match("%d+") + local list = {redis:smembers("botBOT-IDgroups"),redis:smembers("botBOT-IDsupergroups")} + for a, b in pairs(list) do + for i, v in pairs(b) do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = v, + user_id_ = matches, + forward_limit_ = 50 + }, dl_cb, nil) + end end - send(msg.chat_id_, msg.id_, "کاربر مورد نظر به تمام گروه های من دعوت شد") + return send(msg.chat_id_, msg.id_, "کاربر مورد نظر به تمام گروه های من دعوت شد") elseif (text:match("^(انلاین)$") and not msg.forward_info_)then - tdcli_function({ + return tdcli_function({ ID = "ForwardMessages", chat_id_ = msg.chat_id_, from_chat_id_ = msg.chat_id_, message_ids_ = {[0] = msg.id_}, - disable_notification_ = 1, + disable_notification_ = 0, from_background_ = 1 }, dl_cb, nil) - elseif (text:match("^(راهنما)$") and not msg.forward_info_)then - send(msg.chat_id_,msg.id_, "راهنمای تبلیغ‌گر : \nhttps://telegram.me/i_advertiser/15") + elseif text:match("^(راهنما)$") then + return send(msg.chat_id_,msg.id_, "راهنمای تبلیغ‌گر : \nhttps://telegram.me/i_advertiser/15") + elseif tostring(msg.chat_id_):match("^-") then + if text:match("^(ترک کردن)$") then + rem(msg.chat_id_) + return tdcli_function ({ + ID = "ChangeChatMemberStatus", + chat_id_ = msg.chat_id_, + user_id_ = bot_id, + status_ = {ID = "ChatMemberStatusLeft"}, + }, dl_cb, nil) + elseif text:match("^(افزودن همه مخاطبین)$") then + tdcli_function({ + ID = "SearchContacts", + query_ = nil, + limit_ = 999999999 + },function(i, naji) + local users, count = redis:smembers("botBOT-IDusers"), naji.total_count_ + for n=0, tonumber(count) - 1 do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = i.chat_id, + user_id_ = naji.users_[n].id_, + forward_limit_ = 50 + }, dl_cb, nil) + end + for n=1, #users do + tdcli_function ({ + ID = "AddChatMember", + chat_id_ = i.chat_id, + user_id_ = users[n], + forward_limit_ = 50 + }, dl_cb, nil) + end + end, {chat_id=msg.chat_id_}) + return send(msg.chat_id_, msg.id_, "در حال افزودن مخاطبین به گروه ...") + end end end if redis:sismember("botBOT-IDanswerslist", text) then @@ -511,26 +625,23 @@ function tdcli_update_callback(data) end end elseif msg.content_.ID == "MessageContact" then - local first = msg.content_.contact_.first_name_ or "-" - local last = msg.content_.contact_.last_name_ or "-" - local phone = msg.content_.contact_.phone_number_ local id = msg.content_.contact_.user_id_ - tdcli_function ({ - ID = "ImportContacts", - contacts_ = {[0] = { - phone_number_ = tostring(phone), - first_name_ = tostring(first), - last_name_ = tostring(last), - user_id_ = id - }, - }, - }, dl_cb, nil) - if redis:get("botBOT-IDaddmsg") then - local answer = redis:get("botBOT-IDaddmsgtext") or "اددی گلم خصوصی پیام بده" - send(msg.chat_id_, msg.id_, answer) - end if not redis:sismember("botBOT-IDaddedcontacts",id) then redis:sadd("botBOT-IDaddedcontacts",id) + local first = msg.content_.contact_.first_name_ or "-" + local last = msg.content_.contact_.last_name_ or "-" + local phone = msg.content_.contact_.phone_number_ + local id = msg.content_.contact_.user_id_ + tdcli_function ({ + ID = "ImportContacts", + contacts_ = {[0] = { + phone_number_ = tostring(phone), + first_name_ = tostring(first), + last_name_ = tostring(last), + user_id_ = id + }, + }, + }, dl_cb, nil) if redis:get("botBOT-IDaddcontact") and msg.sender_user_id_ ~= bot_id then local fname = redis:get("botBOT-IDfname") local lnasme = redis:get("botBOT-IDlname") or "" @@ -555,6 +666,10 @@ function tdcli_update_callback(data) }, dl_cb, nil) end end + if redis:get("botBOT-IDaddmsg") then + local answer = redis:get("botBOT-IDaddmsgtext") or "اددی گلم خصوصی پیام بده" + send(msg.chat_id_, msg.id_, answer) + end elseif msg.content_.ID == "MessageChatDeleteMember" and msg.content_.id_ == bot_id then return rem(msg.chat_id_) elseif msg.content_.ID == "MessageChatJoinByLink" and msg.sender_user_id_ == bot_id then @@ -566,7 +681,7 @@ function tdcli_update_callback(data) end end elseif msg.content_.caption_ then - return process_link(msg.content_.caption_) + return find_link(msg.content_.caption_) end if redis:get("botBOT-IDmarkread") then tdcli_function ({ From 94d57a25724cb99945f8146fcaf31a999fb50e94 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 20 Mar 2017 22:24:53 +0330 Subject: [PATCH 27/36] ver 0.999 --- README.md | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f017003..4f1ac88 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@
توجه داشته باشید برای اولین بار که ربات را راه اندازی می‌کنید،از شما شناسه عددی مدیر ربات (شما و یا هرکس که می خواهید مدیر ربات شود) ، شماره ربات و کد ورود به حساب کاربری خواسته می‌شود.
شما می توانید با استفاده از ربات @ID_ProBot شناسه عددی خود را بدست آورید.
-
از راهنمای‌تبلیغ‌گر برای ثبت گروه مدیریتی و آشنا شدن با طرز کار رباتتان استفاده کنید.
+
از راهنمای‌تبلیغ‌گر برای آشنا شدن با طرز کار رباتتان استفاده کنید.

جلوگیری از قطع شدن عملکرد تبلیغ‌گر🛡
@@ -77,20 +77,33 @@ بروزرسانی ربات    بروزرسانی ربات به آخرین نسخه
و بارگذاری مجدد + + + تازه سازی +    تازه سازی آمار تبیلغ‌گر
(حدکثر یک بار در روز) + + + ریپورت +    اطلاع از وضعیت ریپورت ربات + + + تازه سازی ربات +    تازه سازی اطلاعات فردی تبلیغ‎گر
بعد از تغییر در مشخصات فردی تبلیغ‎گر
مانند اسم انجام گیرد - تنظیم مدیر + افزودن مدیر شناسه - جایگزینی مدیر جدید با شناسه عددی + افزودن مدیر با شناسه وارد شد - - تنظیم گروه مدیریت -    در نظر گرفتن گروه به‌عنوان گروه مدیریتی - ✤ + + افزودن مدیرکل + شناسه + افزودن مدیرکل با شناسه وارد شد - - حذف گروه مدیریت -    حذف گروه از دیتابیس به‌عنوان گروه مدیریتی + + حذف مدیر + شناسه + حذف مدیر یا مدیر کل با شناسه خاص ترک کردن @@ -101,17 +114,10 @@ افزودن همه مخاطبین    افزودن تمام مخاطبین و افراد در گفت‌و‎گوی شخصی
به گروه ✤ - - - مخصوص مدیر و گروه مدیریتی شناسه من    ارسال شناسه عددی شما - - - شناسه مدیر -    ارسال شناسه عددی مدیر بگو @@ -218,6 +224,10 @@ امار    ارسال آمار و وضعیت تبلیغ‌گر + + + وضعیت +    ارسال وضعیت اجرایی تبلیغ‌گر ارسال به From b1746912270d9d353be4b86e61ee518d5e772475 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 20 Mar 2017 22:25:35 +0330 Subject: [PATCH 28/36] ver 0.999 From 03ae0cd164e1fe48cd98cefefd6c131bdb69f779 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 20 Mar 2017 22:31:53 +0330 Subject: [PATCH 29/36] ver 0.999 --- bot.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bot.lua b/bot.lua index b777319..39b8f13 100644 --- a/bot.lua +++ b/bot.lua @@ -246,11 +246,11 @@ function tdcli_update_callback(data) return reload(msg.chat_id_,msg.id_) elseif text:match("^بروزرسانی ربات$") then io.popen("git fetch --all && git reset --hard origin/persian && git pull origin persian && chmod +x bot"):read("*all") - local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",4) + local text,ok = io.open("bot.lua",'r'):read('*a'):gsub("BOT%-ID",BOT-ID) io.open("bot-BOT-ID.lua",'w'):write(text):close() return reload(msg.chat_id_,msg.id_) elseif text:match("^همگام سازی با تبچی$") then - local botid = 4 - 1 + local botid = BOT-ID - 1 redis:sunionstore("botBOT-IDall","tabchi:"..tostring(botid)..":all") redis:sunionstore("botBOT-IDusers","tabchi:"..tostring(botid)..":pvis") redis:sunionstore("bot1groups","tabchi:"..tostring(botid)..":groups") @@ -287,7 +287,7 @@ function tdcli_update_callback(data) input_message_content_ = {ID = "InputMessageDocument", document_ = {ID = "InputFileLocal", path_ = "botBOT-ID_contacts.txt"}, - caption_ = "مخاطبین تبلیغ‌گر شماره 4"} + caption_ = "مخاطبین تبلیغ‌گر شماره BOT-ID"} }, dl_cb, nil) return io.popen("rm -rf botBOT-ID_contacts.txt"):read("*all") end, {chat_id = msg.chat_id_}) @@ -330,7 +330,7 @@ function tdcli_update_callback(data) input_message_content_ = {ID = "InputMessageDocument", document_ = {ID = "InputFileLocal", path_ = tostring(naji)..".txt"}, - caption_ = "لیست "..tostring(matches).." های تبلیغ گر شماره 4"} + caption_ = "لیست "..tostring(matches).." های تبلیغ گر شماره BOT-ID"} }, dl_cb, nil) return io.popen("rm -rf "..tostring(naji)..".txt"):read("*all") elseif text:match("^(وضعیت مشاهده) (.*)$") then @@ -404,7 +404,7 @@ function tdcli_update_callback(data) end, {id=b}) end end - return send(msg.chat_id_,msg.id_,"تازه‌سازی آمار تبلیغ‌گر شماره 4 با موفقیت انجام شد.") + return send(msg.chat_id_,msg.id_,"تازه‌سازی آمار تبلیغ‌گر شماره BOT-ID با موفقیت انجام شد.") elseif text:match("^(وضعیت)$") then local s = redis:get("botBOT-IDmaxjoin") and redis:ttl("botBOT-IDmaxjoin") or 0 local ss = redis:get("botBOT-IDmaxlink") and redis:ttl("botBOT-IDmaxlink") or 0 @@ -415,7 +415,7 @@ function tdcli_update_callback(data) local wlinks = redis:scard("botBOT-IDwaitelinks") local glinks = redis:scard("botBOT-IDgoodlinks") local links = redis:scard("botBOT-IDsavedlinks") - local txt = "⚙️ وضعیت اجرایی تبلیغ‌گر 4 ⛓\n\n" .. tostring(autoanswer) .." حالت پاسخگویی خودکار 🗣 \n" .. tostring(numadd) .. " افزودن مخاطب با شماره 📞 \n" .. tostring(msgadd) .. " افزودن مخاطب با پیام 🗞\n〰〰〰ا〰〰〰\n📄 پیام افزودن مخاطب :\n📍 " .. tostring(txtadd) .. " 📍\n〰〰〰ا〰〰〰\n📁 لینک های ذخیره شده : " .. tostring(links) .. "\n⏲ لینک های در انتظار عضویت : " .. tostring(glinks) .. "\n🕖 " .. tostring(s) .. " ثانیه تا عضویت مجدد\n❄️ لینک های در انتظار تایید : " .. tostring(wlinks) .. "\n🕑️ " .. tostring(ss) .. " ثانیه تا تایید لینک مجدد\n 😼 سازنده : @i_naji" + local txt = "⚙️ وضعیت اجرایی تبلیغ‌گر BOT-ID ⛓\n\n" .. tostring(autoanswer) .." حالت پاسخگویی خودکار 🗣 \n" .. tostring(numadd) .. " افزودن مخاطب با شماره 📞 \n" .. tostring(msgadd) .. " افزودن مخاطب با پیام 🗞\n〰〰〰ا〰〰〰\n📄 پیام افزودن مخاطب :\n📍 " .. tostring(txtadd) .. " 📍\n〰〰〰ا〰〰〰\n📁 لینک های ذخیره شده : " .. tostring(links) .. "\n⏲ لینک های در انتظار عضویت : " .. tostring(glinks) .. "\n🕖 " .. tostring(s) .. " ثانیه تا عضویت مجدد\n❄️ لینک های در انتظار تایید : " .. tostring(wlinks) .. "\n🕑️ " .. tostring(ss) .. " ثانیه تا تایید لینک مجدد\n 😼 سازنده : @i_naji" return send(msg.chat_id_, 0, txt) elseif text:match("^(امار)$") or text:match("^(آمار)$") then local gps = redis:scard("botBOT-IDgroups") From e8faceabbb5b4556b688e3d35a84e6ed37d28164 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 20 Mar 2017 23:39:42 +0330 Subject: [PATCH 30/36] ver 0.99 --- bot.lua | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/bot.lua b/bot.lua index 39b8f13..8080360 100644 --- a/bot.lua +++ b/bot.lua @@ -4,16 +4,17 @@ redis = redis.connect('127.0.0.1', 6379) function dl_cb(arg, data) end function get_admin () - if redis:exists('botBOT-IDadmin') then - return true - else - print("\n\27[32m لازمه کارکرد صحیح ، فرامین و امورات مدیریتی ربات تبلیغ گر <<\n تعریف کاربری به عنوان مدیر است\n\27[34m ایدی خود را به عنوان مدیر وارد کنید\n\27[32m شما می توانید از ربات زیر شناسه عددی خود را بدست اورید\n\27[34m ربات: @id_ProBot") - print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @id_ProBot") - print("\n\27[36m : شناسه عددی ادمین را وارد کنید << \n >> Imput the Admin ID :\n\27[31m ") - admin=io.read() - redis:sadd("botBOT-IDadmin", admin) - end - return print("\n\27[36m ADMIN ID |\27[32m ".. admin .." \27[36m| شناسه ادمین") + if redis:get('botBOT-IDadminset') then + return true + else + print("\n\27[32m لازمه کارکرد صحیح ، فرامین و امورات مدیریتی ربات تبلیغ گر <<\n تعریف کاربری به عنوان مدیر است\n\27[34m ایدی خود را به عنوان مدیر وارد کنید\n\27[32m شما می توانید از ربات زیر شناسه عددی خود را بدست اورید\n\27[34m ربات: @id_ProBot") + print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @id_ProBot") + print("\n\27[36m : شناسه عددی ادمین را وارد کنید << \n >> Imput the Admin ID :\n\27[31m ") + admin=io.read() + redis:sadd("botBOT-IDadmin", admin) + redis:set('botBOT-IDadminset',true) + end + return print("\n\27[36m ADMIN ID |\27[32m ".. admin .." \27[36m| شناسه ادمین") end function get_bot (i, naji) function bot_info (i, naji) From 05a178c8e91c0b1189fda525e19d191ec96513c8 Mon Sep 17 00:00:00 2001 From: Naji Date: Mon, 20 Mar 2017 23:45:01 +0330 Subject: [PATCH 31/36] ver 0.99 --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 8080360..f1d1dea 100644 --- a/bot.lua +++ b/bot.lua @@ -81,7 +81,7 @@ function find_link(text) local text = text:gsub("telegram.dog", "telegram.me") for link in text:gmatch("(https://telegram.me/joinchat/%S+)") do print("newlink") - if (not redis:sismember("botBOT-IDsavedlinks", link or not redis:sismember("botBOT-IDwaitelinks", link)) then + if (not redis:sismember("botBOT-IDsavedlinks", link) or not redis:sismember("botBOT-IDwaitelinks", link) or not redis:sismember("botBOT-IDgoodlinks", link)) then redis:sadd("botBOT-IDwaitelinks", link) end end From ef73719a139b5d53a43376f958c21b871272291c Mon Sep 17 00:00:00 2001 From: Naji Date: Tue, 21 Mar 2017 00:59:57 +0330 Subject: [PATCH 32/36] ver 0.99 fix all linux vers --- bot.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.lua b/bot.lua index f1d1dea..9ec00ee 100644 --- a/bot.lua +++ b/bot.lua @@ -11,6 +11,7 @@ function get_admin () print("\n\27[32m >> Tabchi Bot need a fullaccess user (ADMIN)\n\27[34m Imput Your ID as the ADMIN\n\27[32m You can get your ID of this bot\n\27[34m @id_ProBot") print("\n\27[36m : شناسه عددی ادمین را وارد کنید << \n >> Imput the Admin ID :\n\27[31m ") admin=io.read() + redis:del("botBOT-IDadmin") redis:sadd("botBOT-IDadmin", admin) redis:set('botBOT-IDadminset',true) end From 21ff19f1d2db0b65316d3f84042c85c19ec3be1f Mon Sep 17 00:00:00 2001 From: Naji Date: Tue, 21 Mar 2017 02:35:39 +0330 Subject: [PATCH 33/36] ver 0.99 fix find_link --- bot.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 9ec00ee..dca5799 100644 --- a/bot.lua +++ b/bot.lua @@ -82,8 +82,9 @@ function find_link(text) local text = text:gsub("telegram.dog", "telegram.me") for link in text:gmatch("(https://telegram.me/joinchat/%S+)") do print("newlink") - if (not redis:sismember("botBOT-IDsavedlinks", link) or not redis:sismember("botBOT-IDwaitelinks", link) or not redis:sismember("botBOT-IDgoodlinks", link)) then + if not redis:sismember("botBOT-IDalllinks", link) then redis:sadd("botBOT-IDwaitelinks", link) + redis:sadd("botBOT-IDalllinks", link) end end end From a25ad79134d51533c3291d891c61dbbb64a9e507 Mon Sep 17 00:00:00 2001 From: Naji Date: Tue, 21 Mar 2017 02:40:38 +0330 Subject: [PATCH 34/36] ver 0.99 fix process_link --- bot.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/bot.lua b/bot.lua index dca5799..8e39451 100644 --- a/bot.lua +++ b/bot.lua @@ -58,7 +58,6 @@ function process_join(i, naji) local Time = message:match('%d+') redis:setex("botBOT-IDmaxjoin", tonumber(Time), true) else - print("join_ok") redis:srem("botBOT-IDgoodlinks", i.link) redis:sadd("botBOT-IDsavedlinks", i.link) end @@ -73,7 +72,6 @@ function process_link(i, naji) redis:setex("botBOT-IDmaxlink", tonumber(Time), true) else redis:srem("botBOT-IDwaitelinks", i.link) - redis:srem("botBOT-IDsavedlinks", i.link) end end function find_link(text) @@ -81,7 +79,6 @@ function find_link(text) local text = text:gsub("t.me", "telegram.me") local text = text:gsub("telegram.dog", "telegram.me") for link in text:gmatch("(https://telegram.me/joinchat/%S+)") do - print("newlink") if not redis:sismember("botBOT-IDalllinks", link) then redis:sadd("botBOT-IDwaitelinks", link) redis:sadd("botBOT-IDalllinks", link) From b16fd04d8abab997206133caedca4e5d9a8f0bcd Mon Sep 17 00:00:00 2001 From: Naji Date: Tue, 21 Mar 2017 18:30:48 +0330 Subject: [PATCH 35/36] ver 0.99 fix little bug --- bot.lua | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/bot.lua b/bot.lua index 8e39451..4a4c4e3 100644 --- a/bot.lua +++ b/bot.lua @@ -188,47 +188,47 @@ function tdcli_update_callback(data) if is_naji(msg) then if text:match("^(افزودن مدیر) (%d+)$") then local matches = text:match("%d+") - if redis:sismember('bot2admin', matches) then + if redis:sismember('botBOT-IDadmin', matches) then return send(msg.chat_id_, msg.id_, "کاربر مورد نظر در حال حاضر مدیر است.") - elseif redis:sismember('bot2mod', msg.sender_user_id_) then + elseif redis:sismember('botBOT-IDmod', msg.sender_user_id_) then return send(msg.chat_id_, msg.id_, "شما دسترسی ندارید.") else - redis:sadd('bot2admin', matches) - redis:sadd('bot2mod', matches) + redis:sadd('botBOT-IDadmin', matches) + redis:sadd('botBOT-IDmod', matches) return send(msg.chat_id_, msg.id_, "مقام کاربر به مدیر ارتقا یافت") end elseif text:match("^(افزودن مدیرکل) (%d+)$") then local matches = text:match("%d+") - if redis:sismember('bot2mod',msg.sender_user_id_) then + if redis:sismember('botBOT-IDmod',msg.sender_user_id_) then return send(msg.chat_id_, msg.id_, "شما دسترسی ندارید.") end - if redis:sismember('bot2mod', matches) then - redis:srem("bot2mod",matches) - redis:sadd('bot2admin'..tostring(matches),msg.sender_user_id_) + if redis:sismember('botBOT-IDmod', matches) then + redis:srem("botBOT-IDmod",matches) + redis:sadd('botBOT-IDadmin'..tostring(matches),msg.sender_user_id_) return send(msg.chat_id_, msg.id_, "مقام کاربر به مدیریت کل ارتقا یافت .") - elseif redis:sismember('bot2admin',matches) then + elseif redis:sismember('botBOT-IDadmin',matches) then return send(msg.chat_id_, msg.id_, 'درحال حاضر مدیر هستند.') else - redis:sadd('bot2admin', matches) - redis:sadd('bot2admin'..tostring(matches),msg.sender_user_id_) + redis:sadd('botBOT-IDadmin', matches) + redis:sadd('botBOT-IDadmin'..tostring(matches),msg.sender_user_id_) return send(msg.chat_id_, msg.id_, "کاربر به مقام مدیرکل منصوب شد.") end elseif text:match("^(حذف مدیر) (%d+)$") then local matches = text:match("%d+") - if redis:sismember('bot2mod', msg.sender_user_id_) then + if redis:sismember('botBOT-IDmod', msg.sender_user_id_) then if tonumber(matches) == msg.sender_user_id_ then - redis:srem('bot2admin', msg.sender_user_id_) - redis:srem('bot2mod', msg.sender_user_id_) + redis:srem('botBOT-IDadmin', msg.sender_user_id_) + redis:srem('botBOT-IDmod', msg.sender_user_id_) return send(msg.chat_id_, msg.id_, "شما دیگر مدیر نیستید.") end return send(msg.chat_id_, msg.id_, "شما دسترسی ندارید.") end - if redis:sismember('bot2admin', matches) then - if redis:sismember('bot2admin'..msg.sender_user_id_ ,matches) then + if redis:sismember('botBOT-IDadmin', matches) then + if redis:sismember('botBOT-IDadmin'..msg.sender_user_id_ ,matches) then return send(msg.chat_id_, msg.id_, "شما نمی توانید مدیری که به شما مقام داده را عزل کنید.") end - redis:srem('bot2admin', matches) - redis:srem('bot2mod', matches) + redis:srem('botBOT-IDadmin', matches) + redis:srem('botBOT-IDmod', matches) return send(msg.chat_id_, msg.id_, "کاربر از مقام مدیریت خلع شد.") end return send(msg.chat_id_, msg.id_, "کاربر مورد نظر مدیر نمی باشد.") @@ -253,9 +253,9 @@ function tdcli_update_callback(data) local botid = BOT-ID - 1 redis:sunionstore("botBOT-IDall","tabchi:"..tostring(botid)..":all") redis:sunionstore("botBOT-IDusers","tabchi:"..tostring(botid)..":pvis") - redis:sunionstore("bot1groups","tabchi:"..tostring(botid)..":groups") - redis:sunionstore("bot1supergroups","tabchi:"..tostring(botid)..":channels") - redis:sunionstore("bot1savedlinks","tabchi:"..tostring(botid)..":savedlinks") + redis:sunionstore("botBOT-IDgroups","tabchi:"..tostring(botid)..":groups") + redis:sunionstore("botBOT-IDsupergroups","tabchi:"..tostring(botid)..":channels") + redis:sunionstore("botBOT-IDsavedlinks","tabchi:"..tostring(botid)..":savedlinks") return send(msg.chat_id_, msg.id_, "همگام سازی اطلاعات با تبچی شماره "..tostring(botid).." انجام شد.") elseif text:match("^(لیست) (.*)$") then local matches = text:match("^لیست (.*)$") @@ -409,8 +409,8 @@ function tdcli_update_callback(data) local s = redis:get("botBOT-IDmaxjoin") and redis:ttl("botBOT-IDmaxjoin") or 0 local ss = redis:get("botBOT-IDmaxlink") and redis:ttl("botBOT-IDmaxlink") or 0 local msgadd = redis:get("botBOT-IDaddmsg") and "☑️" or "❎" - local numadd = redis:get("bot3addcontact") and "✅" or "❎" - local txtadd = redis:get("bot3addmsgtext") or "اد‌دی گلم خصوصی پیام بده" + local numadd = redis:get("botBOT-IDaddcontact") and "✅" or "❎" + local txtadd = redis:get("botBOT-IDaddmsgtext") or "اد‌دی گلم خصوصی پیام بده" local autoanswer = redis:get("botBOT-IDautoanswer") and "✅" or "❎" local wlinks = redis:scard("botBOT-IDwaitelinks") local glinks = redis:scard("botBOT-IDgoodlinks") From e43bd5e43e5f2f4e554c2f9e0e2a1b8a0ff42b70 Mon Sep 17 00:00:00 2001 From: Naji Date: Tue, 21 Mar 2017 18:31:47 +0330 Subject: [PATCH 36/36] Fix little bug --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 4a4c4e3..c30c379 100644 --- a/bot.lua +++ b/bot.lua @@ -310,7 +310,7 @@ function tdcli_update_callback(data) elseif matches == "لینک" then naji = "botBOT-IDsavedlinks" elseif matches == "مدیر" then - naji = "bot2admin" + naji = "botBOT-IDadmin" else return true end