- // ==UserScript==
- // @name ThisVid.com Improved
- // @namespace http://tampermonkey.net/
- // @version 5.0.8
- // @license MIT
- // @description Infinite scroll (optional). Preview for private videos. Filter: duration, public/private, include/exclude terms. Check access to private vids. Mass friend request button. Sorts messages. Download button 📼
- // @author smartacephale
- // @supportURL https://github.com/smartacephale/sleazy-fork
- // @match https://*.thisvid.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=thisvid.com
- // @grant GM_addStyle
- // @require https://cdn.jsdelivr.net/npm/billy-herrington-utils@1.1.8/dist/billy-herrington-utils.umd.js
- // @require https://cdn.jsdelivr.net/npm/jabroni-outfit@1.4.9/dist/jabroni-outfit.umd.js
- // @require https://cdn.jsdelivr.net/npm/lskdb@1.0.2/dist/lskdb.umd.js
- // @require https://update.greasyfork.org/scripts/494204/data-manager.user.js?version=1458190
- // @require https://update.greasyfork.org/scripts/494205/pagination-manager.user.js?version=1459738
- // @run-at document-idle
- // ==/UserScript==
- /* globals $ DataManager PaginationManager */
-
- const { Tick, parseDom, fetchWith, fetchHtml, timeToSeconds, parseCSSUrl, circularShift, range, listenEvents, replaceElementTag,
- sanitizeStr, chunks, downloader, AsyncPool } = window.bhutils;
- Object.assign(unsafeWindow, { bhutils: window.bhutils });
- const { JabroniOutfitStore, defaultStateWithDurationAndPrivacy, JabroniOutfitUI, defaultSchemeWithPrivateFilter } = window.jabronioutfit;
- const { LSKDB } = window.lskdb;
-
- const SponsaaLogo = `
- Kono bangumi ha(wa) goran no suponsaa no teikyou de okurishimasu⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⡟⣟⢻⢛⢟⠿⢿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣾⣾⣵⣧⣷⢽⢮⢧⢿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣯⣭⣧⣯⣮⣧⣯⣧⣯⡮⣵⣱⢕⣕⢕⣕⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⡫⡻⣝⢯⡻⣝⡟⣟⢽⡫⡟⣏⢏⡏⡝⡭⡹⡩⣻⣿⣿⣿⣿⠟⠟⢟⡟⠟⠻⠛⠟⠻⠻⣿⣿⣿⡟⠟⠻⠛⠟⠻⠻⣿⣿
- ⣿⣿⣿⣿⡿⣻⣿⣿⣿⡿⣿⣿⡿⣿⣿⢿⢿⡻⢾⠽⡺⡞⣗⠷⣿⣿⣿⡏⠀⠀⠀⣣⣤⡄⠀⠠⣄⡆⠫⠋⠻⢕⣤⡄⠀ ⢀⣤⣔⣿⣿
- ⣿⣿⣿⣿⣷⣷⣷⣾⣶⣯⣶⣶⣷⣷⣾⣷⣳⣵⣧⣳⡵⣕⣮⣞⣾⣿⡟⠄⢀⣦⠀⢘⣽⡇⠀⠨⣿⡌⠀⠣⣠⠹⠿⡭⠀ ⠐⣿⣿⣿⣿
- ⣿⣿⣿⣿⣕⣵⣱⣫⣳⡯⣯⣫⣯⣞⣮⣎⣮⣪⣢⣣⣝⣜⡜⣜⣾⣿⠃⠀⠀⠑⠀⠀⢺⡇⠀ ⢘⣾⠀⢄⢄⠘⠀⢘⢎⠀⢈⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣙⣛⣛⢻⢛⢟⢟⣛⢻⢹⣙⢳⢹⢚⢕⣓⡓⡏⣗⣿⣓⣀⣀⣿⣿⣮⢀⣀⣇⣀⣐⣿⣔⣀⢁⢀⣀⣀⣅⣀⡠⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣾⡞⣞⢷⡻⡯⡷⣗⢯⢷⢞⢷⢻⢞⢷⡳⣻⣺⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣷⣵⡵⣼⢼⢼⡴⣵⢵⡵⣵⢵⡵⣵⣪⣾⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣧⣫⣪⡪⡣⣫⣪⣣⣯⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
- ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿`;
-
- const haveAccessColor = 'linear-gradient(90deg, #31623b, #212144)';
- const haveNoAccessColor = 'linear-gradient(90deg, #462525, #46464a)';
- const succColor = 'linear-gradient(#2f6eb34f, #66666647)';
- const failColor = 'linear-gradient(rgba(179, 47, 47, 0.31), rgba(102, 102, 102, 0.28))';
- const friendProfileColor = 'radial-gradient(circle, rgb(28, 42, 50) 48%, rgb(0, 0, 0) 100%)';
-
- class THISVID_RULES {
- constructor() {
- const { href, pathname } = window.location;
-
- this.PAGINATION_ALLOWED = [
- /\.com\/$/,
- /\/(categories|tags?)\//,
- /\/?q=.*/,
- /\/(\w+-)?(rated|popular|private|newest|winners|updates)\/(\d+\/)?$/,
- /\/members\/\d+\/\w+_videos\//,
- /\/playlist\/\d+\//,
- /\/my_(\w+)_videos\//
- ].some(r => r.test(href));
-
- this.IS_MEMBER_PAGE = /^\/members\/\d+\/$/.test(pathname);
- this.IS_WATCHLATER_KIND = /^\/my_(\w+)_videos\//.test(pathname);
- this.IS_MESSAGES_PAGE = /^\/my_messages\//.test(pathname);
- this.IS_PLAYLIST = /^\/playlist\/\d+\//.test(pathname);
- this.IS_VIDEO_PAGE = /^\/videos\//.test(pathname);
-
- this.PAGE_HAS_VIDEO = this.GET_THUMBS(document).length > 0;
-
- this.PAGINATION = document.querySelector('.pagination');
- this.PAGINATION_LAST = this.GET_PAGINATION_LAST();
-
- this.CONTAINER = Array.from(document.querySelectorAll('.thumbs-items')).pop();
-
- this.MY_ID = document.querySelector('[target="_self"]')?.href.match(/\/(\d+)\//)[1] || null;
- this.LOGGED_IN = !!this.MY_ID;
- this.IS_MY_MEMBER_PAGE = this.LOGGED_IN && !!document.querySelector('.my-avatar');
- this.IS_OTHER_MEMBER_PAGE = !this.IS_MY_MEMBER_PAGE && this.IS_MEMBER_PAGE;
- this.IS_MEMBER_FRIEND = this.IS_OTHER_MEMBER_PAGE && document.querySelector('.case-left')?.innerText.includes('is in your friends');
-
- // highlight friend page profile
- if (this.IS_MEMBER_FRIEND) {
- document.querySelector('.profile').style.background = friendProfileColor;
- }
-
- // playlist page add link to video
- if (this.IS_PLAYLIST) {
- const videoUrl = this.PLAYLIST_THUMB_URL(pathname);
- const desc = document.querySelector('.tools-left > li:nth-child(4) > .title-description');
- const link = replaceElementTag(desc, 'a');
- link.href = videoUrl;
- }
- }
-
- GET_PAGINATION_LAST(doc) {
- return parseInt((doc || document).querySelector('.pagination-next')?.previousElementSibling?.innerText) || 1;
- }
-
- GET_THUMBS(html) {
- if (this.IS_WATCHLATER_KIND) {
- return Array.from(html.querySelectorAll('.thumb-holder'));
- }
- let thumbs = Array.from(html.querySelectorAll('.tumbpu[title]'));
- if (thumbs.length === 0 && html?.classList?.contains('tumbpu')) thumbs = [html];
- return thumbs.filter(thumb => !thumb?.parentElement.classList.contains('thumbs-photo'));
- }
-
- PLAYLIST_THUMB_URL(src) {
- return src.replace(/playlist\/\d+\/video/, () => 'videos');
- }
-
- THUMB_URL(thumb) {
- if (this.IS_WATCHLATER_KIND) {
- return thumb.firstElementChild.href;
- }
- let url = thumb.getAttribute('href');
- if (this.IS_PLAYLIST) url = this.PLAYLIST_THUMB_URL(url);
- return url;
- }
-
- URL_DATA(proxyLocation) {
- const url = new URL(proxyLocation || window.location);
- const offset = this.IS_PLAYLIST ? 1 : (parseInt(url.pathname.match(/\/(\d+)\/?$/)?.[1]) || 1);
-
- if (url.pathname === '/') url.pathname = '/latest-updates/';
- if (!/\/(\d+)\/?$/.test(url.pathname)) url.pathname = `${url.pathname}${offset}/`;
-
- const iteratable_url = (n) => {
- if (this.IS_PLAYLIST) {
- url.search = `mode=async&function=get_block&block_id=playlist_view_playlist_view&sort_by=added2fav_date&from=${n}&_=${Date.now()}`;
- } else {
- url.pathname = url.pathname.replace(/\/\d+\/$/, `/${n}/`);
- }
- return url.href;
- }
-
- return { offset, iteratable_url }
- }
-
- THUMB_IMG_DATA(thumb) {
- const img = thumb.querySelector('img');
- const privateThumb = thumb.querySelector('.private');
- let imgSrc = img?.getAttribute('data-original');
- if (privateThumb) {
- imgSrc = parseCSSUrl(privateThumb.style.background);
- privateThumb.removeAttribute('style');
- }
- const count = img.getAttribute('data-cnt');
- if (!count || count === "6") img.removeAttribute('data-cnt');
- img.classList.remove('lazy-load');
- img.classList.add('tracking');
-
- if (this.IS_PLAYLIST) {
- img.onmouseover = img.onmouseout = null;
- img.removeAttribute('onmouseover');
- img.removeAttribute('onmouseout');
- }
-
- return { img, imgSrc };
- }
-
- ITERATE_PREVIEW_IMG(img) {
- const count = parseInt(img.getAttribute('data-cnt')) || 6;
- img.src = img.getAttribute('src').replace(/(\d+)(?=\.jpg$)/, (_, n) => `${circularShift(parseInt(n), count)}`);
- }
-
- THUMB_DATA(thumb) {
- const title = sanitizeStr(thumb.querySelector('.title').innerText);
- const duration = timeToSeconds(thumb.querySelector('.thumb > .duration').textContent);
- return { title, duration }
- }
-
- IS_PRIVATE(thumb) {
- return !thumb.querySelector('.private');
- }
- }
-
- const RULES = new THISVID_RULES();
-
- //====================================================================================================
-
- function friend(id) {
- return fetchWith(FRIEND_REQUEST_URL(id));
- }
-
- const FRIEND_REQUEST_URL = (id) => `https://thisvid.com/members/${id}/?action=add_to_friends_complete&function=get_block&block_id=member_profile_view_view_profile&format=json&mode=async&message=`;
-
- const USERS_PER_PAGE = 24;
-
- async function getMemberFriends(memberId, start, end) {
- const { friendsCount } = await getMemberData(memberId);
- const offset = Math.ceil(friendsCount / USERS_PER_PAGE);
- const pages = range(offset).slice(start, end).map(o => `https://thisvid.com/members/${memberId}/friends/${o}/`);
- const pagesFetched = pages.map(p => fetchHtml(p));
- const friends = (await Promise.all(pagesFetched)).flatMap(getMembers);
- return friends;
- }
-
- function getMembers(el) {
- const friendsList = el.querySelector('#list_members_friends_items');
- return Array.from(friendsList?.querySelectorAll('.tumbpu') || [])
- .map(e => e.href.match(/\d+/)?.[0]).filter(_ => _);
- }
-
- async function friendMemberFriends(orientationFilter) {
- const memberId = window.location.pathname.match(/\d+/)[0];
- friend(memberId);
- const friends = await getMemberFriends(memberId);
- const spool = new AsyncPool(60);
- friends.map((fid) => {
- if (!orientationFilter) () => friend(fid);
- return () => getMemberData(fid).then(async ({ orientation, uploadedPrivate }) => {
- if (orientation === orientationFilter && uploadedPrivate > 0) {
- await friend(fid);
- }
- });
- }).forEach(f => spool.push(f));
- await spool.run();
- }
-
- function initFriendship() {
- GM_addStyle('.buttons {display: flex; flex-wrap: wrap} .buttons button, .buttons a {align-self: center; padding: 4px; margin: 5px;}');
-
- const buttonAll = parseDom('<button style="background: radial-gradient(red, blueviolet);">friend everyone</button>');
- const buttonStraightOnly = parseDom('<button style="background: radial-gradient(red, #a18cb5);">friend straights</button>');
- const buttonGayOnly = parseDom('<button style="background: radial-gradient(red, #46baff);">friend gays</button>');
- const buttonBisexualOnly = parseDom('<button style="background: radial-gradient(red, #4ebaaf);">friend bisexuals</button>');
-
- document.querySelector('.buttons').append(buttonAll, buttonStraightOnly, buttonGayOnly, buttonBisexualOnly);
-
- buttonAll.addEventListener('click', (e) => handleClick(e), { once: true });
- buttonStraightOnly.addEventListener('click', (e) => handleClick(e, 'Straight'), { once: true });
- buttonGayOnly.addEventListener('click', (e) => handleClick(e, 'Gay'), { once: true });
- buttonBisexualOnly.addEventListener('click', (e) => handleClick(e, 'Bisexual'), { once: true });
-
- function handleClick(e, orientationFilter) {
- const button = e.target;
- button.style.background = 'radial-gradient(#ff6114, #5babc4)';
- button.innerText = 'processing requests';
- friendMemberFriends(orientationFilter).then(() => {
- button.style.background = 'radial-gradient(blue, lightgreen)';
- button.innerText = 'friend requests sent';
- });
- }
- }
-
- //====================================================================================================
-
- async function getMemberData(id) {
- const url = id.includes('member') ? id : `/members/${id}/`;
- const doc = await fetchHtml(url);
- const data = {};
-
- doc.querySelectorAll('.profile span').forEach(s => {
- if (s.innerText.includes('Name:')) {
- data.name = s.firstElementChild.innerText.trim();
- }
- if (s.innerText.includes('Orientation:')) {
- data.orientation = s.firstElementChild.innerText.trim();
- }
- if (s.innerText.includes('Videos uploaded:')) {
- data.uploadedPublic = parseInt(s.children[0].innerText);
- data.uploadedPrivate = parseInt(s.children[1].innerText);
- }
- });
-
- data.friendsCount = parseInt(doc.querySelector('#list_members_friends')?.firstElementChild.innerText.match(/\d+/g).pop()) || 0;
-
- return data;
- }
-
- //====================================================================================================
-
- unsafeWindow.requestPrivateAccess = (e, memberid) => {
- e.preventDefault();
- friend(memberid);
- e.target.innerText = e.target.innerText.replace('🚑', '🍆');
- }
-
- async function checkPrivateVideoAccess(url) {
- const html = await fetchHtml(url);
- const holder = html.querySelector('.video-holder > p');
-
- const access = !holder;
-
- const uploaderEl = holder ? holder.querySelector('a') : html.querySelector('a.author');
- const uploaderURL = uploaderEl.href.replace(/.*\/(\d+)\/$/, (a, b) => b);
- const uploaderName = uploaderEl.innerText;
-
- return {
- access,
- uploaderURL,
- uploaderName
- }
- }
-
- function checkPrivateVidsAccess() {
- document.querySelectorAll('.tumbpu > .private').forEach(async t => {
- const thumb = t.parentElement;
- const { access, uploaderURL, uploaderName } = await checkPrivateVideoAccess(thumb.href);
-
- thumb.style.background = access ? haveAccessColor : haveNoAccessColor;
- thumb.querySelector('.title').innerText += access ? ' ✅ ' : ' ❌ ';
- thumb.querySelector('.title').appendChild(parseDom(access ? `<span>${uploaderName}</span>` :
- `<span onclick="requestPrivateAccess(event, ${uploaderURL});"> 🚑 ${uploaderName}</span>`));
- });
- }
-
- //====================================================================================================
-
- const createDownloadButton = () => downloader({
- append: '',
- after: '.share_btn',
- button: '<li><a href="#" style="text-decoration: none;font-size: 2rem;">📼</a></li>',
- cbBefore: () => $('.fp-ui').click()
- })
-
- //====================================================================================================
-
- class PreviewAnimation {
- constructor(element, delay = ANIMATION_DELAY) {
- $('img[alt!="Private"]').off();
- this.tick = new Tick(delay);
- listenEvents(element, ['mouseover', 'touchstart'], this.animatePreview);
- }
-
- animatePreview = (e) => {
- const { target: el, type } = e;
- if (!el.classList.contains('tracking') || !el.getAttribute("src")) return;
- this.tick.stop();
- if (type === 'mouseover' || type === 'touchstart') {
- const orig = el.getAttribute("src");
- this.tick.start(
- () => { RULES.ITERATE_PREVIEW_IMG(el); },
- () => { el.src = orig; });
- el.addEventListener(type === 'mouseover' ? 'mouseleave' : 'touchend', () => this.tick.stop(), { once: true });
- }
- };
- }
-
- //====================================================================================================
-
- function highlightMessages() {
- for (const member of document.querySelectorAll('.user-avatar > a')) {
- getMemberData(member.href).then(({ uploadedPublic, uploadedPrivate }) => {
- if (uploadedPrivate > 0) {
- const success = !member.parentElement.nextElementSibling.innerText.includes('declined');
- member.parentElement.parentElement.style.background = success ? succColor : failColor;
- }
- member.parentElement.parentElement.querySelector('.user-comment p').innerText +=
- ` | videos: ${uploadedPublic} public, ${uploadedPrivate} private`;
- });
- }
- }
-
- //====================================================================================================
-
- const lskdb = new LSKDB();
-
- async function getMemberVideos(id, type = 'private') {
- const { uploadedPrivate, uploadedPublic, name } = await getMemberData(id);
- const videosCount = type === 'private' ? uploadedPrivate : uploadedPublic;
- const paginationLast = Math.ceil(videosCount / 48);
- const { iteratable_url } = RULES.URL_DATA(new URL(`https://thisvid.com/members/${id}/${type}_videos/`));
- const memberVideosGenerator = PaginationManager.createPaginationGenerator(0, paginationLast, iteratable_url);
- return { name, videosCount, memberVideosGenerator };
- }
-
- async function getMembersVideos(id, friendsCount, memberGeneratorCallback, type = 'private') {
- let skipFlag = false;
- let skipCount = 1;
- let minVideosCount = 1;
-
- const skipCurrentMember = (n = 1) => { skipFlag = true; skipCount = n; }
- const filterVideosCount = (n = 1) => { minVideosCount = n; }
-
- let membersIds = await getMemberFriends(id, 0, 1);
- getMemberFriends(id, 1).then(r => { membersIds = membersIds.concat(r) });
-
- async function* pageGenerator() {
- let currentGenerator = null;
- for (let c = 0; c < friendsCount - 1; c++) {
- if (lskdb.hasKey(membersIds[c])) continue;
-
- if (!currentGenerator) {
- const { memberVideosGenerator, name, videosCount } = await getMemberVideos(membersIds[c], type);
-
- if (memberVideosGenerator && videosCount >= minVideosCount) {
- currentGenerator = memberVideosGenerator;
- memberGeneratorCallback(name, videosCount, membersIds[c]);
- } else continue;
- }
-
- const { value: { url } = {}, done } = await currentGenerator.next();
-
- if (done || skipFlag) {
- c += skipCount - 1;
- skipCount = 1;
- currentGenerator = null;
- skipFlag = false;
- } else {
- yield { url, offset: c };
- }
- }
-
- }
-
- return {
- pageGenerator: () => pageGenerator(membersIds, type),
- skipCurrentMember,
- filterVideosCount
- };
- }
-
- function createPrivateFeedButton() {
- const container = document.querySelectorAll('.sidebar ul')[1];
- const buttonPrv = parseDom(`<li><a href="https://thisvid.com/my_wall/#private_feed" class="selective"><i class="ico-arrow"></i>My Friends Private Videos</a></li>`);
- const buttonPub = parseDom(`<li><a href="https://thisvid.com/my_wall/#public_feed" class="selective"><i class="ico-arrow"></i>My Friends Public Videos</a></li>`);
- container.append(buttonPub, buttonPrv);
- }
-
- async function createPrivateFeed() {
- createPrivateFeedButton();
- if (!window.location.hash.includes('feed')) return;
- const isPubKey = window.location.hash === '#public_feed';
-
- const container = parseDom('<div class="thumbs-items"></div>');
- const ignored = parseDom('<div class="ignored"><h2>IGNORED:</h2></div>');
-
- Object.assign(defaultSchemeWithPrivateFilter, {
- controlsSkip: [
- { type: "button", innerText: "skip 10", callback: async () => skip(event, 10) },
- { type: "button", innerText: "skip 100", callback: async () => skip(event, 100) },
- { type: "button", innerText: "skip 1000", callback: async () => skip(event, 1000) }],
- controlsFilter: [
- { type: "button", innerText: "filter >10", callback: async () => filterVidsCount(event, 10) },
- { type: "button", innerText: "filter >25", callback: async () => filterVidsCount(event, 25) },
- { type: "button", innerText: "filter >100", callback: async () => filterVidsCount(event, 100) },
- ]
- });
-
- const containerParent = document.querySelector('.main > .container > .content');
- containerParent.innerHTML = '';
- containerParent.nextElementSibling.remove()
- containerParent.append(container);
- container.before(ignored);
- GM_addStyle(`.content { width: auto; }
- .member-videos, .ignored { background: #b3b3b324; min-height: 3rem; margin: 1rem 0px; color: #fff; font-size: 1.24rem; display: flex; flex-wrap: wrap; justify-content: center;
- padding: 10px; width: 100%; }
- .member-videos * { padding: 5px; margin: 4px; }
- .member-videos h2 a { font-size: 1.24rem; margin: 0; padding: 0; display: inline; }
- .ignored * { padding: 4px; margin: 5px; }
- .thumbs-items { display: flex; flex-wrap: wrap; }`);
-
- const { friendsCount } = await getMemberData(RULES.MY_ID);
-
- RULES.INTERSECTION_OBSERVABLE = document.querySelector('.footer');
- RULES.PAGINATION_LAST = friendsCount;
- RULES.CONTAINER = container;
-
- const { pageGenerator, skipCurrentMember, filterVideosCount } = await getMembersVideos(RULES.MY_ID, friendsCount, (name, videosCount, id) => {
- container.append(parseDom(`
- <div class="member-videos" id="mem-${id}">
- <h2><a href="/members/${id}/">${name}</a> ${videosCount} videos</h2>
- <button onClick="hideMemberVideos(event)">ignore 🗡</button>
- <button onClick="hideMemberVideos(event, false)">skip</button>
- </div>`));
- }, isPubKey ? 'public' : 'private');
-
- const ignoredMembers = lskdb.getAllKeys();
- ignoredMembers.forEach(im => {
- document.querySelector('.ignored').append(parseDom(`<button id="#ir-${im}" onClick="unignore(event)">${im} 🗡</button>`));
- });
-
- const skip = (e, n) => {
- skipCurrentMember(n);
- document.querySelector('.thumbs-items').innerHTML = '';
- }
-
- unsafeWindow.hideMemberVideos = (e, ignore = true) => {
- let id = e.target.parentElement.id;
- if (!document.querySelector(`#${id} ~ div`)) {
- skipCurrentMember();
- }
- const box = document.getElementById(id);
- const toDelete = [box];
- let curr = box.nextElementSibling;
- while (curr?.classList.contains('tumbpu')) {
- toDelete.push(curr);
- curr = curr.nextElementSibling;
- }
- toDelete.forEach(e => e.remove());
- id = id.slice(4)
- if (ignore) {
- document.querySelector('.ignored').append(parseDom(`<button id="irm-${id}" onClick="unignore(event)">${id} X</button>`));
- lskdb.setKey(id);
- }
- }
-
- unsafeWindow.unignore = (e) => {
- const id = e.target.id.slice(4);
- lskdb.removeKey(id);
- e.target.remove();
- }
-
- const filterVidsCount = (e, count) => {
- filterVideosCount(count);
- }
-
- new PaginationManager(state, stateLocale, RULES, handleLoadedHTML, SCROLL_RESET_DELAY, pageGenerator);
- new PreviewAnimation(document.body);
- new JabroniOutfitUI(store, defaultSchemeWithPrivateFilter);
- }
-
- //====================================================================================================
-
- async function clearMessages() {
- const sortMsgs = (doc) => {
- doc.querySelectorAll('.entry').forEach(e => {
- const id = e.querySelector('input[name="delete[]"]').value;
- const msg = e.querySelector('.user-comment').innerText;
- if (/has confirmed|declined your|has removed/g.test(msg)) deleteMsg(id);
- });
- }
-
- const deleteMsg = id => {
- const url = `https://thisvid.com/my_messages/inbox/?mode=async&format=json&action=delete&function=get_block&block_id=list_messages_my_conversation_messages&delete[]=${id}`;
- fetch(url).then(res => console.log(url, res?.status));
- }
-
- await Promise.all(Array.from({ length: RULES.PAGINATION_LAST }, (_, i) =>
- fetchHtml(`https://thisvid.com/my_messages/inbox/${i + 1}/`).then(html => sortMsgs(html))));
- }
-
- function clearMessagesButton() {
- const btn = parseDom('<button>clear messages</button>');
- btn.addEventListener('click', clearMessages);
- document.querySelector('.headline').append(btn);
- }
-
- //====================================================================================================
-
- function route() {
- console.log(SponsaaLogo);
-
- if (RULES.LOGGED_IN) {
- defaultSchemeWithPrivateFilter.privateFilter.push(
- { type: "button", innerText: "check access 🔓", callback: checkPrivateVidsAccess });
- }
-
- if (RULES.IS_MY_MEMBER_PAGE) {
- createPrivateFeed();
- }
-
- if (RULES.IS_MESSAGES_PAGE) {
- clearMessagesButton();
- highlightMessages();
- }
-
- if (RULES.IS_VIDEO_PAGE) createDownloadButton();
-
- if (!RULES.PAGE_HAS_VIDEO) return;
-
- const containers = Array.from(RULES.IS_WATCHLATER_KIND ? [RULES.CONTAINER] : document.querySelectorAll('.thumbs-items:not(.thumbs-members)'));
- if (containers.length > 1 && !RULES.IS_MEMBER_PAGE) RULES.CONTAINER = containers[0];
- containers.forEach(c => {
- handleLoadedHTML(c, RULES.IS_MEMBER_PAGE ? c : RULES.CONTAINER, true);
- });
-
- new PreviewAnimation(document.body);
- new JabroniOutfitUI(store, defaultSchemeWithPrivateFilter);
-
- if (RULES.IS_OTHER_MEMBER_PAGE) {
- initFriendship();
- }
-
- if (RULES.PAGINATION_ALLOWED) {
- stateLocale.pagIndexLast = RULES.PAGINATION_LAST;
- if (!RULES.PAGINATION) return;
- new PaginationManager(state, stateLocale, RULES, handleLoadedHTML, SCROLL_RESET_DELAY);
- }
- }
-
- //====================================================================================================
-
- const SCROLL_RESET_DELAY = 350;
- const ANIMATION_DELAY = 750;
-
- const store = new JabroniOutfitStore(defaultStateWithDurationAndPrivacy);
- const { state, stateLocale } = store;
- const { applyFilters, handleLoadedHTML } = new DataManager(RULES, state);
- store.subscribe(applyFilters);
-
- route();