---------------------------------- About Programmer ----------------------------------

-- Written By Ebi Khosravi
-- Bot Project With Lua Programming Language

---------------------------------- Argo ----------------------------------
if not arg[1] then
	return false
end
if arg[1] and string.match(arg[1], 'new:(%d+)') then
local conutBot = string.match(arg[1], 'new:(%d+)') 
	local InputConfig = [[
local _ = {
	Token = "",
	owner_id = {1276352601, 12345678},
	title_bot = "مووی سنتر"
}
return _]]
	local file = io.open('./Config/config-'..conutBot..'.lua', 'w')
		file:write(InputConfig)
		file:close()
	return false
end
---------------------------------- Require ----------------------------------
local http = require("socket.http")
local https = require("ssl.https")
local URL = require("socket.url")
local db = require('redis')
local redis = db.connect('127.0.0.1', 6379)
local json = require("cjson")
---------------------------------- Config -----------------------------------
local Config = dofile('./Config/config-'..arg[1]..'.lua')
local owner_id = Config.owner_id
local Token = Config.Token
local idBot,tokenKey = string.match(Token, "(%d+):(.*)")
local RedisBot = idBot
local ApiKey = 'https://api.telegram.org/bot'..Token
local is_link = {url = 'https://www.film2mediax.top', url_photo = 'https://intocdn.top'}
local data_timer = {}
need = {
process = 0, -- Start : need.process = need.process + 1 >> Stop :  need.process = need.process - 1
username_bot = ''
}
---------------------------------- DataWeb ----------------------------------
local WebSite = {
[1] = {value = 'فیلم سینمایی', key = 'AllMovies', type = 1, genre = 0},
[2] = {value = 'فیلم و سریال', key = 'AllBoth', type = 2, genre = 0},
[3] = {value = 'سریال جدید', key = 'AllSeries', type = 3, genre = 0},
-------------------------------------------------------
[10] = {value = 'هیجان انگیز', key = 'AllMGenre49165', type = 1, genre = 49165},
[11] = {value = 'کمدی', key = 'AllMGenre49159', type = 1, genre = 49159},
[12] = {value = 'درام', key = 'AllMGenre49160', type = 1, genre = 49160},
[13] = {value = 'معمایی', key = 'AllMGenre49161', type = 1, genre = 49161},
[14] = {value = 'علمی تخیلی', key = 'AllMGenre49162', type = 1, genre = 49162},
[15] = {value = 'فانتزی', key = 'AllMGenre49182', type = 1, genre = 49182},
[16] = {value = 'اکشن', key = 'AllMGenre49166', type = 1, genre = 49166},
[17] = {value = 'عاشقانه', key = 'AllMGenre49167', type = 1, genre = 49167},
[18] = {value = 'ماجراجویی', key = 'AllMGenre49170', type = 1, genre = 49170},
[19] = {value = 'انیمیشن', key = 'AllMGenre49173', type = 1, genre = 49173},
[20] = {value = 'انیمه', key = 'AllMGenre220320', type = 1, genre = 220320},
[21] = {value = 'ترسناک', key = 'AllMGenre49174', type = 1, genre = 49174},
[22] = {value = 'جنایی', key = 'AllMGenre49179', type = 1, genre = 49179},
-------------------------------------------------------
[30] = {value = 'هیجان انگیز', key = 'AllBGenre49165', type = 2, genre = 49165},
[31] = {value = 'کمدی', key = 'AllBGenre49159', type = 2, genre = 49159},
[32] = {value = 'درام', key = 'AllBGenre49160', type = 2, genre = 49160},
[33] = {value = 'معمایی', key = 'AllBGenre49161', type = 2, genre = 49161},
[34] = {value = 'علمی تخیلی', key = 'AllBGenre49162', type = 2, genre = 49162},
[35] = {value = 'فانتزی', key = 'AllBGenre49182', type = 2, genre = 49182},
[36] = {value = 'اکشن', key = 'AllBGenre49166', type = 2, genre = 49166},
[37] = {value = 'عاشقانه', key = 'AllBGenre49167', type = 2, genre = 49167},
[38] = {value = 'ماجراجویی', key = 'AllBGenre49170', type = 2, genre = 49170},
[39] = {value = 'انیمیشن', key = 'AllBGenre49173', type = 2, genre = 49173},
[40] = {value = 'انیمه', key = 'AllBGenre220320', type = 2, genre = 220320},
[41] = {value = 'ترسناک', key = 'AllBGenre49174', type = 2, genre = 49174},
[42] = {value = 'جنایی', key = 'AllBGenre49179', type = 2, genre = 49179},
-------------------------------------------------------
[50] = {value = 'هیجان انگیز', key = 'AllSGenre49165', type = 3, genre = 49165},
[51] = {value = 'کمدی', key = 'AllSGenre49159', type = 3, genre = 49159},
[52] = {value = 'درام', key = 'AllSGenre49160', type = 3, genre = 49160},
[52] = {value = 'معمایی', key = 'AllSGenre49161', type = 3, genre = 49161},
[54] = {value = 'علمی تخیلی', key = 'AllSGenre49162', type = 3, genre = 49162},
[55] = {value = 'فانتزی', key = 'AllSGenre49182', type = 3, genre = 49182},
[56] = {value = 'اکشن', key = 'AllSGenre49166', type = 3, genre = 49166},
[57] = {value = 'عاشقانه', key = 'AllSGenre49167', type = 3, genre = 49167},
[58] = {value = 'ماجراجویی', key = 'AllSGenre49170', type = 3, genre = 49170},
[59] = {value = 'انیمیشن', key = 'AllSGenre49173', type = 3, genre = 49173},
[60] = {value = 'انیمه', key = 'AllSGenre220320', type = 3, genre = 220320},
[61] = {value = 'ترسناک', key = 'AllSGenre49174', type = 3, genre = 49174},
[62] = {value = 'جنایی', key = 'AllSGenre49179', type = 3, genre = 49179},
}
---------------------------------- Color ----------------------------------
local color = {
red = {"\027[31m", "\027[41m"},
green = {"\027[32m", "\027[42m"},
yellow = {"\027[33m", "\027[43m"},
blue = {"\027[34m", "\027[44m"},
magenta = {"\027[35m", "\027[45m"},
cyan = {"\027[36m", "\027[46m"},
default = "\027[00m"
}
---------------------------------- Run_Bash ----------------------------
function Run_Bash(c)
local cmd = io.popen(c)
local result = cmd:read('*all')
return result
end
---------------------------------- send_request -----------------------------
function SendRequest(url)
local dat, res = https.request(url)
local tab = json.decode(dat)
if res ~= 200 then return false end
if not tab.ok then return false end
return tab
end
---------------------------------- getMe ---------------------------
function getMe()
	local url = ApiKey..'/getMe'
	local result = https.request(url)
	return json.decode(result)
end
---------------------------------- getUsernameBot ----------------------------------
if need.username_bot == '' then
local extra = getMe()
if extra then
if extra and extra.ok and extra.result then
if extra.result and extra.result.username then
need.username_bot = extra.result.username
end
end
end
end
---------------------------------- MentionUser ------------------------------
function MentionUser(user_id, parse_mode)
	if parse_mode == 'md' then
		return '['..user_id..'](tg://user?id='..user_id..')'
	else
		return '<a href="tg://user?id='..user_id..'">'..user_id..'</a>'
	end
end
---------------------------------- vardump ----------------------------------
function Dumper(input)
	local function Dumper(value)
		if type(value) == 'table' then
			local dump = '{\n'
			for key,v in pairs(value) do
				if type(key) == 'number' then
					key = '['..key..']'
				elseif type(key) == 'string' and key:match('@') then
					key = '["'..key..'"]'
				end
				if type(v) == 'string' then
					v = "'"..v.."'"
				end
				dump = dump..key..' = '..Dumper(v)..',\n'
			end
			return dump..'}'
		else
			return tostring(value)
		end
	end
	return Dumper(input)
end
function vardump(value)
	print(Dumper(value))
end
---------------------------------- set_timer --------------------------------
function errorMessage(input)
   print(input)
end
function set_timer(seconds, def, argv)
if type(seconds) ~= 'number' then
  return {
  _ = false,
  message = 'set_timer(int seconds, funtion def, table)'
  }
elseif type(def) ~= 'function' then
  return {
  _ = false,
  message = 'set_timer(int seconds, funtion def, table)'
  }
end
data_timer[#data_timer + 1] = { def = def, argv = argv, run_in = os.time() + seconds }
return { _ = true, run_in = os.time() + seconds, timer_id = #data_timer }
end
---------------------------------- OwnerRank --------------------------------
function OwnerRank(user_id)
	if redis:sismember(RedisBot..':ListAdmins:', user_id) then
		return true
	end
	if #owner_id ~= 0 then 
		for k,v in pairs(owner_id) do
			if tonumber(user_id) == tonumber(v) then
				return true
			end
		end
	end
return false
end
---------------------------------- is_private -------------------------------
function is_private(msg)
	local value = false
	if not tostring(msg.chat.id):match('^-') then
		value = true
	end
return value
end
---------------------------------- get_update -------------------------------
function getUpdates(offset)
	local url = ApiKey.."/getUpdates?timeout=10&limit=100&offset="..offset
	return SendRequest(url)
end
---------------------------------- forward_message ---------------------------
function ForwardMessage(chat_id, from_chat_id, message_id)
	local url = ApiKey..'/forwardMessage?chat_id='..chat_id..'&from_chat_id='..from_chat_id..'&message_id='..message_id
	return SendRequest(url)
end
---------------------------------- deletemessage ---------------------------
function deletemessage(chat_id, message_id)
	local url = ApiKey..'/deletemessage?chat_id='..chat_id..'&message_id='..message_id
	return SendRequest(url)
end
---------------------------------- getChat ---------------------------
function getChat(chat_id)
	local url = ApiKey..'/getChat?chat_id='..chat_id
	return SendRequest(url)
end
---------------------------------- answerCallbackQuery ---------------------------
function answerCallbackQuery(callback_query_id, text, show_alert)
	local url = ApiKey..'/answerCallbackQuery?callback_query_id='..callback_query_id..'&text='..URL.escape(text)
	if show_alert then
		url = url..'&show_alert=true'
	end
	return SendRequest(url)
end
---------------------------------- sendText -------------------------------
function sendText(chat_id, reply_to_message_id, text, markdown, keyboard, kind, link_preview_options)
    local response = {}
    local url = ApiKey..'/sendMessage?chat_id='..chat_id..'&text='..URL.escape(text)
    if reply_to_message_id then
        url = url..'&reply_to_message_id='..reply_to_message_id
    end
    if markdown == 'md' or markdown == 'markdown' then
        url = url..'&parse_mode=Markdown'
    elseif markdown == 'html' then
        url = url..'&parse_mode=HTML'
    end
    if kind == 1 then
        response.inline_keyboard = keyboard
        responseString = json.encode(response)
        url = url.."&reply_markup="..URL.escape(responseString)
    elseif kind == 2 then
        response.keyboard = keyboard
        response.resize_keyboard = true
        response.one_time_keyboard = false
        response.selective = true
        responseString = json.encode(response)
        url = url.."&reply_markup="..URL.escape(responseString)
    end
    if link_preview_options then
        url = url.."&link_preview_options="..
        URL.escape(json.encode(link_preview_options))
    else
        url = url.."&disable_web_page_preview=true"
    end
    local result = https.request(url)
	return json.decode(result)
end
---------------------------------- editText -------------------------------
function editText(chat_id, message_id, text, markdown, keyboard, kind, link_preview_options)
    local response = {}
    local url = ApiKey..'/editMessageText?chat_id='..chat_id..'&message_id='..message_id..'&text='..URL.escape(text)
    if markdown == 'md' or markdown == 'markdown' then
        url = url..'&parse_mode=Markdown'
    elseif markdown == 'html' then
        url = url..'&parse_mode=HTML'
    end
    if kind == 1 then
        response.inline_keyboard = keyboard
        responseString = json.encode(response)
        url = url.."&reply_markup="..URL.escape(responseString)
    end
    if link_preview_options then
        url = url.."&link_preview_options="..
        URL.escape(json.encode(link_preview_options))
    else
        url = url.."&disable_web_page_preview=true"
    end
    local result = https.request(url)
	return json.decode(result)
end
---------------------------------- answerInlineQuery ------------------------------
function answerInlineQuery(inline_query_id, results, cache_time, is_personal, next_offset, switch_pm_text, switch_pm_parameter)
local url = ApiKey..'/answerInlineQuery?inline_query_id='..inline_query_id
url = url..'&results='..URL.escape(json.encode(results))
if cache_time then
url = url..'&cache_time='..cache_time
else
url = url..'&cache_time=0'
end
if is_personal then
url = url..'&is_personal=true'
end
if next_offset then
url = url..'&next_offset='..URL.escape(next_offset)
end
if switch_pm_text and switch_pm_parameter then
url = url..'&switch_pm_text='..URL.escape(switch_pm_text)
url = url..'&switch_pm_parameter='..URL.escape(switch_pm_parameter)
end
	local result = https.request(url)
	return json.decode(result)
end
---------------------------------- sendMedia ------------------------------
function sendMedia(chat_id, reply_to_message_id, file_id, caption, parse_mode, media, keyboard)
local response = {}
	if media and string.lower(media) == 'video' then
			Method,Parameter = 'sendVideo','video'
		elseif media and string.lower(media) == 'videonote' then
			Method,Parameter = 'sendVideoNote','video_note'
		elseif media and string.lower(media) == 'voice' then
			Method,Parameter = 'sendVoice','voice'
		elseif media and string.lower(media) == 'photo' then
			Method,Parameter = 'sendPhoto','photo'
		else
			Method,Parameter = 'sendDocument','document'
		end
		url = ApiKey..'/'..Method..'?chat_id='..chat_id..'&reply_to_message_id='..reply_to_message_id..'&'..Parameter..'='..file_id..'&caption='..URL.escape(caption)
		if parse_mode == 'md' or parse_mode == 'markdown' then
			url = url..'&parse_mode=Markdown'
		elseif parse_mode == 'html' then
			url = url..'&parse_mode=HTML'
		end
	if keyboard then
		response.inline_keyboard = keyboard
		response.one_time_keyboard = false
		response.selective = false
		responseString = json.encode(response)
		url = url.."&disable_web_page_preview=true&reply_markup="..URL.escape(responseString)
	end
return SendRequest(url)
end
---------------------------------- importMedia -------------------------------
function importMedia(org)
	local TextCaption = org.caption and org.caption ~= '' and org.caption or 'NIL'
	if org.text then
	result = { type = 'Text', type_fa = 'متن', file_id = 'nil', text = org.text }
	elseif org.photo then
	result = { type = 'Photo', type_fa = 'عکس', file_id = org.photo[#org.photo].file_id, text = TextCaption }
	elseif org.voice then
	result = { type = 'Voice', type_fa = 'ویس', file_id = org.voice.file_id, text = TextCaption }
	elseif org.video then
	result = { type = 'Video', type_fa = 'ویدیو', file_id = org.video.file_id, text = TextCaption }
	elseif org.video_note then
	result = { type = 'VideoNote', type_fa = 'ویدیو سلفی', file_id = org.video_note.file_id, text = TextCaption }
	elseif org.audio then
	result = { type = 'Audio', type_fa = 'آهنگ', file_id = org.audio.file_id, text = TextCaption }
	elseif org.animation then
	result = { type = 'Gif', type_fa = 'گیف', file_id = org.animation.file_id, text = TextCaption }
	elseif org.document then
	result = { type = 'Document', type_fa = 'فایل', file_id = org.document.file_id, text = TextCaption }
	elseif org.sticker then
	result = { type = 'Sticker', type_fa = 'استیکر', file_id = org.sticker.file_id, text = TextCaption }
	else
	result = { type = 'nil' }
	end
return result
end
---------------------------------- CoreMessageProc -------------------------------
function CoreMessageProc(argv)
	for k,v in pairs(argv[1]) do
		if argv[5] == 'send' then
			if argv[4].type == 'Text' then
				sendText(v, 0, argv[4].text, 'html')
			else
				sendMedia(v, 0, argv[4].file_id, (argv[4].text == 'NIL' and '' or argv[4].text), 'html', argv[4].type)
			end
		else
			ForwardMessage(v, argv[2], argv[4])
		end
	end
	if argv[7] then
		need.process = need.process - 1
		if argv[5] == 'send' then
			KindText = '\n📮 نوع محتوا : '..argv[4].type_fa
		else
			KindText = ''
		end
		sendText(argv[2], argv[3], '📨 عملیات '..(argv[5] == 'send' and 'ارسال' or 'فوروارد')..' پیام به کاربران به اتمام رسید !\n\n👤 تعداد کاربران : '..argv[6]..KindText, 'html')
	end
end
---------------------------------- is_joinchannel ----------------------------
function CheckJoined(user_id, channels)
local Joined = {}
for k,v in pairs(channels) do
	url = https.request(ApiKey..'/getchatmember?chat_id='..v..'&user_id='..user_id)
	jdat = json.decode(url)
	if (not jdat.ok or jdat.result.status == "left" or jdat.result.status == "kicked") then
		table.insert(Joined , v)
	end
end
return {Joined = Joined}
end
function is_JoinChannel(msg, chat_id, message_id, alert_id)
local channels = redis:hkeys(RedisBot..':JoinChGpBot:')
	local KeyboardJoined = {}
		if OwnerRank(msg.from.id) or (#channels == 0) then
			return true
		else
		local data = CheckJoined(msg.from.id, channels)
		if #data.Joined == 0 then
			return true
		else
		if need.username_bot == '' then
			local extra = getMe()
			if extra then
				if extra and extra.ok and extra.result then
					if extra.result and extra.result.username then
						need.username_bot = extra.result.username
					end
				end
			end
		end
		local LEmoji = {'🔸','🔹','▪️','▫️'}
		local EM = LEmoji[math.random(#LEmoji)]
		for k,v in pairs(data.Joined) do
			local Type,Kinds,Links,Title = string.match(redis:hget(RedisBot..':JoinChGpBot:', v), '(%S+)|(%S+)|(%S+)|(.*)')
			table.insert(KeyboardJoined, {{text = EM ..' ' ..Title.. ' '..EM , url = string.gsub(Links, '@', 'https://t.me/')}}) 
		end
			table.insert(KeyboardJoined, {{text = EM..' بررسی عضویت '..EM, url = 'https://t.me/'..need.username_bot..'?start=new'}})
			local Text = '<b>👤 سلام <a href="tg://user?id='..msg.from.id..'">'..string.gsub(msg.from.first_name, '[<>]','')..'</a></b>\n\n<b>📍 برای حمایت از ما و همچنین دسترسی به تمامی امکانات ربات، لطفا در کانال‌های زیر عضو شوید :</b>\n\n'
			if alert_id  then
				answerCallbackQuery(alert_id, '• کاربر گرامی لطفا برای حمایت از ما داخل کانال ربات عضو شوید !', true)
				editText(chat_id, message_id, Text, 'html', KeyboardJoined, 1)
			else
			sendText(chat_id, message_id, Text, 'html', KeyboardJoined, 1)
			end
		end
	end
end
---------------------------------- AutoPro ----------------------------
function AutoPro(args)
local sec = (60 - os.date("%S")) + 5
set_timer(math.modf(sec), AutoPro, args)
if not redis:sismember(RedisBot..'ListDate', os.date("%Y/%m/%d")) then
	redis:sadd(RedisBot..'ListDate', os.date("%Y/%m/%d"))
end
if not redis:get('AutoCleanerData') then
redis:setex('AutoCleanerData', 43200, true)
Run_Bash("rm -rf $PWD/Data/*")
end
end
set_timer(2, AutoPro, {arg[1]})
---------------------------------- clean_string ----------------------------
local function clean_string(str)
	if str then
		str = str:gsub("&#%d+;", "")
		str = str:gsub("&#x%x+;", "")
		str = str:gsub("&%a+;", "")
		str = str:gsub("%s+", " ")
		str = str:match("^%s*(.-)%s*$")
	end
	return str
end
---------------------------------- slug_code ----------------------------
function slug_code(slug)
    local h=0
    for i=1,#slug do h=(h*31+slug:byte(i))%2^32 end
    local chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    local out=""
    for i=1,10 do h=(h*31+i)%2^32 out=out..chars:sub((h%#chars)+1,(h%#chars)+1) end
    return out
end
---------------------------------- getCodeTable ----------------------------
function getCodeTable(list, code)
if #list == 0 then
return false
end
for k,v in pairs(list) do
if v.code == code then
return v.link
end
end
return false
end
---------------------------------- TableSplit -------------------------------
function table.split(data, num) 
  local result = {} 
  for index, element in pairs(data) do 
    if #result == 0 or #result[#result] == num then 
      table.insert(result, {}) 
    end 
    table.insert(result[#result], element) 
  end 
  return result 
end
---------------------------------- extractMovies ----------------------------
function extractMovies(org)
    local typeMovie = {[1] = 'movie', [2] = 'both', [3] = 'series'}
	local html,res = https.request("https://www.film2mediax.top/?s=&type="..(typeMovie[tonumber(org.type)] or 'movie').."&sortby=newest&genre[]="..(org.genre or 0).."&paged="..(org.page or 1))
	local movies = {}
	if res ~= 200 then
		return json.encode(movies)
	end
	local html = string.gsub(html, '&#(%S+);t', '')
	for article in html:gmatch('<article class="entry">(.-)</article>') do
        local img_url = article:match('<img width=.- src="(.-)"')
        local movie_url = article:match('</figure> <a href="(.-)"')
        local movie_title = article:match('<h2 class="entry%-title">(.-)</h2>')
        local description = article:match('<figcaption class="sr%-only">(.-)</figcaption>')
        local subs = article:match('class="icon bg%-primary" title="(.-)"')
        local imdb_rating = article:match('<strong class="fw%-500 fsz%-16">(.-)</strong>')
		local year = article:match('href="#icon%-calendar".-</svg>%s*(%d%d%d%d)')
        table.insert(movies, {
            photo = img_url or '',
            link = movie_url or '',
            title = clean_string(movie_title or ''),
            title_full = clean_string(description or ''),
            subs = subs or '',
            imdb = imdb_rating or '---',
			year = year or '---',
			code = slug_code(movie_url)
        })
    end
    local table_json = json.encode(movies)
    return table_json
end
---------------------------------- extractInfoMovie ----------------------------
function extractInfoMovie(url)
	local result = {movie_info = {}}
	local html,res = https.request(url)
	if res ~= 200 then
		return {}
	end
	result.movie_info.title = clean_string(html:match('<h1 class="entry%-title.-">(.-)</h1>') or "")
	result.movie_info.description = clean_string(html:match('<div class="entry%-excerpt.-"><p>(.-)</p></div>') or "")
	result.movie_info.imdb = html:match('<strong class=".-">(.-)</strong>') or ""
	result.movie_info.photo = html:match('<img width=.- src="(.-)"') or ""
	result.movie_info.year = html:match('<span%s+dir="ltr">%s*(%d+/%d+/%d+)%s*</span>') or ""
	result.movie_info.times = html:match('</svg> زمان :\n (.-)</div>') or ""
	local NewGetDub = string.match(html, '<div class="download%-list dubbled">(.-)</ul></div>')
	if NewGetDub then
		for block in NewGetDub:gmatch("<li>(.-)</li>") do
			local title = block:match('<span[^>]*class="text"[^>]*>(.-)</span>')
			local url = block:match('<a%s+href="([^"]+)"%s+download')
			if title and url then
				if not result.link_dubbed then
					result.link_dubbed = {}
				end
				table.insert(result.link_dubbed, {title = title, url = url})
			end
		end
	end
	local NewGetSub = string.match(html, '<div class="download%-list hardsub">(.-)</ul></div>')
	if NewGetSub then
		for block in NewGetSub:gmatch("<li>(.-)</li>") do
			local title = block:match('<span[^>]*class="text"[^>]*>(.-)</span>')
			local url = block:match('<a%s+href="([^"]+)"%s+download')
			if title and url then
				if not result.link_hardsub then
					result.link_hardsub = {}
				end
				table.insert(result.link_hardsub, {title = title, url = url})
			end
		end
	end
	return result
end
---------------------------------- extractInfoSeries ----------------------------
function extractInfoSeries(url)
	local result = {movie_info = {}, series = {}}
	local html,res = https.request(url)
	if res ~= 200 then
		return {}
	end
	result.movie_info.title = clean_string(html:match('<h1 class="entry%-title.-">(.-)</h1>') or "")
	result.movie_info.description = clean_string(html:match('<div class="entry%-excerpt.-"><p>(.-)</p></div>') or "")
	result.movie_info.imdb = html:match('<strong class=".-">(.-)</strong>') or ""
	result.movie_info.photo = html:match('<img width=.- src="(.-)"') or ""
	result.movie_info.year = html:match('<span%s+dir="ltr">%s*(%d+/%d+/%d+)%s*</span>') or ""
	result.movie_info.times = html:match('</svg> زمان :\n (.-)</div>') or ""
	for key in html:gmatch('<div class="download%-season bg%-card rounded">(.-)</div>%s*</div>%s*</div>%s*</div>') do
		key = '<div class="download-season bg-card rounded">'..key..'</div></div></div></div>'
		season_name = key:match('aria%-controls="season%-dlbox[^"]*">%s*(.-)%s*<')
		local season_data = {season = (season_name or ''), dubbled = {}, hardsub = {}}
		for newKey in key:gmatch('<div class="download%-list dubbled">%s*(.-)%s*</li>%s*</ul>') do
		local newKey = '<div class="download-list dubbled">'..newKey..'</li></ul>'
		info = newKey:match('<p class="title">%s*<span>%s*(.-)%s*</span>%s*</p>')
		for block in newKey:gmatch('<li class="bg%-body">%s*(.-)%s*</div>%s*</li>') do
		quality = block:match('<span class="text" dir="ltr"%s*>(.-)</span>')
		local Links = {}
		for link, name in block:gmatch('<a%s*href="(%S+)"%s*class="btn btn%-block btn%-default"%s*>(.-)</a>') do
		table.insert(Links, {name = name,url = link})
		end
		table.insert(season_data.dubbled, {info = info, quality = quality, links = Links})
		end
		end
		for newKey in key:gmatch('<div class="download%-list hardsub">%s*(.-)%s*</li>%s*</ul>') do
		local newKey = '<div class="download-list hardsub">'..newKey..'</li></ul>'
		info = newKey:match('<p class="title">%s*<span>%s*(.-)%s*</span>%s*</p>')
		for block in newKey:gmatch('<li class="bg%-body">%s*(.-)%s*</div>%s*</li>') do
		quality = block:match('<span class="text" dir="ltr"%s*>(.-)</span>')
		local Links = {}
		for link, name in block:gmatch('<a%s*href="(%S+)"%s*class="btn btn%-block btn%-default"%s*>(.-)</a>') do
		table.insert(Links, {name = name, url = link})
		end
		table.insert(season_data.hardsub, {info = (info or ''), quality = (quality or ''), links = Links})
		end
		end
		table.insert(result.series, season_data)
	end
	return result
end
---------------------------------- SearchMovie ----------------------------
function SearchMovie(search)
	local html,res = https.request('https://www.film2mediax.top/quick-search?q='..URL.escape(search))
	if res ~= 200 then
		return {}
	end
	local data = json.decode(html)
	return data
end
---------------------------------- loadFromJSON ----------------------------
function loadFromJSON(path, count)
    local file = io.open('./Data/'..path..'_'..tostring(count)..'.txt', 'r')
    if not file then return nil end
    local jsonText = file:read("*a")
    file:close()
    return jsonText
end
---------------------------------- MenuStartBot ----------------------------
function MenuStartBot(chat_id, message_id, user_id, query)
local keyboard = {
	{
		{text = '• جستجوی فیلم 🔍', switch_inline_query_current_chat = ''}
	},
	{
		{text = '• فیلم سینمایی 🎥', callback_data = 'Page:1_1_1'},
		{text = '• سریال جدید 💎', callback_data = 'Page:3_1_1'}
	},
	{
		{text = '• دسته بندی 📚', callback_data = 'Genre:1'},
		{text = '• فیلم و سریال 🎬', callback_data = 'Page:2_1_1'}
	},
	{
		{text = '• راهنما ⁉️', callback_data = 'Help:1'},
		{text = '• پشتیبانی 👤', callback_data = 'Support:1'}
	},
	{
		{text = '• بستن فهرست 🔚', callback_data = 'Exit:1'}
	},
}
local Text = '<b>📍 | سلام به '..(Config.title_bot or 'مووی سنتر')..' خوش آمدید.\n🔅 | این ربات مرجع دانلود فیلم و سریال بدون سانسور است.\n\n• دوبله فارسی حرفه‌ای 🎙\n• زیرنویس چسبیده فارسی ✏️\n• کیفیت‌های متنوع 🎞\n• لینک دانلود مستقیم ⚡️\n\n🔻 | لطفا یک مورد را برای شروع انتخاب کنید :</b>'
if query then
editText(chat_id, message_id, Text, 'html', keyboard, 1)
else
sendText(chat_id, message_id, Text, 'html', keyboard, 1)
if not redis:sismember(RedisBot..'ListMemberBot', user_id) then
redis:sadd(RedisBot..'ListMemberBot', user_id)
redis:incr(RedisBot..'Count:DayMemberBot:'..os.date("%Y/%m/%d"))
end
end
end
---------------------------------- Core -------------------------------
function Core(msg)
if msg then
	if msg.date < os.time() - 60 then
		print('\27[36m>>>> Old Message <<<<\27[39m')
		return false
	end
-------------------------------
print('\27[36m[Message]['..msg.from.first_name..']['..msg.from.id..']['..os.date("%H:%M:%S")..']\27[39m')
-------------------------------
if is_private(msg) then
-------------------------------
if msg.text and (string.lower(msg.text) == '/start') and is_JoinChannel(msg, msg.chat.id, msg.message_id) then
redis:del(RedisBot..':SystemBotCheck:'..msg.from.id)
MenuStartBot(msg.chat.id, msg.message_id, msg.from.id)
return
elseif msg.text and string.match(msg.text, '^/[Ss][Tt][Aa][Rr][Tt] (.*)$') and is_JoinChannel(msg, msg.chat.id, msg.message_id) then
local getMatch = string.match(msg.text, '^/[Ss][Tt][Aa][Rr][Tt] (.*)$')
if getMatch and string.match(getMatch, '^[Mm]_(.*)$') then
local Code = string.match(getMatch, '^[Mm]_(.*)$')
local data = extractInfoMovie(is_link.url..'/'..Code)
if data and data.movie_info and data.movie_info.title ~= '' then
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n'
local keyboard = {}
if data.link_dubbed then
table.insert(keyboard, {{text = '─┅━━━ °• دوبله فارسی ها •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(data.link_dubbed) do
table.insert(keyboard, {{text = '📥 | '..v.title..' 🎙', url = v.url}})
end
end
if data.link_hardsub then
table.insert(keyboard, {{text = '─┅━━━ °• زیرنویس فارسی ها •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(data.link_hardsub) do
table.insert(keyboard, {{text = '📥 | '..v.title..' ✏️', url = v.url}})
end
end
if #keyboard ~= 0 then
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
sendText(msg.chat.id, msg.message_id, Text, 'html', keyboard, 1, preview)
else
sendText(msg.chat.id, msg.message_id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', 'html')
end
else
sendText(msg.chat.id, msg.message_id, '• متاسفانه نتوانستم فیلم را دریافت کنم !', 'html')
end
elseif getMatch and string.match(getMatch, '^[Ss]_(.*)$') then
local Code = string.match(getMatch, '^[Ss]_(.*)$')
if not loadFromJSON(Code, 0) then
local data = extractInfoSeries(is_link.url..'/'..Code)
if data and data.series and data.series[1] and ((#data.series[1].hardsub ~= 0) or (#data.series[1].dubbled ~= 0)) then
local ultra = json.encode(data)
local file = io.open('./Data/'..Code..'_0.txt', 'w')
file:write(ultra)
file:close()
end
end
local eseyGet = loadFromJSON(Code, 0)
if not eseyGet then
sendText(msg.chat.id, msg.message_id, '• اطلاعاتی از این سریال در دسترس نمیباشد !', 'html')
return
end
local data = json.decode(eseyGet)
if data and data.series and data.series[1] and ((#data.series[1].hardsub ~= 0) or (#data.series[1].dubbled ~= 0)) then
local keyboard = {}
if data.series and #data.series ~= 0 then
local row = {}
for k,v in pairs(data.series) do
table.insert(row, {text = '• '..v.season, callback_data = 'DLI:'..k..'_'..Code})
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
row = {}
end
end
if #row > 0 then
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
else
table.insert(keyboard, row)
end
end
end
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n\n🔻 | لطفا فصل سریال مورد نظر خود را انتخاب کنید :'
if #keyboard ~= 0 then
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
sendText(msg.chat.id, msg.message_id, Text, 'html', keyboard, 1, preview)
else
sendText(msg.chat.id, msg.message_id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', 'html')
end
else
sendText(msg.chat.id, msg.message_id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد !', 'html')
end
else
MenuStartBot(msg.chat.id, msg.message_id, msg.from.id)
end
if redis:get(RedisBot..':SystemBotCheck:'..msg.from.id) then
	redis:del(RedisBot..':SystemBotCheck:'..msg.from.id)
	return false
end
end
-------------------------------
local SystemBotCheck = redis:get(RedisBot..':SystemBotCheck:'..msg.from.id) or ''
if SystemBotCheck == 'ReportSupport' and (msg.text or msg.photo or msg.video or msg.voice or msg.audio or msg.document or msg.animation or msg.video_note or msg.sticker) then
if msg.text then
redis:incr(RedisBot..'Count:AllMessage')
redis:incr(RedisBot..'Count:DayMessage:'..os.date("%Y/%m/%d"))
redis:del(RedisBot..':SystemBotCheck:'..msg.from.id)
sendText(msg.chat.id, msg.message_id, '📬 | کاربر گرامی پیام شما برای ادمین ارسال شد !\n🔻 | لطفا تا بررسی پیام و جواب آن صبور باشید !', 'html')
return sendText(owner_id[1], 0, '📬 | #پیام_جدید\n'..msg.text, 'html', {{{text = "• ارسال کننده : "..msg.from.id, url = "tg://user?id="..msg.from.id}}}, 1)
else
local data = importMedia(msg)
if data.type ~= 'nil' then
redis:incr(RedisBot..'Count:AllMessage')
redis:incr(RedisBot..'Count:DayMessage:'..os.date("%Y/%m/%d"))
redis:del(RedisBot..':SystemBotCheck:'..msg.from.id)
sendText(msg.chat.id, msg.message_id, '📬 | کاربر گرامی پیام شما برای ادمین ارسال شد !\n🔻 | لطفا تا بررسی پیام و جواب آن صبور باشید !', 'html')
return sendMedia(owner_id[1], 0, data.file_id, '📬 | #پیام_جدید\n'..(data.text == 'NIL' and '' or data.text), 'html', data.type, {{{text = "• ارسال کننده : "..msg.from.id, url = "tg://user?id="..msg.from.id}}})
end
end
end
-------------------------------
if msg.reply_to_message and msg.reply_to_message.reply_markup and msg.reply_to_message.reply_markup.inline_keyboard and (#msg.reply_to_message.reply_markup.inline_keyboard == 1) and msg.reply_to_message.reply_markup.inline_keyboard[1] and msg.reply_to_message.reply_markup.inline_keyboard[1] and msg.reply_to_message.reply_markup.inline_keyboard[1][1].url then
local user_id = string.match(msg.reply_to_message.reply_markup.inline_keyboard[1][1].text, '^• ارسال کننده : (%d+)$')
if user_id then
if msg.text then
redis:incr(RedisBot..'Count:AllMessage')
redis:incr(RedisBot..'Count:DayMessage:'..os.date("%Y/%m/%d"))
sendText(msg.chat.id, msg.message_id, '📬 | پیام شما برای کاربر [ '..MentionUser(user_id, 'html')..' ] ارسال شد !', 'html')
return sendText(user_id, 0, '📨 | #پیام_پشتیبان\n'..msg.text)
else
local data = importMedia(msg)
if data.type ~= 'nil' then
redis:incr(RedisBot..'Count:AllMessage')
redis:incr(RedisBot..'Count:DayMessage:'..os.date("%Y/%m/%d"))
sendText(msg.chat.id, msg.message_id, '📬 | پیام شما برای کاربر [ '..MentionUser(user_id, 'html')..' ] ارسال شد !', 'html')
return sendMedia(user_id, 0, data.file_id, '📨 | #پیام_پشتیبان\n'..(data.text == 'NIL' and '' or data.text), 'html', data.type)
end
end
end
end
-------------------------------
if msg.text then
local matches = { string.lower(msg.text), msg.text, msg.text }
if matches[1] then
matches[1] = matches[1]:gsub('^[/!]','')
elseif matches[2] then
matches[2] = matches[2]:gsub('^[/!]','')
end
-------------------------------
if OwnerRank(msg.from.id) then
-------------------------------
if (matches[1] == 'reload' or matches[1] == 'ریلود' or matches[1] == 'بازنگری') then
if need.process > 0 then
sendText(msg.chat.id, msg.message_id, '💢 | عملیاتی در جریان میباشد ، لطفا در زمان دیگری از این دستور استفاده کنید !', 'html')
else
sendText(msg.chat.id, msg.message_id, '♻️ | ربات با موفقیت بازنگری شد !', 'html')
dofile('./Base.lua')
end
------------------------------------------------------
elseif (matches[1] == 'stats' or matches[1] == 'آمار' or matches[1] == 'امار') then
local ListMemberBot = redis:smembers(RedisBot..'ListMemberBot')
local DayMemberBot = redis:get(RedisBot..'Count:DayMemberBot:'..os.date("%Y/%m/%d")) or 0
local AllMessage = redis:get(RedisBot..'Count:AllMessage') or 0
local DayMessage = redis:get(RedisBot..'Count:DayMessage:'..os.date("%Y/%m/%d")) or 0
local AllSearch = redis:get(RedisBot..'Count:AllSearch') or 0
local DaySearch = redis:get(RedisBot..'Count:DaySearch:'..os.date("%Y/%m/%d")) or 0
local Text = '<b>📊 | آمار ربات به شرح زیر میباشد :\n\n👤 | کل کاربران : '..#ListMemberBot..'\n👥 | کاربران امروز : '..DayMemberBot..'\n📮 | کل پیام ها : '..AllMessage..'\n📨 | پیام های امروز : '..DayMessage..'\n🔍 | کل جستجو ها : '..AllSearch..'\n📡 |جستجو های امروز : '..DaySearch..'\n</b>'
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1] == 'send' or matches[1] == 'ارسال پیام') and msg.reply_to_message then
local result = importMedia(msg.reply_to_message)
if result.type == 'nil' then
sendText(msg.chat.id, msg.message_id, '📮 | تنها موارد قابل ارسال ❲متن / عکس / فیلم / فیلم سلفی / ویس / آهنگ / گیف / استیکر / فایل❳ میباشد !', 'html')
else
local ListMember = redis:smembers(RedisBot..'ListMemberBot')
if #ListMember == 0 then
sendText(msg.chat.id, msg.message_id, '👤 | لیست کاربران ربات خالی میباشد !', 'html')
else
need.process = need.process + 1
sendText(msg.chat.id, msg.message_id, '👤 | عملیات ارسال پیام به کاربران شروع شد !', 'html')
local data = table.split(ListMember, 2) 
for i = 1, #data do
set_timer(tonumber(i * 2), CoreMessageProc, {data[i], msg.chat.id, msg.message_id, result, 'send', #ListMember, (i == #data)})
end
end
end
------------------------------------------------------
elseif (matches[1] == 'fwd' or matches[1] == 'فوروارد پیام') and msg.reply_to_message then
local ListMember = redis:smembers(RedisBot..'ListMemberBot')
if #ListMember == 0 then
sendText(msg.chat.id, msg.message_id, '👤 | لیست کاربران ربات خالی میباشد !', 'html')
else
need.process = need.process + 1
sendText(msg.chat.id, msg.message_id, '👤 | عملیات فوروارد پیام به کاربران شروع شد !', 'html')
local data = table.split(ListMember, 2) 
for i = 1, #data do
set_timer(tonumber(i * 2), CoreMessageProc, {data[i], msg.chat.id, msg.message_id, msg.reply_to_message.message_id, 'fwd', #ListMember, (i == #data)})
end
end
------------------------------------------------------
elseif (matches[2]:match('^[Ss]et%s?[Jj]oin (-100%d+):(https://t.me/%S+)$') or matches[2]:match('^تنظیم جوین (-100%d+):(https://t.me/%S+)$')) then
local CMD_EN = {matches[2]:match('^[Ss]et%s?[Jj]oin (-100%d+):(%S+)$')}
local CMD_FA = {matches[2]:match('^تنظیم جوین (-100%d+):(%S+)$')}
local chat_id = CMD_EN[1] or CMD_FA[1]
local chat_link = CMD_EN[2] or CMD_FA[2]
if string.match(chat_link, '^https://t.me/%+(%S+)$') then
type_ = {result = 'لینک', status = 'خصوصی', link = chat_link}
else
type_ = {result = 'یوزرنیم', status = 'عمومی', link = '@'..string.match(chat_link, '^https://t.me/(%S+)$')}
end
local data = getChat(chat_id)
if data and data.ok then
if data.result.type == 'supergroup' then
redis:hset(RedisBot..':JoinChGpBot:', chat_id, 'گروه|'..type_.status..'|'..type_.link..'|'..string.gsub(data.result.title, '[<>]', ''))
Text = '🏷 گروه با موفقیت تنظیم شد !\n\n📮 نام گروه : '..string.gsub(data.result.title, '[<>]', '')..'\n🔍 شناسه : '..chat_id..'\n📌 نوع گروه : '..type_.status..'\n🌐 '..type_.result..' : '..type_.link..'\n\n📍 حتما ربات را ادمین گروه کنید !'
elseif data.result.type == 'channel' then
redis:hset(RedisBot..':JoinChGpBot:', chat_id, 'کانال|'..type_.status..'|'..type_.link..'|'..string.gsub(data.result.title, '[<>]', ''))
Text = '🏷 | کانال با موفقیت تنظیم شد !\n\n📮 نام کانال : '..string.gsub(data.result.title, '[<>]', '')..'\n🔍 شناسه : '..chat_id..'\n📌 نوع کانال : '..type_.status..'\n🌐 '..type_.result..' : '..type_.link..'\n\n📍 حتما ربات را ادمین کانال کنید !'
else
Text = '⭕️ | شناسه وارد شده نامعتبر میباشد !'
end
else
Text = '⭕️ | ابتدا ربات را در گروه یا کانال ادمین کنید !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[2]:match('^[Ss]et%s?[Jj]oin (-100%d+)$') or matches[2]:match('^تنظیم جوین (-100%d+)$')) then
local chat_id = (matches[2]:match('^[Ss]et%s?[Jj]oin (-100%d+)$') or matches[2]:match('^تنظیم جوین (-100%d+)$'))
local data = getChat(chat_id)
if data and data.ok then
if data.result.type ~= 'supergroup' then
Text = '⭕️ | شناسه وارد شده متعلق به گروه نمیباشد !'
else
if data.result and data.result.username then
redis:hset(RedisBot..':JoinChGpBot:', chat_id, 'گروه|عمومی|@'..data.result.username..'|'..string.gsub(data.result.title, '[<>]', ''))
Text = '🏷 | گروه با موفقیت تنظیم شد !\n\n📮 نام گروه : '..string.gsub(data.result.title, '[<>]', '')..'\n🔍 شناسه : '..chat_id..'\n📌 نوع گروه : عمومی\n🌐 یوزرنیم : @'..data.result.username..'\n\n📍 حتما ربات را ادمین گروه کنید !'
elseif data.result and data.result.invite_link then
redis:hset(RedisBot..':JoinChGpBot:', chat_id, 'گروه|خصوصی|'..data.result.invite_link..'|'..string.gsub(data.result.title, '[<>]', ''))
Text = '🏷 | گروه با موفقیت تنظیم شد !\n\n📮 نام گروه : '..string.gsub(data.result.title, '[<>]', '')..'\n🔍 شناسه : '..chat_id..'\n📌 نوع گروه : خصوصی\n🌐 لینک :\n'..data.result.invite_link..'\n\n📍 حتما ربات را ادمین گروه کنید !'
end
end
else
Text = '⭕️ | ابتدا ربات را در گروه ادمین کنید و دسترسی به لینک را حتما داشته باشد !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[2]:match('^[Rr]em%s?[Jj]oin (-100%d+)$') or matches[2]:match('^حذف جوین (-100%d+)$')) then
local chat_id = (matches[2]:match('^[Rr]em%s?[Jj]oin (-100%d+)$') or matches[2]:match('^حذف جوین (-100%d+)$'))
local getValue = redis:hget(RedisBot..':JoinChGpBot:', chat_id)
if getValue then
if string.match(getValue, '^گروه') then
redis:hdel(RedisBot..':JoinChGpBot:', chat_id)
Text = '🏷 | گروه با شناسه ('..chat_id..') با موفقیت حذف شد !'
else
Text = '⭕️ | شناسه وارد شده متعلق به گروه نمیباشد !'
end
else
Text = '⭕️ | گروه با شناسه ('..chat_id..') در لیست نمیباشد !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1] == 'set join' or matches[1] == 'تنظیم جوین') and msg.reply_to_message then
if not msg.reply_to_message.forward_from_chat then
Text = '⭕️ | لطفا پستی از کانال مورد نظر ارسال کنید و مجدد امتحان کنید !'
else
local chat_id = msg.reply_to_message.forward_from_chat.id
local Type = msg.reply_to_message.forward_from_chat.type
if Type ~= 'channel' then
Text = '⭕️ | تنها پست فوروارد شده از کانال قابل اجرا میباشد !'
else
local data = getChat(chat_id)
if data and data.ok then
if data.result and data.result.username then
redis:hset(RedisBot..':JoinChGpBot:', chat_id, 'کانال|عمومی|@'..data.result.username..'|'..string.gsub(data.result.title, '[<>]', ''))
Text = '🏷 | کانال با موفقیت تنظیم شد !\n\n📮 نام کانال : '..string.gsub(data.result.title, '[<>]', '')..'\n🔍 شناسه : '..chat_id..'\n📌 نوع کانال : عمومی\n🌐 یوزرنیم : @'..data.result.username..'\n\n📍 حتما ربات را ادمین کانال کنید !'
elseif data.result and data.result.invite_link then
redis:hset(RedisBot..':JoinChGpBot:', chat_id, 'کانال|خصوصی|'..data.result.invite_link..'|'..string.gsub(data.result.title, '[<>]', ''))
Text = '🏷 | کانال با موفقیت تنظیم شد !\n\n📮 نام کانال : '..string.gsub(data.result.title, '[<>]', '')..'\n🔍 شناسه : '..chat_id..'\n📌 نوع کانال : خصوصی\n🌐 لینک :\n'..data.result.invite_link..'\n\n📍 حتما ربات را ادمین کانال کنید !'
end
else
Text = '⭕️ | ابتدا ربات را در کانال ادمین کنید تا به لینک دسترسی داشته باشد !'
end
end
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1] == 'rem join' or matches[1] == 'حذف جوین') and msg.reply_to_message then
if not msg.reply_to_message.forward_from_chat then
Text = '⭕️ | لطفا پستی از کانال مورد نظر ارسال کنید و مجدد امتحان کنید !'
else
local chat_id = msg.reply_to_message.forward_from_chat.id
local Type = msg.reply_to_message.forward_from_chat.type
if Type ~= 'channel' then
Text = '⭕️ | تنها پست فوروارد شده از کانال قابل اجرا میباشد !'
elseif not redis:hget(RedisBot..':JoinChGpBot:', chat_id) then
Text = '⭕️ | کانال با شناسه ('..chat_id..') در لیست نمیباشد !'
else
redis:hdel(RedisBot..':JoinChGpBot:', chat_id)
Text = '🏷 | کانال با شناسه ('..chat_id..') با موفقیت حذف شد !'
end
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1]:match('^list%s?join$') or matches[1]:match('^لیست جوین$'))  then
local List = redis:hkeys(RedisBot..':JoinChGpBot:')
if #List == 0 then
sendText(msg.chat.id, msg.message_id, '⭕️ هیچ جوین اجباری در ربات تنظیم نشده است !', 'html')
else
Text = '📋 | لیست جوین اجباری ها :\n\n'
for k,v in pairs(List) do
local Type,Kinds,Links,Title = string.match(redis:hget(RedisBot..':JoinChGpBot:', v), '(%S+)|(%S+)|(%S+)|(.*)')
Text = Text..'📮 نام '..Type..' : '..Title..'\n🔍 شناسه : '..v..'\n📌 نوع '..Type..' : '..Kinds..'\n🌐 لینک : '..Links..'\n\n'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
end
------------------------------------------------------
elseif (matches[1]:match('^clean%s?join$') or matches[1]:match('^پاکسازی جوین ها$'))  then
local List = redis:hkeys(RedisBot..':JoinChGpBot:')
if #List == 0 then
Text = '⭕️ | هیچ جوین اجباری در ربات تنظیم نشده است !'
else
redis:del(RedisBot..':JoinChGpBot:')
Text = '🗑 | لیست جوین اجباری تنظیم شده با موفقیت پاکسازی شد !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1]:match('^set%s?admin (%d+)$') or matches[1]:match('^تنظیم ادمین (%d+)$'))  then
local CP = matches[1]:match('^set%s?admin (%d+)$') or matches[1]:match('^تنظیم ادمین (%d+)$')
if redis:sismember(RedisBot..':ListAdmins:', CP) then
Text = '👤 | کاربر [ '..MentionUser(CP)..' ] از قبل در لیست ادمین وجود داشت !'
else
redis:sadd(RedisBot..':ListAdmins:', CP)
Text = '👤 | کاربر [ '..MentionUser(CP)..' ] با موفقیت به لیست ادمین اضافه شد !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1]:match('^rem%s?admin (%d+)$') or matches[1]:match('^حذف ادمین (%d+)$'))  then
local CP = matches[1]:match('^rem%s?admin (%d+)$') or matches[1]:match('^حذف ادمین (%d+)$')
if not redis:sismember(RedisBot..':ListAdmins:', CP) then
Text = '👤 | کاربر [ '..MentionUser(CP)..' ] از قبل در لیست ادمین وجود نداشت !'
else
redis:srem(RedisBot..':ListAdmins:', CP)
Text = '👤 | کاربر [ '..MentionUser(CP)..' ] با موفقیت از لیست ادمین حذف شد !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1]:match('^list%s?admin$') or matches[1]:match('^لیست ادمین$'))  then
local List = redis:smembers(RedisBot..':ListAdmins:')
if #List == 0 then
sendText(msg.chat.id, msg.message_id, '👤 | هیچ ادمین برای ربات تنظیم نشده است !', 'html')
else
Text = '📋 | لیست ادمین ها :\n\n'
for k,v in pairs(List) do
Text = Text..k..'- '..MentionUser(v)..'\n'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
end
------------------------------------------------------
elseif (matches[1]:match('^clean%s?admin$') or matches[1]:match('^پاکسازی ادمین ها$'))  then
local List = redis:smembers(RedisBot..':ListAdmins:')
if #List == 0 then
Text = '👤 | هیچ ادمینی برای ربات تنظیم نشده است !'
else
redis:del(RedisBot..':ListAdmins:')
Text = '🗑 | لیست ادمین ها با موفقیت پاکسازی شد !'
end
sendText(msg.chat.id, msg.message_id, Text, 'html')
------------------------------------------------------
elseif (matches[1] == 'help' or matches[1] == 'راهنما') then
local Text = [[
✱ بخش راهنمای کلی ربات :

● بروز
○ Reload
◂ برای بارگذاری مجدد فایل های ربات استفاده می‌شود.
┅┅┅┅┅┅┅┅┅
● آمار
○ Stats
◂ برای دریافت آمار کلی ربات استفاده می‌شود.
┅┅┅┅┅┅┅┅┅
● ارسال پیام
○ Send
◂ پیام عادی را برای تمام کاربران ربات ارسال می‌کند. فقط با ریپلای قابل استفاده است.
┅┅┅┅┅┅┅┅┅
● فوروارد پیام
○ Fwd
◂ پیام فوروارد شده را برای تمام کاربران ربات فوروارد می‌کند. فقط با ریپلای قابل استفاده است.
┅┅┅┅┅┅┅┅┅
● تنظیم جوین (شناسه:لینک)
○ Set Join (chat_id:link)
◂ یک گروه یا کانال با لینک را به عنوان جوین اجباری تنظیم می‌کند.
┅┅┅┅┅┅┅┅┅
● تنظیم جوین (شناسه)
○ Set Join (chat_id)
◂ گروه یا کانال عمومی/خصوصی را با شناسه به عنوان جوین اجباری تنظیم می‌کند.
┅┅┅┅┅┅┅┅┅
● حذف جوین (شناسه)
○ Rem Join (chat_id)
◂ گروه یا کانال مربوط به شناسه را از لیست جوین اجباری حذف می‌کند.
┅┅┅┅┅┅┅┅┅
● تنظیم جوین (ریپلی)
○ Set Join (Reply)
◂ جوین اجباری را با فوروارد پست از کانال تنظیم می‌کند.
┅┅┅┅┅┅┅┅┅
● حذف جوین (ریپلی)
○ Rem Join (Reply)
◂ کانال فوروارد شده را از لیست جوین اجباری حذف می‌کند.
┅┅┅┅┅┅┅┅┅
● لیست جوین
○ List Join
◂ تمامی کانال‌ها و گروه‌های تنظیم شده به عنوان جوین اجباری را نمایش می‌دهد.
┅┅┅┅┅┅┅┅┅
● پاکسازی جوین ها
○ Clean Join
◂ تمام جوین‌های تنظیم شده را پاک می‌کند.
┅┅┅┅┅┅┅┅┅
⎉ کل بخش ادمینی :
● Set Admin [id]
● Rem Admin [id]
● List Admin
● Clean Admin
○ تنظیم ادمین [شناسه]
○ حذف ادمین [شناسه]
○ لیست ادمین
○ پاکسازی ادمین ها
┅┅┅┅┅┅┅┅┅
]]
sendText(msg.chat.id, msg.message_id, Text, 'html')
end
end -- is_owner
end -- msg.text
end -- is_private
end
end
function CoreQuery(msg)
if msg and msg.data then
local callback = msg.data
local matches,count = callback:match('^(.*):(%d+)$')
print(color.yellow[1]..'➲ Private : '..color.magenta[1]..'['..callback..']'..color.green[1]..'['..os.date("%H:%M:%S")..']')
---------------------
if string.match(callback, '^Page:(%d+)_(%d+)_(%d+)$') then
local countSite,countPage,countVideo = string.match(callback, '^Page:(%d+)_(%d+)_(%d+)$')
if redis:get('CLimit:'..callback..':'..msg.from.id) then
	return false
else
	redis:setex('CLimit:'..callback..':'..msg.from.id, 3, true)
end
local alpha = WebSite[tonumber(countSite)] or {key = 'AllMovies', type = 1, genre = 0}
local LoadTable = loadFromJSON(alpha.key, tonumber(countPage))
if LoadTable then
extra = LoadTable
else
extra = extractMovies({page = countPage, type = alpha.type, genre = alpha.genre})
if extra ~= '{}' then
local file = io.open('./Data/'..alpha.key..'_'..tonumber(countPage)..'.txt', 'w')
file:write(extra)
file:close()
end
end
local data = json.decode(extra)
if #data == 0 then
answerCallbackQuery(msg.id, '• در این صفحه هیچ فیلمی یافت نشد !')
elseif not data[tonumber(countVideo)] then
answerCallbackQuery(msg.id, '• این فیلم در سایت موجود نمیباشد !')
else
local nextPage = tonumber(countPage) + 1
local backPage = tonumber(countPage) - 1
if tonumber(countPage) == 1 then
keyboard_page = {{text = '🔻 صفحه بعدی', callback_data = 'Page:'..tonumber(countSite)..'_'..nextPage..'_1'}}
else
keyboard_page = {{text = '🔺 صفحه قبل', callback_data = 'Page:'..tonumber(countSite)..'_'..backPage..'_1'},{text = '🔻 صفحه بعدی', callback_data = 'Page:'..tonumber(countSite)..'_'..nextPage..'_1'}}
end
local next_key = tonumber(countVideo) + 1
local back_key = tonumber(countVideo) - 1
local result = data[tonumber(countVideo)]
if string.match(result.link, '/series/') then
key_input = 'IS'
else
key_input = 'IM'
end
local key_value = {{text = '─┅━━━ °• '..alpha.value..' •° ━━━┅─', callback_data = 'Showe:1'}}
if result.photo ~= '' then
key_1 = {{text = '👁‍🗨 نمایش عکس', url = result.photo},{text = '🏆 امتیاز ️: '..result.imdb, callback_data = 'Showe:1'}}
else
key_1 = {{text = '🏆 امتیاز ️: '..result.imdb, callback_data = 'Showe:1'}}
end
if data[next_key] and data[back_key] then
keyboard = {
key_value,
key_1,
{
{text = '🎞 فیلم ️: ('..tonumber(countVideo)..' / '..tonumber(#data)..')', callback_data = 'Showe:1'},{text = '📖 صفحه : '..tonumber(countPage), callback_data = 'Showe:1'}
},
{
{text = 'فیلم قبلی ◀️', callback_data = 'Page:'..tonumber(countSite)..'_'..countPage..'_'..back_key},
{text = '▶️ فیلم بعدی', callback_data = 'Page:'..tonumber(countSite)..'_'..countPage..'_'..next_key}
},
keyboard_page,
{
{text = 'اطلاعات و دانلود فیلم 🎬', callback_data = key_input..':'..tonumber(countSite)..'_'..countPage..'_'..countVideo..'_'..result.code}
}
}
elseif data[next_key] then
keyboard = {
key_value,
key_1,
{
{text = '🎞 فیلم ️: ('..tonumber(countVideo)..' / '..tonumber(#data)..')', callback_data = 'Showe:1'},{text = '📖 صفحه : '..tonumber(countPage), callback_data = 'Showe:1'}
},
{
{text = '▶️ فیلم بعدی', callback_data = 'Page:'..tonumber(countSite)..'_'..countPage..'_'..next_key}
},
keyboard_page,
{
{text = 'اطلاعات و دانلود فیلم 🎬', callback_data = key_input..':'..tonumber(countSite)..'_'..countPage..'_'..countVideo..'_'..result.code}
},
}
else
keyboard = {
key_value,
key_1,
{
{text = '🎞 فیلم ️: ('..tonumber(countVideo)..' / '..tonumber(#data)..')', callback_data = 'Showe:1'},{text = '📖 صفحه : '..tonumber(countPage), callback_data = 'Showe:1'}
},
{
{text = 'فیلم قبلی ◀️', callback_data = 'Page:'..tonumber(countSite)..'_'..countPage..'_'..back_key}
},
keyboard_page,
{
{text = 'اطلاعات و دانلود فیلم 🎬', callback_data  = key_input..':'..tonumber(countSite)..'_'..countPage..'_'..countVideo..'_'..result.code}
}
}
end
table.insert(keyboard, {{text = 'صفحه اصلی 🏠', callback_data = 'Start:1'}})
local title_full = string.gsub(result.title_full, 'سانسور (با .*)', 'سانسور')
local Text = '<blockquote><b>'..result.title..'</b></blockquote>\n<blockquote>'..title_full..'</blockquote>'
local preview = {url = tostring(result.photo), show_above_text = true, prefer_large_media = false, is_disabled = false}
editText(msg.message.chat.id, msg.message.message_id, Text, 'html', keyboard, 1, preview)
end
end
------------------------------------------------------------------------------------------------------------
if string.match(callback, '^IM:(%d+)_(%d+)_(%d+)_(.*)$') and is_JoinChannel(msg, msg.message.chat.id, msg.message.message_id, msg.id) then
local countSite,Page,countVideo,code = string.match(callback, '^IM:(%d+)_(%d+)_(%d+)_(.*)$')
local alpha = WebSite[tonumber(countSite)] or {key = 'AllMovies', type = 1, genre = 0}
if redis:get('CLimit:'..callback..':'..msg.from.id) then
	return false
else
	redis:setex('CLimit:'..callback..':'..msg.from.id, 3, true)
end
if not loadFromJSON(alpha.key, tonumber(Page)) then
local extra = extractMovies({page = Page, type = alpha.type, genre = alpha.genre})
if extra ~= '{}' then
local file = io.open('./Data/'..alpha.key..'_'..tonumber(Page)..'.txt', 'w')
file:write(extra)
file:close()
end
end
local data_json = loadFromJSON(alpha.key, tonumber(Page))
local ultra = json.decode(data_json)
local result = getCodeTable(ultra, code)
if result then
local data = extractInfoMovie(result)
if data.movie_info and data.movie_info.title ~= '' then
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n'
local keyboard = {}
if data.link_dubbed then
table.insert(keyboard, {{text = '─┅━━━ °• دوبله فارسی ها •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(data.link_dubbed) do
table.insert(keyboard, {{text = '📥 | '..v.title..' 🎙', url = v.url}})
end
end
if data.link_hardsub then
table.insert(keyboard, {{text = '─┅━━━ °• زیرنویس فارسی ها •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(data.link_hardsub) do
table.insert(keyboard, {{text = '📥 | '..v.title..' ✏️', url = v.url}})
end
end
if #keyboard ~= 0 then
answerCallbackQuery(msg.id, '• لینک های دانلود برای شما ارسال شد !')
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
sendText(msg.message.chat.id, 0, Text, 'html', keyboard, 1, preview)
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', true)
end
else
answerCallbackQuery(msg.id, '• متاسفانه نتوانستم فیلم را دریافت کنم !', true)
end
else
answerCallbackQuery(msg.id, '• متاسفانه نتوانستم فیلم را دریافت کنم !', true)
end
end
------------------------------------------------------------------------------------------------------------
if string.match(callback, '^IS:(%d+)_(%d+)_(%d+)_(.*)$') and is_JoinChannel(msg, msg.message.chat.id, msg.message.message_id, msg.id) then
local countSite,Page,countVideo,code = string.match(callback, '^IS:(%d+)_(%d+)_(%d+)_(.*)$')
local alpha = WebSite[tonumber(countSite)] or {key = 'AllMovies', type = 1, genre = 0}
if redis:get('CLimit:'..callback..':'..msg.from.id) then
	return false
else
	redis:setex('CLimit:'..callback..':'..msg.from.id, 3, true)
end
if not loadFromJSON(alpha.key, tonumber(Page)) then
local extra = extractMovies({page = Page, type = alpha.type, genre = alpha.genre})
if extra ~= '{}' then
local file = io.open('./Data/'..alpha.key..'_'..tonumber(Page)..'.txt', 'w')
file:write(extra)
file:close()
end
end
local data_json = loadFromJSON(alpha.key, tonumber(Page))
local ultra = json.decode(data_json)
local result = getCodeTable(ultra, code)
if result then
if not loadFromJSON(code, tonumber(Page)) then
local data = extractInfoSeries(result)
if data and data.series and data.series[1] and ((#data.series[1].hardsub ~= 0) or (#data.series[1].dubbled ~= 0)) then
local ultra = json.encode(data)
local file = io.open('./Data/'..code..'_'..tonumber(Page)..'.txt', 'w')
file:write(ultra)
file:close()
end
end
local eseyGet = loadFromJSON(code, tonumber(Page))
if not eseyGet then
answerCallbackQuery(msg.id, '• اطلاعاتی از این فیلم در دسترس نمیباشد !', true)
return
end
local data = json.decode(eseyGet)
if data and data.series and data.series[1] and ((#data.series[1].hardsub ~= 0) or (#data.series[1].dubbled ~= 0)) then
local keyboard = {}
if data.series and #data.series ~= 0 then
local row = {}
for k,v in pairs(data.series) do
table.insert(row, {text = '• '..v.season, callback_data = 'DL:'..k..'_'..tonumber(countSite)..'_'..Page..'_'..code})
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
row = {}
end
end
if #row > 0 then
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
else
table.insert(keyboard, row)
end
end
end
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n\n🔻 | لطفا فصل سریال مورد نظر خود را انتخاب کنید :'
if #keyboard ~= 0 then
table.insert(keyboard, {{text = '• بازگشت ↪️', callback_data = 'Page:'..countSite..'_'..Page..'_'..countVideo}})
local link_preview_options = {_ = 'linkPreviewOptions', url = data.movie_info.photo, show_above_text = true, force_small_media = false, force_large_media = false, is_disabled = false}
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
editText(msg.message.chat.id, msg.message.message_id, Text, 'html', keyboard, 1, preview)
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', true)
end
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد !', true)
end
else
answerCallbackQuery(msg.id, '• متاسفانه نتوانستم فیلم را دریافت کنم !', true)
end
end
------------------------------------------------------------------------------------------------------------
if string.match(callback, '^DL:(%d+)_(%d+)_(%d+)_(.*)$') and is_JoinChannel(msg, msg.message.chat.id, msg.message.message_id, msg.id) then
local countSession,countSite,Page,code = string.match(callback, '^DL:(%d+)_(%d+)_(%d+)_(.*)$')
local alpha = WebSite[tonumber(countSite)] or {key = 'AllMovies', type = 1, genre = 0}
if redis:get('CLimit:'..callback..':'..msg.from.id) then
	return false
else
	redis:setex('CLimit:'..callback..':'..msg.from.id, 3, true)
end
if not loadFromJSON(alpha.key, tonumber(Page)) then
local extra = extractMovies({page = Page, type = alpha.type, genre = alpha.genre})
if extra ~= '{}' then
local file = io.open('./Data/'..alpha.key..'_'..tonumber(Page)..'.txt', 'w')
file:write(extra)
file:close()
end
end
local data_json = loadFromJSON(alpha.key, tonumber(Page))
local ultra = json.decode(data_json)
local result = getCodeTable(ultra, code)
if not loadFromJSON(code, tonumber(Page)) then
local data = extractInfoSeries(result)
if data and data.series and data.series[1] and ((#data.series[1].hardsub ~= 0) or (#data.series[1].dubbled ~= 0)) then
local ultra = json.encode(data)
local file = io.open('./Data/'..code..'_'..tonumber(Page)..'.txt', 'w')
file:write(ultra)
file:close()
end
end
if result then
local eseyGet = loadFromJSON(code, tonumber(Page))
if not eseyGet then
answerCallbackQuery(msg.id, '• اطلاعاتی از این فیلم در دسترس نمیباشد !', true)
return
end
local data = json.decode(eseyGet)
local org = data.series[tonumber(countSession)]
if org then
if #org.dubbled ~= 0 then
local keyboard = {}
local new_keyboard = {}
local new_session_name = string.match(org.season, 'فصل (%S+)')
table.insert(keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' دوبله فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(org.dubbled) do
local quality_keyboard = {}
table.insert(quality_keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' دوبله فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
local quality_btn = {{text = '🎬 کیفیت : '..v.quality, callback_data = 'Showe:1'}}
table.insert(keyboard, quality_btn)
table.insert(quality_keyboard, quality_btn)
if v.links ~= 0 then
local row = {}
for _,i in pairs(v.links) do
table.insert(row, {text = '📥 | '..i.name, url = i.url})
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
table.insert(quality_keyboard, {row[2], row[1]})
row = {}
end
end
if #row > 0 then
table.insert(keyboard, row)
table.insert(quality_keyboard, row)
end
end
table.insert(new_keyboard, quality_keyboard)
end
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n'
if #keyboard ~= 0 then
answerCallbackQuery(msg.id, '• لینک های دانلود برای شما ارسال شد !')
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
local extra = sendText(msg.message.chat.id, 0, Text, 'html', keyboard, 1, preview)
if extra and not extra.ok then
sendText(msg.message.chat.id, 0, Text, 'html', nil, nil, preview)
for k,v in pairs(new_keyboard) do
sendText(msg.message.chat.id, 0, '🔻🔻🔻🔻🔻🔻🔻🔻🔻🔻', 'html', v, 1)
end
end
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', true)
end
end
if #org.hardsub ~= 0 then
local keyboard = {}
local new_keyboard = {}
local new_session_name = string.match(org.season, 'فصل (%S+)')
table.insert(keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' زیرنویس فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(org.hardsub) do
local quality_keyboard = {}
table.insert(quality_keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' زیرنویس فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
local quality_btn = {{text = '🎬 کیفیت : '..v.quality, callback_data = 'Showe:1'}}
table.insert(keyboard, quality_btn)
table.insert(quality_keyboard, quality_btn)
if v.links ~= 0 then
local row = {}
for _,i in pairs(v.links) do
table.insert(row, {text = '📥 | '..i.name, url = i.url})
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
table.insert(quality_keyboard, {row[2], row[1]})
row = {}
end
end
if #row > 0 then
table.insert(keyboard, row)
table.insert(quality_keyboard, row)
end
end
table.insert(new_keyboard, quality_keyboard)
end
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n'
if #keyboard ~= 0 then
answerCallbackQuery(msg.id, '• لینک های دانلود برای شما ارسال شد !')
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
local extra = sendText(msg.message.chat.id, 0, Text, 'html', keyboard, 1, preview)
if extra and not extra.ok then
sendText(msg.message.chat.id, 0, Text, 'html', nil, nil, preview)
for k,v in pairs(new_keyboard) do
sendText(msg.message.chat.id, 0, '🔻🔻🔻🔻🔻🔻🔻🔻🔻🔻', 'html', v, 1)
end
end
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', true)
end
end
end
end
end
------------------------------------------------------------------------------------------------------------
if string.match(callback, '^DLI:(%d+)_(.*)$') and is_JoinChannel(msg, msg.message.chat.id, msg.message.message_id, msg.id) then
local countSession,code = string.match(callback, '^DLI:(%d+)_(.*)$')
if redis:get('CLimit:'..callback..':'..msg.from.id) then
	return false
else
	redis:setex('CLimit:'..callback..':'..msg.from.id, 3, true)
end
if not loadFromJSON(code, 0) then
local data = extractInfoSeries(is_link.url..'/'..code)
if data and data.series and data.series[1] and ((#data.series[1].hardsub ~= 0) or (#data.series[1].dubbled ~= 0)) then
local ultra = json.encode(data)
local file = io.open('./Data/'..code..'_0.txt', 'w')
file:write(ultra)
file:close()
end
end
local eseyGet = loadFromJSON(code, 0)
if not eseyGet then
answerCallbackQuery(msg.id, '• اطلاعاتی از این سریال در دسترس نمیباشد !', true)
return
end
local data = json.decode(eseyGet)
local org = data.series[tonumber(countSession)]
if org then
if #org.dubbled ~= 0 then
local keyboard = {}
local new_keyboard = {}
local new_session_name = string.match(org.season, 'فصل (%S+)')
table.insert(keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' دوبله فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(org.dubbled) do
local quality_keyboard = {}
table.insert(quality_keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' دوبله فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
local quality_btn = {{text = '🎬 کیفیت : '..v.quality, callback_data = 'Showe:1'}}
table.insert(keyboard, quality_btn)
table.insert(quality_keyboard, quality_btn)
if v.links ~= 0 then
local row = {}
for _,i in pairs(v.links) do
table.insert(row, {text = '📥 | '..i.name, url = i.url})
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
table.insert(quality_keyboard, {row[2], row[1]})
row = {}
end
end
if #row > 0 then
table.insert(keyboard, row)
table.insert(quality_keyboard, row)
end
end
table.insert(new_keyboard, quality_keyboard)
end
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n'
if #keyboard ~= 0 then
answerCallbackQuery(msg.id, '• لینک های دانلود برای شما ارسال شد !')
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
local extra = sendText(msg.message.chat.id, 0, Text, 'html', keyboard, 1, preview)
if extra and not extra.ok then
sendText(msg.message.chat.id, 0, Text, 'html', nil, nil, preview)
for k,v in pairs(new_keyboard) do
sendText(msg.message.chat.id, 0, '🔻🔻🔻🔻🔻🔻🔻🔻🔻🔻', 'html', v, 1)
end
end
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', true)
end
end
if #org.hardsub ~= 0 then
local keyboard = {}
local new_keyboard = {}
local new_session_name = string.match(org.season, 'فصل (%S+)')
table.insert(keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' زیرنویس فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
for k,v in pairs(org.hardsub) do
local quality_keyboard = {}
table.insert(quality_keyboard, {{text = '─┅━━━ °• فصل '..new_session_name..' زیرنویس فارسی •° ━━━┅─', callback_data = 'Showe:1'}})
local quality_btn = {{text = '🎬 کیفیت : '..v.quality, callback_data = 'Showe:1'}}
table.insert(keyboard, quality_btn)
table.insert(quality_keyboard, quality_btn)
if v.links ~= 0 then
local row = {}
for _,i in pairs(v.links) do
table.insert(row, {text = '📥 | '..i.name, url = i.url})
if #row == 2 then
table.insert(keyboard, {row[2], row[1]})
table.insert(quality_keyboard, {row[2], row[1]})
row = {}
end
end
if #row > 0 then
table.insert(keyboard, row)
table.insert(quality_keyboard, row)
end
end
table.insert(new_keyboard, quality_keyboard)
end
local Text = '<blockquote><b>'..data.movie_info.title..'</b></blockquote>\n🗓 | سال انتشار : '..data.movie_info.year..'\n⏱️ | زمان : '..data.movie_info.times..'\n🏆 | امتیاز : '..data.movie_info.imdb..'\n🏷 | درباره : '..data.movie_info.description..'\n'
if #keyboard ~= 0 then
answerCallbackQuery(msg.id, '• لینک های دانلود برای شما ارسال شد !')
local preview = {url = data.movie_info.photo, show_above_text = true, prefer_large_media = false, is_disabled = false}
local extra = sendText(msg.message.chat.id, 0, Text, 'html', keyboard, 1, preview)
if extra and not extra.ok then
sendText(msg.message.chat.id, 0, Text, 'html', nil, nil, preview)
for k,v in pairs(new_keyboard) do
sendText(msg.message.chat.id, 0, '🔻🔻🔻🔻🔻🔻🔻🔻🔻🔻', 'html', v, 1)
end
end
else
answerCallbackQuery(msg.id, '• متاسفانه لینک های دانلود فیلم موجود نمیباشد در صورت انتشار فیلم قرار داده خواهد شد !', true)
end
end
end
end
--------------------------------
if (matches == 'Genre') then
local keyboard = {
	{
		{text = '• فیلم و سریال 🎬', callback_data = 'SetGenre:2'}
	},
	{
		{text = '• فیلم سینمایی 🎥', callback_data = 'SetGenre:1'},
		{text = '• سریال جدید 💎', callback_data = 'SetGenre:3'}
	},
	{
		{text = '• بازگشت ↪️', callback_data = 'Start:1'}
	},
}
local Text = '<b>📍 | لطفا یک مورد را برای دسته بندی انتخاب کنید :</b>'
editText(msg.message.chat.id, msg.message.message_id, Text, 'html', keyboard, 1)
end
--------------------------------
if string.match(callback, '^SetGenre:(%d+)$') then
local codeDaste = string.match(callback, '^SetGenre:(%d+)$')
local org = {}
if tonumber(codeDaste) == 1 then
dataTable = {10, 22}
elseif tonumber(codeDaste) == 2 then
dataTable = {30, 42}
else
dataTable = {50, 62}
end

for i = dataTable[1], dataTable[2] do
table.insert(org, tonumber(i))
end
local keyboard = {
	{
		{text = '• هیجان انگیز 😱', callback_data = 'Page:'..org[1]..'_1_1'}
	},
	{
		{text = '• کمدی 🤣' , callback_data = 'Page:'..org[2]..'_1_1'},
		{text = '• درام ❤️‍🩹', callback_data = 'Page:'..org[3]..'_1_1'}
	},
	{
		{text = '• معمایی ⁉️', callback_data = 'Page:'..org[4]..'_1_1'},
		{text = '• علمی تخیلی 👽', callback_data = 'Page:'..org[5]..'_1_1'}
	},
	{
		{text = '• فانتزی ✨', callback_data = 'Page:'..org[6]..'_1_1'},
		{text = '• اکشن 🥷🏻', callback_data = 'Page:'..org[7]..'_1_1'}
	},
	{
		{text = '• عاشقانه ♥️', callback_data = 'Page:'..org[8]..'_1_1'},
		{text = '• ماجراجویی 🎒', callback_data = 'Page:'..org[9]..'_1_1'}
	},
	{
		{text = '• انیمیشن 👻', callback_data = 'Page:'..org[10]..'_1_1'},
		{text = '• انیمه 🎃', callback_data = 'Page:'..org[11]..'_1_1'}
	},
	{
		{text = '• ترسناک 👹', callback_data = 'Page:'..org[12]..'_1_1'},
		{text = '• جنایی 💀', callback_data = 'Page:'..org[13]..'_1_1'}
	},
	{
		{text = '• بازگشت ↪️', callback_data = 'Genre:1'}
	},
}
local Text = '<b>📍 | لطفا ژانر مورد نظر را انتخاب کنید :</b>'
editText(msg.message.chat.id, msg.message.message_id, Text, 'html', keyboard, 1)
end
--------------------------------
if matches == 'Help' then
local Text = [[
<b>
🎬 | راهنمای استفاده از بخش جستجوی فیلم و سریال

🔹 | برای دسترسی سریع و آسان به آرشیو فیلم‌ها و سریال‌ها، تنها کافی است مراحل زیر را دنبال کنید :

1️⃣ | بر روی دکمه «🔎 جستجوی فیلم» کلیک نمایید.
2️⃣ | نام فیلم یا سریال موردنظر خود را به زبان فارسی یا انگلیسی وارد کنید.
3️⃣ | پس از وارد کردن نام، لیستی از نتایج مرتبط برای شما نمایش داده خواهد شد.

📍 | در نتایج نمایش داده ‌شده میتوانید اطلاعات کاملی را مشاهده کنید از جمله :

🔻 | سال انتشار
🔻 | امتیاز اثر
🔻 | وضعیت دوبله یا زیرنویس
🔻 | لینک دسترسی

📌 | توجه داشته باشید:

• هرچه نام اثر را دقیق‌تر وارد کنید، نتایج مرتبط‌تری دریافت خواهید کرد.

🔅 | با استفاده از این قابلیت، بدون نیاز به پیمایش طولانی در میان محتواها، تنها در چند ثانیه به فیلم یا سریال دلخواه خود دسترسی خواهید داشت.

از همراهی شما سپاسگزاریم 🌟
</b>
]]
editText(msg.message.chat.id, msg.message.message_id, Text, 'html', {{{text = '• بازگشت ↪️', callback_data = 'Start:1'}}}, 1)
end
--------------------------------
if matches == 'Showe' then
answerCallbackQuery(msg.id, '• این مورد برای نمایش میباشد !')
end
--------------------------------
if matches == 'Start' then
MenuStartBot(msg.message.chat.id, msg.message.message_id, msg.from.id, true)
end
--------------------------------
if matches == 'Exit' then
editText(msg.message.chat.id, msg.message.message_id, '🔘 | فهرست با موفقیت بسته شد !', 'html')
end
--------------------------------
if matches == 'Support' then
if OwnerRank(msg.from.id) then
	return answerCallbackQuery(msg.id, '• این بخش تنها برای کاربران عادی میباشد !')
end
if redis:get('CLimit:'..callback..':'..msg.from.id) then
	return false
else
	redis:setex('CLimit:'..callback..':'..msg.from.id, 3, true)
end
deletemessage(msg.message.chat.id, msg.message.message_id)
redis:setex(RedisBot..':SystemBotCheck:'..msg.from.id, 1600, 'ReportSupport')
local TextSuppourt = '<b>📨 | پیام خود را برای ارسال به پشتیبانی ارسال کنید :\n\n📍 | انصراف : /start</b>'
sendText(msg.message.chat.id, 0, TextSuppourt, 'html')
end
--------------------------------
end
end
----------------------------------------------------------
function CoreInlineQuery(msg)
if msg and msg.query and string.len(msg.query) > 2 then
if need.username_bot == '' then
local extra = getMe()
if extra then
if extra and extra.ok and extra.result then
if extra.result and extra.result.username then
need.username_bot = extra.result.username
end
end
end
end
local data = SearchMovie(msg.query)
if #data ~= 0 then
local i = 1
local results = {}
for k,v in pairs(data) do
if v and v.meta_data and v.title and v._formatted.post_id and (string.match(v.meta_data, 'فیلم') or string.match(v.meta_data, 'سریال')) then
is_dubbled = v.is_dubbled and 'دوبله فارسی |' or ''
is_hardsub = v.is_hardsub and ' زیرنویس فارسی' or ''
NewSubDub = is_dubbled..is_hardsub
if NewSubDub ~= '' then
description = v.meta_data..' | '..NewSubDub
description = description:gsub('|$', '')
else
description = v.meta_data
end
local Text = '<blockquote><b>'..v.title..'</b></blockquote>\n🗓 | سال انتشار : '..(v._formatted.year or '')..'\n🏆 | امتیاز : '..(v._formatted.rating or '')..'\n🎙 | دوبله : '..(v.is_dubbled and 'دارد' or '---')..'\n✏️ | زیرنویس : '..(v.is_hardsub and 'دارد' or '---')..'\n🖼 | کاور فیلم : <a href=\"'..is_link.url_photo..v.image..'\">مشاهده</a>'
local Keys = string.match(v.meta_data, 'فیلم') and 'M' or 'S'
table.insert(results, {type = "article",id = tostring(i), title = clean_string(v.title_fa or '')..' | '..v.title..'', description = description, thumb_url = is_link.url_photo..v.image, input_message_content = {message_text = Text, parse_mode = "HTML"}, reply_markup = {inline_keyboard = {{{text = "📤 دانلود / مشاهده", url = 'https://t.me/'..need.username_bot..'?start='..Keys..'_'..v._formatted.post_id}}}}})
i = i + 1
end
end
redis:incr(RedisBot..'Count:AllSearch')
redis:incr(RedisBot..'Count:DaySearch:'..os.date("%Y/%m/%d"))
answerInlineQuery(msg.id, results, 0, true)
end
end
end
----------------------------------------------------------
function RunCore()
while true do
	LastUpdate = LastUpdate or 0
		local res = getUpdates(LastUpdate + 1)
		if res then
			for i,v in ipairs(res.result) do
				LastUpdate = v.update_id
				if v.message then
					Core(v.message)
				elseif v.inline_query then
					CoreInlineQuery(v.inline_query)
				elseif v.callback_query then
					local msg = v.callback_query
					v.inline_id = msg.inline_message_id
					if not v.inline_id then
						CoreQuery(msg)
					end
				end
			end
		else
			print('>>>> Error While <<<')
		end --r
		for timer_id, timer_data in pairs(data_timer) do
			if os.time() >= timer_data.run_in then
				xpcall(timer_data.def, errorMessage, timer_data.argv)
				table.remove(data_timer, timer_id)
			end
		end
	end --w
end --f
--------------------------------------------------------------------------------------------------------
return RunCore()