Список пользователей

1
Админ
Постов: 101
2
Элита
Постов: 34
3
Элита
Постов: 28
4
VIP
Постов: 26
5
Дизайнер
Постов: 25
6
Пользователи
Постов: 25
7
Пользователи
Постов: 24
8
Проверенные
Постов: 21

  • Страница 1 из 1
  • 1
Скрипт который подставляет аватарки на форуме
Дата: Вторник, 07.10.2025, 05:09 | Сообщение # 1 | | Написал: Начинающий
Автор темы
Мурчанн не в сети
        Сообщений:101
         Регистрация:20.10.2016

Последние темы информер на форуме 2
Обычно многие, кто пытался создать такой скрипт, сталкивались с проблемами. Я решил показать, что это возможно.
Этот скрипт достаточно умный, он может сам переходить в профиль, брать оттуда нужную аватарку и подставлять её в информер.

Логика в самом скрипте

Код
<script>
/* Последние темы информер
Подставляет аватар последнего комментатора.
Логика:
- берём ник последнего комментатора из .last_post .uLPost (или похожих селекторов)
- проверяем кеш localStorage
- пробуем fetch по href последнего коммента (и по варианту /index/8-0-USERNAME)
- парсим страницу профиля и ищем <img> где src содержит /avatar/ или /ava/
- если нашли — ставим и кешируем; если нет — смотрим userMap; если и там нет — дефолт
*/
(function(){
'use strict';

const DEFAULT_AVATAR = '/Online/ico/p_profile.gif'; // или мой /ava/default.gif
const CHECK_DELAY = 160; // ms между fetch, чтобы не гонять сервер
const CACHE_KEY = 'autoAvatar_user_cache_v2';
const cache = JSON.parse(localStorage.getItem(CACHE_KEY) || '{}');

// Моя готовая карта — вставить осталось полный userMap, если он есть
const userMap = {
"Ник": "#",
"Ник": "#",
"Ник": "#",
"Ник": "#"
// ...добавь свой полный список
};

function saveCache(){ localStorage.setItem(CACHE_KEY, JSON.stringify(cache)); }

// Ищем непосредственно подходящую аватарку в документе (profile page)
function findAvatarSrcInDoc(doc){
const selectors = [
'img[src*="/avatar/"]',
'img[src*="/ava/"]',
'.user_avatar img',
'.ipsUserPhoto img',
'.ipsUserPhotoLink img',
'img.avatar'
];
for(const s of selectors){
const el = doc.querySelector(s);
if(el && el.src && (el.src.indexOf('/avatar/') !== -1 || el.src.indexOf('/ava/') !== -1)){
return new URL(el.getAttribute('src'), location.href).href;
}
}
return null;
}

async function fetchAndFindAvatar(url){
try{
const res = await fetch(url, { cache: 'no-cache' });
if(!res.ok) return null;
const txt = await res.text();
const parser = new DOMParser();
const doc = parser.parseFromString(txt, 'text/html');
return findAvatarSrcInDoc(doc);
}catch(e){
console.warn('autoAvatar: fetch failed', url, e);
return null;
}
}

// Генерация кандидатов url для профиля по нику/существующей href
function buildProfileCandidates(href, username){
const candidates = [];
if(href){
try{ candidates.push(new URL(href, location.href).href); }catch(e){}
}
if(username){
// uCoz часто использует /index/8-0-USERNAME
const safe = encodeURIComponent(username.replace(/\s+/g, '-'));
candidates.push(location.origin + '/index/8-0-' + safe);
// ещё вариант с без кодирования (иногда работает)
candidates.push(location.origin + '/index/8-0-' + username);
}
// убрать дубли
return Array.from(new Set(candidates)).filter(Boolean);
}

// Извлечь ник и href последнего комментатора из блока темы
function getLastCommentInfo(topicEl){
// главный кандидат: .last_post .uLPost (как в моём примере)
let a = topicEl.querySelector('.last_post .uLPost, .last_post a, .uLPost, .last_post span a');
if(!a){
// ещё возможные селекторы (защита)
a = topicEl.querySelector('a[href*="/index/8-"], a[href*="/user/"], .last_user a, .lastpost_author a');
}
if(!a) return null;
const username = (a.textContent || '').trim();
const href = a.getAttribute('href') || null;
return { username: username || null, href: href };
}

// Основная обработка одной темы
async function handleTopic(topicEl){
try{
const avatarImg = topicEl.querySelector('img.ipsUserPhoto, img[class*="avatar"], .ipsUserPhoto img');
if(!avatarImg) return;
if(avatarImg.dataset.autoAvatarDone) return;
avatarImg.dataset.autoAvatarDone = '1';

const info = getLastCommentInfo(topicEl);
if(!info || !info.username){
// нечего искать — оставляем как есть
//console.debug('autoAvatar: no last author found for topic', topicEl);
return;
}
const uname = info.username;
console.debug('autoAvatar: обработка ника', uname);

// 1) кеш
if(cache[uname]){
avatarImg.src = cache[uname];
console.debug('autoAvatar: from cache', uname, cache[uname]);
return;
}

// 2) если в userMap есть — ставим сразу (переходим в конец)
if(userMap[uname]){
avatarImg.src = userMap[uname];
cache[uname] = userMap[uname];
saveCache();
console.info('autoAvatar: from userMap', uname, userMap[uname]);
return;
}

// 3) пробуем fetch по кандидатурам (сначала href, потом /index/8-0-USERNAME)
const candidates = buildProfileCandidates(info.href, uname);
for(const c of candidates){
console.debug('autoAvatar: пробуем профиль', c);
const found = await fetchAndFindAvatar(c);
if(found){
avatarImg.src = found;
cache[uname] = found;
saveCache();
console.info('autoAvatar: найден по профилю', uname, found);
return;
}
// небольшая пауза между попытками
await new Promise(r => setTimeout(r, CHECK_DELAY));
}

// 4) если не нашлось — пробуем искать профиль по /index/* (поиск по всему документу — редкий случай)
// (опционально: можно реализовать поиск каталога пользователей — но на uCoz это не всегда доступно)

// 5) финальный фолбэк — дефолт
avatarImg.src = DEFAULT_AVATAR;
cache[uname] = DEFAULT_AVATAR;
saveCache();
console.warn('autoAvatar: не найден аватар для', uname, '— поставлен дефолт');

}catch(e){
console.error('autoAvatar: handleTopic error', e);
}
}

// Проходим все топики последовательно, чтобы не нагружать сервер
async function processAll(root = document){
const topics = Array.from(root.querySelectorAll('.__topic, tr.__topic, .bb_box .ipb_table .__topic'));
for(const t of topics){
await handleTopic(t);
await new Promise(r => setTimeout(r, CHECK_DELAY));
}
}

// init
document.addEventListener('DOMContentLoaded', ()=>{ processAll().catch(console.error); });

// наблюдатель для динамических вставок
const obs = new MutationObserver(muts=>{
for(const m of muts){
for(const n of m.addedNodes || []){
if(n.nodeType === 1){
processAll(n).catch(console.error);
}
}
}
});
obs.observe(document.body, { childList: true, subtree: true });

})();
</script>


Я у себя создал папки с аватарками,
но он ищет не только в созданных папках
вообще много где: роет, копает.

Скрипт очень большой и длинный, но эффективный. 12

Мурчанн


Прикрепления: 1484551.jpg (139.7 Kb)
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
  • Страница 1 из 1
  • 1
Поиск: