(function () { 'use strict'; var unic_id = Lampa.Storage.get('fxapi_uid', ''); if (!unic_id) { unic_id = Lampa.Utils.uid(16); Lampa.Storage.set('fxapi_uid', unic_id); } var proxy_url = Lampa.Storage.get('fxapi_proxy', 'https://cors.jacred.stream/'); if (proxy_url && proxy_url.charAt(proxy_url.length - 1) !== '/') proxy_url += '/'; var api_url = 'http://filmixapp.vip/api/v2/'; var ping_auth; function getToken() { return Lampa.Storage.get('fxapi_token', ''); } function devToken(token) { token = typeof token === 'string' ? token : getToken(); return 'app_lang=ru_RU&user_dev_apk=2.2.13&user_dev_id=' + unic_id + '&user_dev_name=Xiaomi+24069PC21G&user_dev_os=12&user_dev_token=' + token + '&user_dev_vendor=Xiaomi'; } function apiPath(path) { return proxy_url + api_url + path; } function proxyPhotoUrl(url) { if (!url) return ''; if (url.indexOf('//') === 0) url = 'https:' + url; else if (url.charAt(0) === '/') url = 'https://filmixapp.vip' + url; else if (url.indexOf('http://') === 0) url = 'https://' + url.substring(7); if (url.indexOf('filmix') > -1 || url.indexOf('thumbs.') > -1) { return proxy_url + url; } return url; } function isPlaylistMap(playlist) { return playlist && !Array.isArray(playlist) && Object.keys(playlist).length > 0; } function normalizePostResponse(data) { if (!data || !data.player_links) return data; var pl = data.player_links; if (Array.isArray(pl.playlist) && !pl.playlist.length) { pl.playlist = null; } return data; } function seasonLabel(key) { return key === '-1' ? '1' : key; } function playlistSeasonKeys(playlist) { if (!isPlaylistMap(playlist)) return []; return Object.keys(playlist).sort(function (a, b) { return parseInt(a, 10) - parseInt(b, 10); }); } function episodeMap(episode_voice) { if (!episode_voice) return {}; if (Array.isArray(episode_voice)) { var mapped = {}; for (var i = 0; i < episode_voice.length; i++) { mapped[String(i + 1)] = episode_voice[i]; } return mapped; } return episode_voice; } function isBlockedTranslation(name) { return typeof name === 'string' && name.toLowerCase().indexOf('заблокировано ') === 0; } function hasStreamLinks(data) { var pl = data && data.player_links; if (!pl) return false; if (pl.movie && pl.movie.length) return true; if (isPlaylistMap(pl.playlist)) return true; return false; } function getProDaysLeft(proDate) { if (proDate == null || proDate === '') return null; if (typeof proDate === 'number') { var ms = proDate > 9999999999 ? proDate : proDate * 1000; return Math.max(0, Math.ceil((ms - Date.now()) / 86400000)); } var str = ('' + proDate).trim(); var match = str.match(/(\d{2})\.(\d{2})\.(\d{4})/); if (match) str = match[3] + '-' + match[2] + '-' + match[1]; var ts = Date.parse(str); if (isNaN(ts)) return null; return Math.max(0, Math.ceil((ts - Date.now()) / 86400000)); } function normalizeProfile(raw) { if (!raw || typeof raw !== 'object') return null; var user = raw.user_data || raw; if (!user || typeof user !== 'object') return null; var login = user.login || user.user_login || ''; var name = user.display_name || user.name || user.username || login; if (!login && !name) return null; var photo = user.avatar || user.photo || user.avatar_url || user.user_photo || user.img || user.foto || user.image || user.avatarUrl || ''; photo = proxyPhotoUrl(photo); var proDays = null; var directDays = user.pro_days != null ? user.pro_days : (user.days_left != null ? user.days_left : (user.days != null ? user.days : user.day_count)); if (directDays != null && directDays !== '') { proDays = parseInt(directDays, 10); if (isNaN(proDays)) proDays = null; } if (proDays == null && user.pro_date) proDays = getProDaysLeft(user.pro_date); return { login: login, name: name, photo: photo, is_pro: !!user.is_pro, is_pro_plus: !!user.is_pro_plus, pro_date: user.pro_date || '', pro_days: proDays, quality: user.is_pro_plus ? 2160 : (user.is_pro ? 1080 : 720), videoserver: user.videoserver || '', email: user.email || user.mail || '', id: user.id || user.user_id || '' }; } function applyQualityFromProfile(user) { window.fxapi.max_qualitie = 720; if (user.is_pro_plus) window.fxapi.max_qualitie = 2160; else if (user.is_pro) window.fxapi.max_qualitie = 1080; } function getSubscriptionLabel(profile) { if (!profile) return Lampa.Lang.translate('filmix_sub_free'); if (profile.is_pro_plus) return 'PRO+'; if (profile.is_pro) return 'PRO'; return Lampa.Lang.translate('filmix_sub_free'); } function renderFxProfile() { var box = $('[data-name="fxapi_profile"]'); if (!box.length) return; var profile = normalizeProfile(Lampa.Storage.get('fxapi_status', {})); var html = ''; if (!profile) { html = '
' + Lampa.Lang.translate('filmix_nodevice') + '
'; } else { var rows = []; var badge = getSubscriptionLabel(profile); rows.push('
' + badge + '
'); if ((profile.is_pro || profile.is_pro_plus) && profile.pro_days != null) { rows.push(Lampa.Lang.translate('filmix_sub_days') + ': ' + profile.pro_days + ''); } if ((profile.is_pro || profile.is_pro_plus) && profile.pro_date) { rows.push(Lampa.Lang.translate('filmix_pro_until') + ' ' + profile.pro_date); } rows.push(Lampa.Lang.translate('filmix_max_quality') + ': ' + profile.quality + 'p'); if (profile.videoserver) { rows.push(Lampa.Lang.translate('filmix_video_server') + ': ' + profile.videoserver); } if (profile.email) { rows.push(profile.email); } var avatarLetter = (profile.name || profile.login).charAt(0).toUpperCase(); var avatar = profile.photo ? '' : '
' + avatarLetter + '
'; html = '
' + '
' + '
' + avatar + '
' + '
' + '
' + (profile.name || profile.login) + '
' + (profile.login && profile.login !== profile.name ? '' : '') + '
' + rows.join('
') + '
' + '
'; } box.html(html); box.find('img').on('error', function () { var letter = box.find('.fxapi-profile__title').text().charAt(0).toUpperCase() || '?'; $(this).replaceWith('
' + letter + '
'); }); } function fetchUserProfile(token, callback, onError) { var network = new Lampa.Reguest(); network.timeout(8000); network.silent(Lampa.Utils.addUrlComponent(apiPath('user_profile'), devToken(token)), function (json) { if (json && json.user_data) { applyQualityFromProfile(json.user_data); Lampa.Storage.set('fxapi_status', json.user_data); var profile = normalizeProfile(json); if (callback) callback(profile, json.user_data); } else { Lampa.Storage.set('fxapi_status', {}); window.fxapi.max_qualitie = 720; window.fxapi.is_max_qualitie = false; if (callback) callback(null); } renderFxProfile(); }, function (a, c) { if (onError) onError(a, c); else Lampa.Noty.show(network.errorDecode(a, c)); }); } function parseLinkQualities(link) { var match = link && link.match(/\[([\d,\s]*)\]/); if (!match) return []; return match[1].split(',').map(function (q) { return parseInt(q, 10); }).filter(function (q) { return q > 0 && q <= window.fxapi.max_qualitie; }); } function maxQuality(list) { if (!list || !list.length) return 0; return Math.max.apply(null, list); } if (!window.fxapi) { window.fxapi = { max_qualitie: 720, is_max_qualitie: false }; } function fxapi(component, _object) { var network = new Lampa.Reguest(); var extract = {}; var results = []; var object = _object; var wait_similars; var filter_items = {}; var choice = { season: 0, voice: 0, voice_name: '' }; this.search = function (_object, sim) { if (wait_similars) this.find(sim[0].id); }; function normalizeString(str) { return str.toLowerCase().replace(/[^a-zа-я0-9]/g, ''); } this.searchByTitle = function (_object, query) { var _this = this; object = _object; var year = parseInt(((object.movie.release_date || object.movie.first_air_date || '0000') + '').slice(0, 4)); var orig = object.movie.original_name || object.movie.original_title; var url = Lampa.Utils.addUrlComponent(apiPath('search'), 'story=' + encodeURIComponent(query)); url = Lampa.Utils.addUrlComponent(url, devToken()); network.clear(); network.timeout(10000); network.silent(url, function (json) { if (!json || !Array.isArray(json)) { component.doesNotAnswer(); return; } var cards = json.filter(function (c) { c.year = parseInt(c.year || c.alt_name.split('-').pop()); return c.year > year - 2 && c.year < year + 2; }); var card = cards.find(function (c) { return c.year == year && normalizeString(c.original_title) == normalizeString(orig); }); if (!card) { card = cards.find(function (c) { return normalizeString(c.original_title) == normalizeString(orig); }); } if (!card && cards.length == 1) card = cards[0]; if (card) _this.find(card.id); else if (json.length) { wait_similars = true; component.similars(json); component.loading(false); } else component.doesNotAnswer(); }, function (a, c) { component.doesNotAnswer(); }); }; this.find = function (filmix_id) { var token = getToken(); if (!window.fxapi.is_max_qualitie && token) { window.fxapi.is_max_qualitie = true; network.clear(); network.timeout(10000); network.silent(Lampa.Utils.addUrlComponent(apiPath('user_profile'), devToken(token)), function (found) { if (found && found.user_data) { if (found.user_data.is_pro) window.fxapi.max_qualitie = 1080; if (found.user_data.is_pro_plus) window.fxapi.max_qualitie = 2160; } end_search(filmix_id); }, function () { end_search(filmix_id); }); } else { end_search(filmix_id); } function end_search(filmix_id) { network.clear(); network.timeout(10000); network.silent(Lampa.Utils.addUrlComponent(apiPath('post/' + filmix_id), devToken()), function (found) { found = normalizePostResponse(found); if (found && hasStreamLinks(found)) { success(found); component.loading(false); } else if (found && found.id) component.empty(Lampa.Lang.translate('online_nostreams')); else component.doesNotAnswer(); }, function (a, c) { component.doesNotAnswer(); }); } }; this.extendChoice = function (saved) { Lampa.Arrays.extend(choice, saved, true); }; this.reset = function () { component.reset(); choice = { season: 0, voice: 0, voice_name: '' }; extractData(results); filter(); append(filtred()); component.saveChoice(choice); }; this.filter = function (type, a, b) { choice[a.stype] = b.index; if (a.stype == 'voice') choice.voice_name = filter_items.voice[b.index]; component.reset(); extractData(results); filter(); append(filtred()); component.saveChoice(choice); }; this.destroy = function () { network.clear(); results = null; }; function success(json) { results = json; extractData(json); filter(); var items = filtred(); if (!items.length) { component.doesNotAnswer(); return; } append(items); } function extractData(data) { extract = {}; var pl_links = data.player_links; if (isPlaylistMap(pl_links.playlist)) { var seas_num = 0; for (var season in pl_links.playlist) { var episode = pl_links.playlist[season]; ++seas_num; var transl_id = 0; var season_num = parseInt(season === '-1' ? '1' : season, 10); for (var voice in episode) { var episode_voice = episodeMap(episode[voice]); ++transl_id; var items = []; for (var ID in episode_voice) { var file_episod = episode_voice[ID]; if (!file_episod || !file_episod.link) continue; var quality_eps = file_episod.qualities.filter(function (qualitys) { return qualitys > 0 && qualitys <= window.fxapi.max_qualitie; }); if (!quality_eps.length) continue; var max_quality = maxQuality(quality_eps); var stream_url = file_episod.link.replace('%s.mp4', max_quality + '.mp4'); var s_e = stream_url.slice(0 - stream_url.length + stream_url.lastIndexOf('/')); var str_s_e = s_e.match(/s(\d+)e(\d+?)_\d+\.mp4/i); var _seas_num = season_num; var _epis_num = parseInt(ID, 10); if (str_s_e) { _seas_num = parseInt(str_s_e[1], 10); _epis_num = parseInt(str_s_e[2], 10); } else if (isNaN(_epis_num)) { continue; } items.push({ id: _seas_num + '_' + _epis_num, comment: _epis_num + ' ' + Lampa.Lang.translate('torrent_serial_episode') + ' ' + ID + '', file: stream_url, episode: _epis_num, season: _seas_num, quality: max_quality, qualities: quality_eps, translation: transl_id }); } if (!extract[transl_id]) extract[transl_id] = { json: [], file: '' }; extract[transl_id].json.push({ id: seas_num, comment: seas_num + ' ' + Lampa.Lang.translate('torrent_serial_season'), folder: items, translation: transl_id }); } } } else if (pl_links.movie && pl_links.movie.length > 0) { if (pl_links.movie.length === 1 && isBlockedTranslation(pl_links.movie[0].translation)) { return; } var _transl_id = 0; for (var _ID in pl_links.movie) { var _file_episod = pl_links.movie[_ID]; if (isBlockedTranslation(_file_episod.translation)) continue; ++_transl_id; var _quality_eps = parseLinkQualities(_file_episod.link); var _max_quality = maxQuality(_quality_eps); if (!_max_quality) continue; var file_url = _file_episod.link.replace(/_\[([\d,\s]*)\]\.mp4/i, '_' + _max_quality + '.mp4'); extract[_transl_id] = { file: file_url, translation: _file_episod.translation, quality: _max_quality, qualities: _quality_eps }; } } } function getFile(element, max_quality) { var translat = extract[element.translation]; var id = element.season + '_' + element.episode; var file = ''; var quality = false; if (translat) { if (element.season) for (var i in translat.json) { var elem = translat.json[i]; if (elem.folder) for (var f in elem.folder) { var folder = elem.folder[f]; if (folder.id == id) { file = folder.file; break; } } else { if (elem.id == id) { file = elem.file; break; } } } else file = translat.file; } max_quality = parseInt(max_quality); if (file) { var link = file.slice(0, file.lastIndexOf('_')) + '_'; var orin = file.split('?'); orin = orin.length > 1 ? '?' + orin.slice(1).join('?') : ''; if (file.split('_').pop().replace('.mp4', '') !== max_quality) { file = link + max_quality + '.mp4' + orin; } quality = {}; var mass = [2160, 1440, 1080, 720, 480, 360]; mass = mass.slice(mass.indexOf(max_quality)); mass.forEach(function (n) { quality[n + 'p'] = link + n + '.mp4' + orin; }); var preferably = Lampa.Storage.get('video_quality_default', '1080') + 'p'; if (quality[preferably]) file = quality[preferably]; } return { file: file, quality: quality }; } function filter() { filter_items = { season: [], voice: [], voice_info: [] }; var playlist = results.player_links.playlist; if (isPlaylistMap(playlist)) { playlistSeasonKeys(playlist).forEach(function (key) { filter_items.season.push(Lampa.Lang.translate('torrent_serial_season') + ' ' + seasonLabel(key)); }); var seasonKeys = playlistSeasonKeys(playlist); var seasonKey = seasonKeys[choice.season] || seasonKeys[0]; var seasonData = playlist[seasonKey]; var d = 0; if (seasonData) { for (var voic in seasonData) { ++d; filter_items.voice.push(voic); filter_items.voice_info.push({ id: d }); } } } else if (results.last_episode && results.last_episode.season) { var lastSeason = parseInt(results.last_episode.season, 10); if (lastSeason > 0) { var s = lastSeason; while (s--) { filter_items.season.push(Lampa.Lang.translate('torrent_serial_season') + ' ' + (lastSeason - s)); } } } if (choice.voice_name) { var inx = filter_items.voice.map(function (v) { return v.toLowerCase(); }).indexOf(choice.voice_name.toLowerCase()); if (inx == -1) choice.voice = 0; else if (inx !== choice.voice) { choice.voice = inx; } } if (choice.voice >= filter_items.voice.length) { choice.voice = 0; } if (filter_items.voice.length) { choice.voice_name = filter_items.voice[choice.voice] || ''; } component.filter(filter_items, choice); } function filtred() { var filtred = []; if (isPlaylistMap(results.player_links.playlist)) { for (var transl in extract) { var element = extract[transl]; for (var season_id in element.json) { var episode = element.json[season_id]; if (episode.id == choice.season + 1) { episode.folder.forEach(function (media) { if (media.translation == filter_items.voice_info[choice.voice].id) { filtred.push({ episode: parseInt(media.episode), season: media.season, title: Lampa.Lang.translate('torrent_serial_episode') + ' ' + media.episode + (media.title ? ' - ' + media.title : ''), quality: media.quality + 'p ', translation: media.translation, voice_name: filter_items.voice[choice.voice], info: filter_items.voice[choice.voice] }); } }); } } } } else if (Object.keys(results.player_links.movie).length) { for (var transl_id in extract) { var _element = extract[transl_id]; filtred.push({ title: _element.translation, quality: _element.quality + 'p ', qualitys: _element.qualities, translation: transl_id, voice_name: _element.translation }); } } return filtred; } function toPlayElement(element) { var extra = getFile(element, element.quality); var play = { title: element.title, url: extra.file, quality: extra.quality, timeline: element.timeline, callback: element.mark }; return play; } function append(items) { component.reset(); component.draw(items, { similars: wait_similars, onEnter: function onEnter(item, html) { var extra = getFile(item, item.quality); if (extra.file) { var playlist = []; var first = toPlayElement(item); if (item.season) { items.forEach(function (elem) { playlist.push(toPlayElement(elem)); }); } else { playlist.push(first); } if (playlist.length > 1) first.playlist = playlist; Lampa.Player.play(first); Lampa.Player.playlist(playlist); item.mark(); } else Lampa.Noty.show(Lampa.Lang.translate('online_nolink')); }, onContextMenu: function onContextMenu(item, html, data, call) { call(getFile(item, item.quality)); } }); } } function component(object) { var network = new Lampa.Reguest(); var scroll = new Lampa.Scroll({ mask: true, over: true }); var files = new Lampa.Explorer(object); var filter = new Lampa.Filter(object); var sources = { fxapi: fxapi }; var last; var extended; var selected_id; var source; var balanser = 'fxapi'; var initialized; var balanser_timer; var images = []; var filter_translate = { season: Lampa.Lang.translate('torrent_serial_season'), voice: Lampa.Lang.translate('torrent_parser_voice'), source: Lampa.Lang.translate('settings_rest_source') }; this.initialize = function () { var _this = this; source = this.createSource(); filter.onSearch = function (value) { Lampa.Activity.replace({ search: value, clarification: true }); }; filter.onBack = function () { _this.start(); }; filter.render().find('.selector').on('hover:enter', function () { clearInterval(balanser_timer); }); filter.onSelect = function (type, a, b) { if (type == 'filter') { if (a.reset) { if (extended) source.reset(); else _this.start(); } else { source.filter(type, a, b); } } else if (type == 'sort') { Lampa.Select.close(); } }; if (filter.addButtonBack) filter.addButtonBack(); filter.render().find('.filter--sort').remove(); files.appendFiles(scroll.render()); files.appendHead(filter.render()); scroll.body().addClass('torrent-list'); scroll.minus(files.render().find('.explorer__files-head')); this.search(); }; this.createSource = function () { return new sources[balanser](this, object); }; /** * Подготовка */ this.create = function () { return this.render(); }; /** * Начать поиск */ this.search = function () { this.activity.loader(true); this.find(); }; this.find = function () { if (source.searchByTitle) { this.extendChoice(); source.searchByTitle(object, object.search || object.movie.original_title || object.movie.original_name || object.movie.title || object.movie.name); } }; this.getChoice = function (for_balanser) { var data = Lampa.Storage.cache('online_choice_' + (for_balanser || balanser), 3000, {}); var save = data[selected_id || object.movie.id] || {}; Lampa.Arrays.extend(save, { season: 0, voice: 0, voice_name: '', voice_id: 0, episodes_view: {}, movie_view: '' }); return save; }; this.extendChoice = function () { extended = true; source.extendChoice(this.getChoice()); }; this.saveChoice = function (choice, for_balanser) { var data = Lampa.Storage.cache('online_choice_' + (for_balanser || balanser), 3000, {}); data[selected_id || object.movie.id] = choice; Lampa.Storage.set('online_choice_' + (for_balanser || balanser), data); }; /** * Есть похожие карточки * @param {Object} json */ this.similars = function (json) { var _this3 = this; json.forEach(function (elem) { var info = []; var year = ((elem.start_date || elem.year || '') + '').slice(0, 4); if (elem.rating && elem.rating !== 'null' && elem.filmId) info.push(Lampa.Template.get('online_prestige_rate', { rate: elem.rating }, true)); if (year) info.push(year); if (elem.countries && elem.countries.length) { info.push((elem.filmId ? elem.countries.map(function (c) { return c.country; }) : elem.countries).join(', ')); } if (elem.categories && elem.categories.length) { info.push(elem.categories.slice(0, 4).join(', ')); } var name = elem.title || elem.ru_title || elem.en_title || elem.nameRu || elem.nameEn; var orig = elem.orig_title || elem.nameEn || ''; elem.title = name + (orig && orig !== name ? ' / ' + orig : ''); elem.time = elem.filmLength || ''; elem.info = info.join('●'); var item = Lampa.Template.get('online_prestige_folder', elem); item.on('hover:enter', function () { _this3.activity.loader(true); _this3.reset(); object.search_date = year; selected_id = elem.id; _this3.extendChoice(); if (source.search) { source.search(object, [elem]); } else { _this3.doesNotAnswer(); } }).on('hover:focus', function (e) { last = e.target; scroll.update($(e.target), true); }); scroll.append(item); }); }; this.clearImages = function () { images.forEach(function (img) { img.onerror = function () { }; img.onload = function () { }; img.src = ''; }); images = []; }; /** * Очистить список файлов */ this.reset = function () { last = false; clearInterval(balanser_timer); network.clear(); this.clearImages(); scroll.render().find('.empty').remove(); scroll.clear(); }; /** * Загрузка */ this.loading = function (status) { if (status) this.activity.loader(true); else { this.activity.loader(false); this.activity.toggle(); } }; /** * Построить фильтр */ this.filter = function (filter_items, choice) { var _this4 = this; var select = []; var add = function add(type, title) { var need = _this4.getChoice(); var items = filter_items[type]; var subitems = []; var value = need[type]; items.forEach(function (name, i) { subitems.push({ title: name, selected: value == i, index: i }); }); select.push({ title: title, subtitle: items[value], items: subitems, stype: type }); }; select.push({ title: Lampa.Lang.translate('torrent_parser_reset'), reset: true }); this.saveChoice(choice); if (filter_items.voice && filter_items.voice.length) add('voice', Lampa.Lang.translate('torrent_parser_voice')); if (filter_items.season && filter_items.season.length) add('season', Lampa.Lang.translate('torrent_serial_season')); filter.set('filter', select); this.selected(filter_items); }; /** * Закрыть фильтр */ this.closeFilter = function () { if ($('body').hasClass('selectbox--open')) Lampa.Select.close(); }; /** * Показать что выбрано в фильтре */ this.selected = function (filter_items) { var need = this.getChoice(), select = []; for (var i in need) { if (filter_items[i] && filter_items[i].length) { if (i == 'voice') { select.push(filter_translate[i] + ': ' + filter_items[i][need[i]]); } else if (i !== 'source') { if (filter_items.season.length >= 1) { select.push(filter_translate.season + ': ' + filter_items[i][need[i]]); } } } } filter.chosen('filter', select); filter.chosen('sort', [balanser]); }; this.getEpisodes = function (season, call) { var episodes = []; if (typeof object.movie.id == 'number' && object.movie.name) { var tmdburl = 'tv/' + object.movie.id + '/season/' + season + '?api_key=' + Lampa.TMDB.key() + '&language=' + Lampa.Storage.get('language', 'ru'); var baseurl = Lampa.TMDB.api(tmdburl); network.timeout(1000 * 10); network["native"](baseurl, function (data) { episodes = data.episodes || []; call(episodes); }, function (a, c) { call(episodes); }); } else call(episodes); }; /** * Добавить элементы в список */ this.append = function (item) { item.on('hover:focus', function (e) { last = e.target; scroll.update($(e.target), true); }); scroll.append(item); }; this.watched = function (set) { var file_id = Lampa.Utils.hash(object.movie.number_of_seasons ? object.movie.original_name : object.movie.original_title); var watched = Lampa.Storage.cache('online_watched_last', 5000, {}); if (set) { if (!watched[file_id]) watched[file_id] = {}; Lampa.Arrays.extend(watched[file_id], set, true); Lampa.Storage.set('online_watched_last', watched); } else { return watched[file_id]; } }; /** * Отрисовка файлов */ this.draw = function (items) { var _this5 = this; var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (!items.length) return this.empty(); this.getEpisodes(items[0].season, function (episodes) { var viewed = Lampa.Storage.cache('online_view', 5000, []); var serial = object.movie.name ? true : false; var choice = _this5.getChoice(); var fully = window.innerWidth > 480; var scroll_to_element = false; var scroll_to_mark = false; items.forEach(function (element, index) { var episode = serial && episodes.length && !params.similars ? episodes.find(function (e) { return e.episode_number == element.episode; }) : false; var episode_num = element.episode || index + 1; var episode_last = choice.episodes_view[element.season]; Lampa.Arrays.extend(element, { info: '', quality: '', time: Lampa.Utils.secondsToTime((episode ? episode.runtime : object.movie.runtime) * 60, true) }); var hash_timeline = Lampa.Utils.hash(element.season ? [element.season, element.episode, object.movie.original_title].join('') : object.movie.original_title); var hash_behold = Lampa.Utils.hash(element.season ? [element.season, element.episode, object.movie.original_title, element.voice_name].join('') : object.movie.original_title + element.voice_name); var data = { hash_timeline: hash_timeline, hash_behold: hash_behold }; var info = []; if (element.season) { element.translate_episode_end = _this5.getLastEpisode(items); element.translate_voice = element.voice_name; } element.timeline = Lampa.Timeline.view(hash_timeline); if (episode) { element.title = episode.name; if (element.info.length < 30 && episode.vote_average) info.push(Lampa.Template.get('online_prestige_rate', { rate: parseFloat(episode.vote_average + '').toFixed(1) }, true)); if (episode.air_date && fully) info.push(Lampa.Utils.parseTime(episode.air_date).full); } else if (object.movie.release_date && fully) { info.push(Lampa.Utils.parseTime(object.movie.release_date).full); } if (!serial && object.movie.tagline && element.info.length < 30) info.push(object.movie.tagline); if (element.info) info.push(element.info); if (info.length) element.info = info.map(function (i) { return '' + i + ''; }).join('●'); var html = Lampa.Template.get('online_prestige_full', element); var loader = html.find('.online-prestige__loader'); var image = html.find('.online-prestige__img'); if (!serial) { if (choice.movie_view == hash_behold) scroll_to_element = html; } else if (typeof episode_last !== 'undefined' && episode_last == episode_num) { scroll_to_element = html; } if (serial && !episode) { image.append('
' + ('0' + (element.episode || index + 1)).slice(-2) + '
'); loader.remove(); } else { var img = html.find('img')[0]; img.onerror = function () { img.src = './img/img_broken.svg'; }; img.onload = function () { image.addClass('online-prestige__img--loaded'); loader.remove(); if (serial) image.append('
' + ('0' + (element.episode || index + 1)).slice(-2) + '
'); }; img.src = Lampa.TMDB.image('t/p/w300' + (episode ? episode.still_path : object.movie.backdrop_path)); images.push(img); } html.find('.online-prestige__timeline').append(Lampa.Timeline.render(element.timeline)); if (viewed.indexOf(hash_behold) !== -1) { scroll_to_mark = html; html.find('.online-prestige__img').append('
' + Lampa.Template.get('icon_viewed', {}, true) + '
'); } element.mark = function () { viewed = Lampa.Storage.cache('online_view', 5000, []); if (viewed.indexOf(hash_behold) == -1) { viewed.push(hash_behold); Lampa.Storage.set('online_view', viewed); if (html.find('.online-prestige__viewed').length == 0) { html.find('.online-prestige__img').append('
' + Lampa.Template.get('icon_viewed', {}, true) + '
'); } } choice = _this5.getChoice(); if (!serial) { choice.movie_view = hash_behold; } else { choice.episodes_view[element.season] = episode_num; } _this5.saveChoice(choice); _this5.watched({ balanser: balanser, balanser_name: Lampa.Utils.capitalizeFirstLetter(balanser), voice_id: choice.voice_id, voice_name: choice.voice_name || element.voice_name, episode: element.episode, season: element.season }); }; element.unmark = function () { viewed = Lampa.Storage.cache('online_view', 5000, []); if (viewed.indexOf(hash_behold) !== -1) { Lampa.Arrays.remove(viewed, hash_behold); Lampa.Storage.set('online_view', viewed); if (Lampa.Manifest.app_digital >= 177) Lampa.Storage.remove('online_view', hash_behold); html.find('.online-prestige__viewed').remove(); } }; element.timeclear = function () { element.timeline.percent = 0; element.timeline.time = 0; element.timeline.duration = 0; Lampa.Timeline.update(element.timeline); }; html.on('hover:enter', function () { if (object.movie.id) Lampa.Favorite.add('history', object.movie, 100); if (params.onEnter) params.onEnter(element, html, data); }).on('hover:focus', function (e) { last = e.target; if (params.onFocus) params.onFocus(element, html, data); scroll.update($(e.target), true); }); if (params.onRender) params.onRender(element, html, data); _this5.contextMenu({ html: html, element: element, onFile: function onFile(call) { if (params.onContextMenu) params.onContextMenu(element, html, data, call); }, onClearAllMark: function onClearAllMark() { items.forEach(function (elem) { elem.unmark(); }); }, onClearAllTime: function onClearAllTime() { items.forEach(function (elem) { elem.timeclear(); }); } }); scroll.append(html); }); if (serial && episodes.length > items.length && !params.similars) { var left = episodes.slice(items.length); left.forEach(function (episode) { var info = []; if (episode.vote_average) info.push(Lampa.Template.get('online_prestige_rate', { rate: parseFloat(episode.vote_average + '').toFixed(1) }, true)); if (episode.air_date) info.push(Lampa.Utils.parseTime(episode.air_date).full); var air = new Date((episode.air_date + '').replace(/-/g, '/')); var now = Date.now(); var day = Math.round((air.getTime() - now) / (24 * 60 * 60 * 1000)); var txt = Lampa.Lang.translate('full_episode_days_left') + ': ' + day; var html = Lampa.Template.get('online_prestige_full', { time: Lampa.Utils.secondsToTime((episode ? episode.runtime : object.movie.runtime) * 60, true), info: info.length ? info.map(function (i) { return '' + i + ''; }).join('●') : '', title: episode.name, quality: day > 0 ? txt : '' }); var loader = html.find('.online-prestige__loader'); var image = html.find('.online-prestige__img'); var season = items[0] ? items[0].season : 1; html.find('.online-prestige__timeline').append(Lampa.Timeline.render(Lampa.Timeline.view(Lampa.Utils.hash([season, episode.episode_number, object.movie.original_title].join(''))))); var img = html.find('img')[0]; if (episode.still_path) { img.onerror = function () { img.src = './img/img_broken.svg'; }; img.onload = function () { image.addClass('online-prestige__img--loaded'); loader.remove(); image.append('
' + ('0' + episode.episode_number).slice(-2) + '
'); }; img.src = Lampa.TMDB.image('t/p/w300' + episode.still_path); images.push(img); } else { loader.remove(); image.append('
' + ('0' + episode.episode_number).slice(-2) + '
'); } html.on('hover:focus', function (e) { last = e.target; scroll.update($(e.target), true); }); scroll.append(html); }); } if (scroll_to_element) { last = scroll_to_element[0]; } else if (scroll_to_mark) { last = scroll_to_mark[0]; } Lampa.Controller.enable('content'); }); }; /** * Меню */ this.contextMenu = function (params) { params.html.on('hover:long', function () { function show(extra) { var enabled = Lampa.Controller.enabled().name; var menu = []; if (Lampa.Platform.is('webos')) { menu.push({ title: Lampa.Lang.translate('player_lauch') + ' - Webos', player: 'webos' }); } if (Lampa.Platform.is('android')) { menu.push({ title: Lampa.Lang.translate('player_lauch') + ' - Android', player: 'android' }); } menu.push({ title: Lampa.Lang.translate('player_lauch') + ' - Lampa', player: 'lampa' }); menu.push({ title: Lampa.Lang.translate('online_video'), separator: true }); menu.push({ title: Lampa.Lang.translate('torrent_parser_label_title'), mark: true }); menu.push({ title: Lampa.Lang.translate('torrent_parser_label_cancel_title'), unmark: true }); menu.push({ title: Lampa.Lang.translate('time_reset'), timeclear: true }); if (extra) { menu.push({ title: Lampa.Lang.translate('copy_link'), copylink: true }); } menu.push({ title: Lampa.Lang.translate('more'), separator: true }); if (Lampa.Account.logged() && params.element && typeof params.element.season !== 'undefined' && params.element.translate_voice) { menu.push({ title: Lampa.Lang.translate('online_voice_subscribe'), subscribe: true }); } menu.push({ title: Lampa.Lang.translate('online_clear_all_marks'), clearallmark: true }); menu.push({ title: Lampa.Lang.translate('online_clear_all_timecodes'), timeclearall: true }); Lampa.Select.show({ title: Lampa.Lang.translate('title_action'), items: menu, onBack: function onBack() { Lampa.Controller.toggle(enabled); }, onSelect: function onSelect(a) { if (a.mark) params.element.mark(); if (a.unmark) params.element.unmark(); if (a.timeclear) params.element.timeclear(); if (a.clearallmark) params.onClearAllMark(); if (a.timeclearall) params.onClearAllTime(); Lampa.Controller.toggle(enabled); if (a.player) { Lampa.Player.runas(a.player); params.html.trigger('hover:enter'); } if (a.copylink) { if (extra.quality) { var qual = []; for (var i in extra.quality) { qual.push({ title: i, file: extra.quality[i] }); } Lampa.Select.show({ title: Lampa.Lang.translate('settings_server_links'), items: qual, onBack: function onBack() { Lampa.Controller.toggle(enabled); }, onSelect: function onSelect(b) { Lampa.Utils.copyTextToClipboard(b.file, function () { Lampa.Noty.show(Lampa.Lang.translate('copy_secuses')); }, function () { Lampa.Noty.show(Lampa.Lang.translate('copy_error')); }); } }); } else { Lampa.Utils.copyTextToClipboard(extra.file, function () { Lampa.Noty.show(Lampa.Lang.translate('copy_secuses')); }, function () { Lampa.Noty.show(Lampa.Lang.translate('copy_error')); }); } } if (a.subscribe) { Lampa.Account.subscribeToTranslation({ card: object.movie, season: params.element.season, episode: params.element.translate_episode_end, voice: params.element.translate_voice }, function () { Lampa.Noty.show(Lampa.Lang.translate('online_voice_success')); }, function () { Lampa.Noty.show(Lampa.Lang.translate('online_voice_error')); }); } } }); } params.onFile(show); }).on('hover:focus', function () { if (Lampa.Helper) Lampa.Helper.show('online_file', Lampa.Lang.translate('helper_online_file'), params.html); }); }; /** * Показать пустой результат */ this.empty = function (msg) { var html = Lampa.Template.get('online_does_not_answer', {}); html.find('.online-empty__buttons').remove(); html.find('.online-empty__title').text(Lampa.Lang.translate('empty_title_two')); scroll.append(html); this.loading(false); }; this.doesNotAnswer = function () { var _this6 = this; this.reset(); var html = Lampa.Template.get('online_does_not_answer', { balanser: balanser }); scroll.append(html); this.loading(false); }; this.getLastEpisode = function (items) { var last_episode = 0; items.forEach(function (e) { if (typeof e.episode !== 'undefined') last_episode = Math.max(last_episode, parseInt(e.episode)); }); return last_episode; }; /** * Начать навигацию по файлам */ this.start = function () { if (Lampa.Activity.active().activity !== this.activity) return; if (!initialized) { initialized = true; this.initialize(); } Lampa.Background.immediately(Lampa.Utils.cardImgBackgroundBlur(object.movie)); Lampa.Controller.add('content', { toggle: function toggle() { Lampa.Controller.collectionSet(scroll.render(), files.render()); Lampa.Controller.collectionFocus(last || false, scroll.render()); }, up: function up() { if (Navigator.canmove('up')) { Navigator.move('up'); } else Lampa.Controller.toggle('head'); }, down: function down() { Navigator.move('down'); }, right: function right() { if (Navigator.canmove('right')) Navigator.move('right'); else filter.show(Lampa.Lang.translate('title_filter'), 'filter'); }, left: function left() { if (Navigator.canmove('left')) Navigator.move('left'); else Lampa.Controller.toggle('menu'); }, gone: function gone() { clearInterval(balanser_timer); }, back: this.back }); Lampa.Controller.toggle('content'); }; this.render = function () { return files.render(); }; this.back = function () { Lampa.Activity.backward(); }; this.pause = function () { }; this.stop = function () { }; this.destroy = function () { network.clear(); this.clearImages(); files.destroy(); scroll.destroy(); clearInterval(balanser_timer); if (source && source.destroy) source.destroy(); clearInterval(ping_auth); }; } function startPlugin() { window.online_filmix = true; var manifest = { type: 'video', version: '1.0.7', name: 'Онлайн - Filmix', description: 'Плагин для просмотра онлайн сериалов и фильмов', component: 'online_fxapi', onContextMenu: function onContextMenu(object) { return { name: Lampa.Lang.translate('online_watch'), description: '' }; }, onContextLauch: function onContextLauch(object) { resetTemplates(); Lampa.Component.add('online_fxapi', component); Lampa.Activity.push({ url: '', title: Lampa.Lang.translate('title_online'), component: 'online_fxapi', search: object.title, search_one: object.title, search_two: object.original_title, movie: object, page: 1 }); } }; Lampa.Manifest.plugins = manifest; Lampa.Lang.add({ online_watch: { ru: 'Смотреть онлайн', en: 'Watch online', ua: 'Дивитися онлайн', zh: '在线观看' }, online_video: { ru: 'Видео', en: 'Video', ua: 'Відео', zh: '视频' }, online_nolink: { ru: 'Не удалось извлечь ссылку', uk: 'Неможливо отримати посилання', en: 'Failed to fetch link', zh: '获取链接失败' }, helper_online_file: { ru: 'Удерживайте клавишу "ОК" для вызова контекстного меню', uk: 'Утримуйте клавішу "ОК" для виклику контекстного меню', en: 'Hold the "OK" key to bring up the context menu', zh: '按住“确定”键调出上下文菜单' }, title_online: { ru: 'Онлайн', uk: 'Онлайн', en: 'Online', zh: '在线的' }, modal_text: { ru: 'Введите код на странице https://filmix.my/consoles', uk: 'Введіть код на сторінці https://filmix.my/consoles', en: 'Enter the code on the page https://filmix.my/consoles', zh: '在您的授权帐户中的 https://filmix.my/consoles' }, modal_wait: { ru: 'Ожидаем код', uk: 'Очікуємо код', en: 'Waiting for the code', zh: '我们正在等待代码' }, copy_secuses: { ru: 'Код скопирован в буфер обмена', uk: 'Код скопійовано в буфер обміну', en: 'Code copied to clipboard', zh: '代码复制到剪贴板' }, copy_fail: { ru: 'Ошибка при копировании', uk: 'Помилка при копіюванні', en: 'Copy error', zh: '复制错误' }, title_status: { ru: 'Статус', uk: 'Статус', en: 'Status', zh: '地位' }, online_voice_subscribe: { ru: 'Подписаться на перевод', uk: 'Підписатися на переклад', en: 'Subscribe to translation', zh: '订阅翻译' }, online_voice_success: { ru: 'Вы успешно подписались', uk: 'Ви успішно підписалися', en: 'You have successfully subscribed', zh: '您已成功订阅' }, online_voice_error: { ru: 'Возникла ошибка', uk: 'Виникла помилка', en: 'An error has occurred', zh: '发生了错误' }, online_clear_all_marks: { ru: 'Очистить все метки', uk: 'Очистити всі мітки', en: 'Clear all labels', zh: '清除所有标签' }, online_clear_all_timecodes: { ru: 'Очистить все тайм-коды', uk: 'Очистити всі тайм-коди', en: 'Clear all timecodes', zh: '清除所有时间代码' }, online_balanser_dont_work: { ru: 'Поиск не дал результатов', uk: 'Пошук не дав результатів', en: 'The search did not return any results', zh: '平衡器 未响应请求。' }, online_nostreams: { ru: 'Контент найден, но ссылки на видео недоступны. Проверьте CORS-прокси или авторизацию Filmix.', uk: 'Контент знайдено, але посилання на відео недоступні. Перевірте CORS-проксі або авторизацію Filmix.', en: 'Content found, but video links are unavailable. Check the CORS proxy or Filmix authorization.', zh: '找到内容,但视频链接不可用。请检查 CORS 代理或 Filmix 授权。' }, fxapi_proxy_title: { ru: 'CORS прокси Filmix', uk: 'CORS проксі Filmix', en: 'Filmix CORS proxy', zh: 'Filmix CORS 代理' }, fxapi_proxy_descr: { ru: 'Прокси должен подменять User-Agent для filmixapp (см. cors.conf)', uk: 'Проксі має підміняти User-Agent для filmixapp (див. cors.conf)', en: 'Proxy must override User-Agent for filmixapp (see cors.conf)', zh: '代理必须为 filmixapp 覆盖 User-Agent(见 cors.conf)' }, filmix_param_add_title: { ru: 'Добавить ТОКЕН от Filmix', uk: 'Додати ТОКЕН від Filmix', en: 'Add TOKEN from Filmix', zh: '从 Filmix 添加 TOKEN' }, filmix_param_add_descr: { ru: 'Добавьте ТОКЕН для подключения подписки', uk: 'Додайте ТОКЕН для підключення передплати', en: 'Add a TOKEN to connect a subscription', zh: '添加 TOKEN 以连接订阅' }, filmix_param_placeholder: { ru: 'Например: nxjekeb57385b..', uk: 'Наприклад: nxjekeb57385b..', en: 'For example: nxjekeb57385b..', zh: '例如:nxjekeb57385b..' }, filmix_param_add_device: { ru: 'Добавить устройство на Filmix', uk: 'Додати пристрій на Filmix', en: 'Add Device to Filmix', zh: '将设备添加到 Filmix' }, filmix_nodevice: { ru: 'Устройство не авторизовано', uk: 'Пристрій не авторизований', en: 'Device not authorized', zh: '设备未授权' }, filmix_sub_free: { ru: 'Бесплатно', uk: 'Безкоштовно', en: 'Free', zh: '免费' }, filmix_sub_days: { ru: 'Осталось дней', uk: 'Залишилось днів', en: 'Days left', zh: '剩余天数' }, filmix_max_quality: { ru: 'Макс. качество', uk: 'Макс. якість', en: 'Max quality', zh: '最高画质' }, filmix_video_server: { ru: 'Видео сервер', uk: 'Відео сервер', en: 'Video server', zh: '视频服务器' }, fxapi_refresh_profile: { ru: 'Обновить профиль Filmix', uk: 'Оновити профіль Filmix', en: 'Refresh Filmix profile', zh: '刷新 Filmix 个人资料' }, filmix_pro_until: { ru: 'Подписка до', uk: 'Підписка до', en: 'Subscription until', zh: '订阅至' }, filmix_profile_updated: { ru: 'Профиль Filmix обновлён', uk: 'Профіль Filmix оновлено', en: 'Filmix profile updated', zh: 'Filmix 个人资料已更新' } }); Lampa.Template.add('fxapi_profile_css', ''); $('body').append(Lampa.Template.get('fxapi_profile_css', {}, true)); Lampa.Template.add('online_prestige_css', "\n \n "); $('body').append(Lampa.Template.get('online_prestige_css', {}, true)); function resetTemplates() { Lampa.Template.add('online_prestige_full', "
\n
\n \"\"\n
\n
\n
\n
\n
{title}
\n
{time}
\n
\n\n
\n\n
\n
{info}
\n
{quality}
\n
\n
\n
"); Lampa.Template.add('online_does_not_answer', "
\n
\n #{online_balanser_dont_work}\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
"); Lampa.Template.add('online_prestige_rate', "
\n \n \n \n {rate}\n
"); Lampa.Template.add('online_prestige_folder', "
\n
\n \n \n \n \n \n
\n
\n
\n
{title}
\n
{time}
\n
\n\n
\n
{info}
\n
\n
\n
"); } var button = "
\n \n \n \n \n\n #{title_online}\n
"); // нужна заглушка, а то при страте лампы говорит пусто Lampa.Component.add('online_fxapi', component); //то же самое resetTemplates(); Lampa.Listener.follow('full', function (e) { if (e.type == 'complite') { var btn = $(Lampa.Lang.translate(button)); btn.on('hover:enter', function () { resetTemplates(); Lampa.Component.add('online_fxapi', component); Lampa.Activity.push({ url: '', title: Lampa.Lang.translate('title_online'), component: 'online_fxapi', search: e.data.movie.title, search_one: e.data.movie.title, search_two: e.data.movie.original_title, movie: e.data.movie, page: 1 }); }); e.object.activity.render().find('.view--torrent').after(btn); } }); window.fxapi = { max_qualitie: 720, is_max_qualitie: false }; function checkToken(token) { fetchUserProfile(token); } Lampa.Params.select('fxapi_token', '', ''); Lampa.Params.select('fxapi_proxy', 'https://cors.jacred.stream/', ''); Lampa.SettingsApi.addComponent({ component: 'fxapi', name: 'Filmix FX', icon: '' }); Lampa.Template.add('settings_fxapi', '
\n
\n
\n
#{fxapi_refresh_profile}
\n
\n
\n
#{fxapi_proxy_title}
\n
\n
#{fxapi_proxy_descr}
\n
\n
\n
#{filmix_param_add_title}
\n
\n
#{filmix_param_add_descr}
\n
\n
\n
#{filmix_param_add_device}
\n
\n
'); Lampa.Storage.listener.follow('change', function (e) { if (e.name == 'fxapi_proxy') { proxy_url = e.value || 'https://cors.jacred.stream/'; if (proxy_url && proxy_url.charAt(proxy_url.length - 1) !== '/') proxy_url += '/'; } if (e.name == 'fxapi_token') { window.fxapi.is_max_qualitie = false; if (e.value) checkToken(e.value); else { Lampa.Storage.set('fxapi_status', {}); window.fxapi.max_qualitie = 720; renderFxProfile(); } } }); Lampa.Settings.listener.follow('open', function (e) { if (e.name != 'fxapi') return; renderFxProfile(); var token = getToken(); if (token) fetchUserProfile(token); e.body.find('[data-name="fxapi_refresh"]').unbind('hover:enter').on('hover:enter', function () { var refreshToken = getToken(); if (!refreshToken) { Lampa.Noty.show(Lampa.Lang.translate('filmix_nodevice')); return; } fetchUserProfile(refreshToken, function (profile) { if (profile) Lampa.Noty.show(Lampa.Lang.translate('filmix_profile_updated')); }); }); e.body.find('[data-name="fxapi_add"]').unbind('hover:enter').on('hover:enter', function () { var network = new Lampa.Reguest(); var user_code = ''; var user_token = ''; var modal = $('
' + Lampa.Lang.translate('modal_text') + '
' + Lampa.Lang.translate('modal_wait') + '...

'); Lampa.Modal.open({ title: '', html: modal, onBack: function () { Lampa.Modal.close(); Lampa.Controller.toggle('settings_component'); clearInterval(ping_auth); }, onSelect: function () { Lampa.Utils.copyTextToClipboard(user_code, function () { Lampa.Noty.show(Lampa.Lang.translate('copy_secuses')); }, function () { Lampa.Noty.show(Lampa.Lang.translate('copy_fail')); }); } }); ping_auth = setInterval(function () { network.silent(Lampa.Utils.addUrlComponent(apiPath('user_profile'), devToken(user_token)), function (json) { if (json && json.user_data) { Lampa.Modal.close(); clearInterval(ping_auth); Lampa.Storage.set('fxapi_token', user_token); e.body.find('[data-name="fxapi_token"] .settings-param__value').text(user_token); fetchUserProfile(user_token); Lampa.Controller.toggle('settings_component'); } }, function () { }); }, 2000); network.clear(); network.timeout(10000); network.quiet(Lampa.Utils.addUrlComponent(apiPath('token_request'), devToken('')), function (found) { if (found.status == 'ok') { user_token = found.code; user_code = found.user_code; modal.find('.selector').text(user_code); } else { Lampa.Noty.show(found); } }, function (a, c) { Lampa.Noty.show(network.errorDecode(a, c)); }); }); }); var token = getToken(); if (token) checkToken(token); if (Lampa.Manifest.app_digital >= 177) { Lampa.Storage.sync('online_choice_fxapi', 'object_object'); } } if (!window.online_filmix && Lampa.Manifest.app_digital >= 155) startPlugin(); })();