test skadi

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » test skadi » Тестовый форум » Тестовое сообщение


Тестовое сообщение

Сообщений 1 страница 8 из 8

1

Благодарим за выбор нашего сервиса!

0

2

Код:
(function () {
  const FORUM_ID = 2;

  let characters = [];

  fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
    .then(r => r.json())
    .then(d => {
      const topics = d.response || [];

      return Promise.all(
        topics.map(t =>
          fetch(`/api.php?method=post.get&topic_id=${t.id}&limit=1`)
            .then(r => r.json())
        )
      );
    })
    .then(postsArray => {

      characters = postsArray.map(r => {
        const html = r.response?.[0]?.message || "";

        // создаём временный DOM
        const temp = document.createElement("div");
        temp.innerHTML = html;

        const name =
          temp.querySelector(".m-name")?.innerText.trim() || "NO NAME";

        const face =
          temp.querySelector(".m-face")?.innerText.trim() || "";

        const gender =
          temp.querySelector(".m-gender")?.innerText.trim() || "";

        return { name, face, gender };
      });

      console.log("CHARACTERS:", characters);

      render(characters);
    });

  function render(chars) {
    const root = document.getElementById("faces-root");
    if (!root) return;

    root.innerHTML = chars
      .map(c => `<div>${c.name} — ${c.face} — ${c.gender}</div>`)
      .join("");
  }
})();

0

3

Код:
<script type="text/javascript">
(function () {
  const FORUM_ID = 2;

  fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
    .then(r => r.json())
    .then(d => {
      const topics = d.response || [];

      return Promise.all(
        topics.map(t =>
          fetch(`/api.php?method=post.get&topic_id=${t.id}&limit=1`)
            .then(r => r.json())
        )
      );
    })
    .then(postsArray => {

      const characters = postsArray.map(r => {
        const html = r.response?.[0]?.message || "";

        const temp = document.createElement("div");
        temp.innerHTML = html;

        const name =
          temp.querySelector(".m-name")?.innerText.trim() || "NO NAME";

        const face =
          temp.querySelector(".m-face")?.innerText.trim() || "";

        const gender =
          temp.querySelector(".m-gender")?.innerText.trim().toLowerCase() || "";

        return { name, face, gender };
      });

      console.log("ALL CHARACTERS:", characters);

      // 💥 нормализация пола
      const maleWords = ["м", "муж", "мужской", "male", "man", "m"];
      const femaleWords = ["ж", "жен", "женский", "female", "woman", "f"];

      const males = [];
      const females = [];

      characters.forEach(c => {
        const g = c.gender;

        if (femaleWords.includes(g)) {
          females.push(c);
        } else if (maleWords.includes(g)) {
          males.push(c);
        } else {
          females.push(c);
        }
      });

      render(males, females);
    });

  function render(males, females) {
    const root = document.getElementById("faces-root");
    if (!root) return;

    root.innerHTML = `
      <div class="faces-wrapper">

        <div class="faces-column">
          <h2>Мужские внешности</h2>
          ${males.map(c => `
            <div class="face-item">
              ${c.name} — ${c.face}
            </div>
          `).join("")}
        </div>

        <div class="faces-column">
          <h2>Женские внешности</h2>
          ${females.map(c => `
            <div class="face-item">
              ${c.name} — ${c.face}
            </div>
          `).join("")}
        </div>

      </div>
    `;
  }
})();
</script>

0

4

Код:
<script type="text/javascript">
(function () {
  const FORUM_ID = 2;

  fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
    .then(r => r.json())
    .then(d => {
      const topics = d.response || [];

      return Promise.all(
        topics.map(t =>
          fetch(`/api.php?method=post.get&topic_id=${t.id}&limit=1`)
            .then(r => r.json())
        )
      );
    })
    .then(postsArray => {

      const characters = postsArray.map(r => {
        let html = r.response?.[0]?.message || "";

        // 💥 чистим html от <p> и [html]
        html = html
          .replace(/\[html\]|\[\/html\]/gi, "")
          .replace(/<p>/gi, "")
          .replace(/<\/p>/gi, "")
          .replace(/&nbsp;/gi, " ");

        const temp = document.createElement("div");
        temp.innerHTML = html;

        const name =
          temp.querySelector(".m-name")?.innerText.trim() || "NO NAME";

        const face =
          temp.querySelector(".m-face")?.innerText.trim() || "";

        const gender =
          temp.querySelector(".m-gender")?.innerText.trim().toLowerCase() || "";

        return { name, face, gender };
      });

      console.log("ALL:", characters);

      // 💥 варианты пола
      const maleWords = ["м", "муж", "мужской", "male", "man", "m"];
      const femaleWords = ["ж", "жен", "женский", "female", "woman", "f"];

      const males = [];
      const females = [];

      characters.forEach(c => {
        const g = c.gender;

        if (femaleWords.includes(g)) {
          females.push(c);
        } else if (maleWords.includes(g)) {
          males.push(c);
        } else {
          females.push(c);
        }
      });

      render(males, females);
    });

  // 💥 группировка по буквам
  function groupByLetters(list) {
    const groups = {
      "a-b-c-d": [],
      "e-f-g-h": [],
      "i-j-k-l": [],
      "m-n-o-p": [],
      "q-r-s-t": [],
      "u-v-w-x-y-z": []
    };

    list.forEach(c => {
      const first = c.face.trim().charAt(0).toLowerCase();

      if ("abcd".includes(first)) groups["a-b-c-d"].push(c);
      else if ("efgh".includes(first)) groups["e-f-g-h"].push(c);
      else if ("ijkl".includes(first)) groups["i-j-k-l"].push(c);
      else if ("mnop".includes(first)) groups["m-n-o-p"].push(c);
      else if ("qrst".includes(first)) groups["q-r-s-t"].push(c);
      else groups["u-v-w-x-y-z"].push(c);
    });

    return groups;
  }

  function renderColumn(title, list) {
    const sorted = list.sort((a, b) => {
      const cleanA = a.face.trim().toLowerCase();
      const cleanB = b.face.trim().toLowerCase();

      return cleanA.localeCompare(cleanB, 'en', { sensitivity: 'base' });
    });

    const groups = groupByLetters(sorted);

    return `
      <div class="faces-column">
        <h2>${title}</h2>

        ${Object.entries(groups).map(([group, items]) => {
          if (!items.length) return "";

          return `
            <div class="face-group">
              <div class="face-letter">${group}</div>

              ${items.map(c => `
                <div class="face-item">
                  ${c.face} — ${c.name}
                </div>
              `).join("")}

            </div>
          `;
        }).join("")}

      </div>
    `;
  }

  function render(males, females) {
    const root = document.getElementById("faces-root");
    if (!root) return;

    root.innerHTML = `
      <div class="faces-wrapper">
        ${renderColumn("Мужские внешности", males)}
        ${renderColumn("Женские внешности", females)}
      </div>
    `;
  }
})();
</script>

0

5

Код:
<script type="text/javascript">
window.addEventListener("DOMContentLoaded", function () {

  const FORUM_ID = 2;
  const CACHE_KEY = `faces_cache_forum_${FORUM_ID}`;
  const CACHE_TTL = 1000 * 60 * 60;

  let isLoading = false;

  const root = document.getElementById("faces-root");

  if (!root) {
    console.error("❌ НЕТ <div id='faces-root'></div>");
    return;
  }

  console.log("SCRIPT STARTED");

  // ======================
  // START (CACHE OR LOAD)
  // ======================
  try {
    const cached = localStorage.getItem(CACHE_KEY);

    if (cached) {
      const parsed = JSON.parse(cached);

      if (Date.now() - parsed.time < CACHE_TTL) {
        console.log("CACHE HIT");
        render(parsed.data.males, parsed.data.females);
      } else {
        load();
      }
    } else {
      load();
    }
  } catch (e) {
    console.warn("CACHE ERROR", e);
    load();
  }

  // ======================
  // LOAD API
  // ======================
  function load() {

    if (isLoading) return;
    isLoading = true;

    console.log("LOADING API...");

    fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
      .then(r => r.json())
      .then(d => {

        const topics = d.response || [];

        return Promise.all(
          topics.map(t =>
            fetch(`/api.php?method=post.get&topic_id=${t.id}&limit=1`)
              .then(r => r.json())
          )
        );
      })
      .then(postsArray => {

        const characters = postsArray.map(r => {
          let html = r.response?.[0]?.message || "";

          const temp = document.createElement("div");
          temp.innerHTML = html;

          return {
            name: temp.querySelector(".m-name")?.innerText.trim() || "NO NAME",
            face: temp.querySelector(".m-face")?.innerText.trim() || "",
            gender: (temp.querySelector(".m-gender")?.innerText || "").toLowerCase()
          };
        }).filter(c => c.face);

        const males = [];
        const females = [];

        const maleWords = ["м", "муж", "male", "man", "m"];
        const femaleWords = ["ж", "жен", "female", "woman", "f"];

        characters.forEach(c => {
          if (femaleWords.includes(c.gender)) females.push(c);
          else if (maleWords.includes(c.gender)) males.push(c);
          else females.push(c);
        });

        localStorage.setItem(CACHE_KEY, JSON.stringify({
          time: Date.now(),
          data: { males, females }
        }));

        console.log("RENDER");
        render(males, females);

        isLoading = false;
      })
      .catch(err => {
        console.error("API ERROR", err);
        isLoading = false;
      });
  }

  // ======================
  // GROUPING
  // ======================
  function groupByLetters(list) {
    const groups = {
      "a-b-c-d": [],
      "e-f-g-h": [],
      "i-j-k-l": [],
      "m-n-o-p": [],
      "q-r-s-t": [],
      "u-v-w-x-y-z": []
    };

    list.forEach(c => {
      const first = (c.face || "").trim().charAt(0).toLowerCase();

      if ("abcd".includes(first)) groups["a-b-c-d"].push(c);
      else if ("efgh".includes(first)) groups["e-f-g-h"].push(c);
      else if ("ijkl".includes(first)) groups["i-j-k-l"].push(c);
      else if ("mnop".includes(first)) groups["m-n-o-p"].push(c);
      else if ("qrst".includes(first)) groups["q-r-s-t"].push(c);
      else groups["u-v-w-x-y-z"].push(c);
    });

    return groups;
  }

  function renderColumn(title, list) {

    const sorted = list.slice().sort((a, b) =>
      (a.face || "").toLowerCase().localeCompare((b.face || "").toLowerCase())
    );

    const groups = groupByLetters(sorted);

    return `
      <div class="faces-column">
        <h2>${title}</h2>

        ${Object.entries(groups).map(([group, items]) => {
          if (!items.length) return "";

          return `
            <div class="face-group">
              <div class="face-letter">${group}</div>

              ${items.map(c => `
                <div class="face-item">
                  ${c.face} — ${c.name}
                </div>
              `).join("")}
            </div>
          `;
        }).join("")}

      </div>
    `;
  }

  // ======================
  // RENDER + BUTTON
  // ======================
function render(males, females) {

  const malesColumn = document.getElementById("males-column");
  const femalesColumn = document.getElementById("females-column");

  malesColumn.innerHTML = renderColumn("Мужские внешности", males);
  femalesColumn.innerHTML = renderColumn("Женские внешности", females);

  document.getElementById("faces-refresh-btn").onclick = () => {
    localStorage.removeItem(CACHE_KEY);
    load();
  };
}

});
</script>

0

6

Код:
<script type="text/javascript">
window.addEventListener("DOMContentLoaded", function () {

  const FORUM_ID = 2;
  const CACHE_KEY = `faces_cache_forum_${FORUM_ID}`;
  const CACHE_TTL = 1000 * 60 * 60;

  let isLoading = false;

  const root = document.getElementById("faces-root");

  if (!root) {
    console.error("❌ НЕТ faces-root");
    return;
  }

  console.log("SCRIPT STARTED");

  // ======================
  // CACHE
  // ======================
  try {
    const cached = localStorage.getItem(CACHE_KEY);

    if (cached) {
      const parsed = JSON.parse(cached);

      if (Date.now() - parsed.time < CACHE_TTL) {
        console.log("CACHE HIT");
        render(parsed.data.males, parsed.data.females);
      } else {
        load();
      }
    } else {
      load();
    }
  } catch (e) {
    console.warn("CACHE ERROR", e);
    load();
  }

  // ======================
  // LOAD
  // ======================
  function load() {

    if (isLoading) return;
    isLoading = true;

    console.log("LOADING TOPICS...");

    fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
      .then(r => r.json())
      .then(d => {

        const topics = d.response || [];

        console.log("TOPICS TEST:", topics[0]); // 🔥 TEST 1

        return Promise.all(
          topics.map(t =>
            fetch(`/viewtopic.php?id=${t.id}`)
              .then(r => r.text())
              .then(html => {

                const temp = document.createElement("div");
                temp.innerHTML = html;

                // ======================
                // ПЕРВЫЙ ПОСТ ТЕМЫ
                // ======================
                const firstPost = temp.querySelector(".post");

                // ======================
                // ID АВТОРА
                // ======================
                const userId = firstPost?.dataset?.userId;

                console.log("DEBUG USER ID:", userId, "TOPIC:", t.id); // 🔥 TEST 2

                // ======================
                // АНКЕТНЫЕ ДАННЫЕ
                // ======================
                return {
                  id: userId,
                  name: temp.querySelector(".m-name")?.innerText.trim() || "NO NAME",
                  face: temp.querySelector(".m-face")?.innerText.trim() || "",
                  gender: (temp.querySelector(".m-gender")?.innerText || "").toLowerCase()
                };

              })
          )
        );
      })
      .then(results => {

        const characters = results
          .filter(Boolean)
          .filter(c => c.face);

        console.log("CHARACTERS TEST:", characters[0]); // 🔥 TEST 3

        const males = [];
        const females = [];

        const maleWords = ["м", "муж", "male", "man", "m"];
        const femaleWords = ["ж", "жен", "female", "woman", "f"];

        characters.forEach(c => {
          if (femaleWords.includes(c.gender)) females.push(c);
          else if (maleWords.includes(c.gender)) males.push(c);
          else females.push(c);
        });

        localStorage.setItem(CACHE_KEY, JSON.stringify({
          time: Date.now(),
          data: { males, females }
        }));

        render(males, females);

        isLoading = false;
      })
      .catch(err => {
        console.error("API ERROR", err);
        isLoading = false;
      });
  }

  // ======================
  // GROUPING
  // ======================
  function groupByLetters(list) {

    const groups = {
      "a-b-c-d": [],
      "e-f-g-h": [],
      "i-j-k-l": [],
      "m-n-o-p": [],
      "q-r-s-t": [],
      "u-v-w-x-y-z": []
    };

    list.forEach(c => {
      const first = (c.face || "").trim().charAt(0).toLowerCase();

      if ("abcd".includes(first)) groups["a-b-c-d"].push(c);
      else if ("efgh".includes(first)) groups["e-f-g-h"].push(c);
      else if ("ijkl".includes(first)) groups["i-j-k-l"].push(c);
      else if ("mnop".includes(first)) groups["m-n-o-p"].push(c);
      else if ("qrst".includes(first)) groups["q-r-s-t"].push(c);
      else groups["u-v-w-x-y-z"].push(c);
    });

    return groups;
  }

  // ======================
  // RENDER
  // ======================
  function renderColumn(title, list) {

    const sorted = list.slice().sort((a, b) =>
      (a.face || "").toLowerCase().localeCompare((b.face || "").toLowerCase())
    );

    const groups = groupByLetters(sorted);

    return `
      <div class="faces-column">
        <h2>${title}</h2>

        ${Object.entries(groups).map(([group, items]) => {
          if (!items.length) return "";

          return `
            <div class="face-group">
              <div class="face-letter">${group}</div>

              ${items.map(c => `
                <div class="face-item">
                  <a href="/profile.php?id=${c.id}">
                    ${c.face} — ${c.name}
                  </a>
                </div>
              `).join("")}

            </div>
          `;
        }).join("")}

      </div>
    `;
  }

  function render(males, females) {

    root.innerHTML = `
      <div style="display:flex; justify-content:flex-end; margin-bottom:10px;">
        <button id="faces-refresh-btn">Обновить</button>
      </div>

      <div class="faces-wrapper">
        <div class="faces-columns">
          ${renderColumn("Мужские внешности", males)}
          ${renderColumn("Женские внешности", females)}
        </div>
      </div>
    `;

    document.getElementById("faces-refresh-btn").onclick = () => {
      localStorage.removeItem(CACHE_KEY);
      load();
    };
  }

});
</script>

0

7

Код:
<script type="text/javascript">
window.addEventListener("DOMContentLoaded", function () {

  const FORUM_ID = 2;
  const root = document.getElementById("names-root");

  if (!root) {
    console.error("❌ НЕТ names-root");
    return;
  }

  console.log("NAMES SCRIPT STARTED");

  // ======================
  // SPLIT NAME
  // ======================
  function splitName(fullName) {
    const parts = fullName.trim().split(/\s+/);

    return {
      firstName: parts[0] || "",
      lastName: parts.slice(1).join(" ") || ""
    };
  }

  // ======================
  // LOAD DATA
  // ======================
  fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
    .then(r => r.json())
    .then(d => {

      const topics = d.response || [];

      return Promise.all(
        topics.map(t =>
          fetch(`/viewtopic.php?id=${t.id}`)
            .then(r => r.text())
            .then(html => {

              const temp = document.createElement("div");
              temp.innerHTML = html;

              const firstPost = temp.querySelector(".post");
              const userId = firstPost?.dataset?.userId;

              const fullName = temp.querySelector(".m-name")?.innerText.trim() || "";

              const { firstName, lastName } = splitName(fullName);

              return {
                id: userId,
                fullName,
                firstName: firstName.toLowerCase(),
                lastName: lastName.toLowerCase()
              };
            })
        )
      );
    })
    .then(characters => {

      // ======================
      // УБИРАЕМ ПУСТОЕ
      // ======================
      characters = characters.filter(c => c.fullName);

      // ======================
      // УНИКАЛЬНЫЕ ИМЕНА
      // ======================
      const firstNames = [];
      const lastNames = [];

      characters.forEach(c => {

        if (c.firstName) {
          firstNames.push({
            key: c.firstName,
            label: c.fullName,
            id: c.id
          });
        }

        if (c.lastName) {
          lastNames.push({
            key: c.lastName,
            label: c.fullName,
            id: c.id
          });
        }

      });

      render(firstNames, lastNames);
    });

  // ======================
  // GROUP
  // ======================
  function groupByLetters(list) {

    const groups = {
      "a-b-c-d": [],
      "e-f-g-h": [],
      "i-j-k-l": [],
      "m-n-o-p": [],
      "q-r-s-t": [],
      "u-v-w-x-y-z": []
    };

    list.forEach(c => {
      const first = (c.key || "").charAt(0);

      if ("abcd".includes(first)) groups["a-b-c-d"].push(c);
      else if ("efgh".includes(first)) groups["e-f-g-h"].push(c);
      else if ("ijkl".includes(first)) groups["i-j-k-l"].push(c);
      else if ("mnop".includes(first)) groups["m-n-o-p"].push(c);
      else if ("qrst".includes(first)) groups["q-r-s-t"].push(c);
      else groups["u-v-w-x-y-z"].push(c);
    });

    return groups;
  }

  // ======================
  // COLUMN
  // ======================
  function renderColumn(title, list) {

    const sorted = list.sort((a, b) =>
      a.key.localeCompare(b.key)
    );

    const groups = groupByLetters(sorted);

    return `
      <div class="faces-column">
        <h2>${title}</h2>

        ${Object.entries(groups).map(([group, items]) => {
          if (!items.length) return "";

          return `
            <div class="face-group">
              <div class="face-letter">${group}</div>

              ${items.map(c => `
                <div class="face-item">
                  <a href="/profile.php?id=${c.id}">
                    ${c.key} — ${c.label}
                  </a>
                </div>
              `).join("")}

            </div>
          `;
        }).join("")}

      </div>
    `;
  }

  // ======================
  // RENDER
  // ======================
  function render(firstNames, lastNames) {

    root.innerHTML = `
      <div class="faces-wrapper">
        <div class="faces-columns">
          ${renderColumn("Имена", firstNames)}
          ${renderColumn("Фамилии", lastNames)}
        </div>
      </div>
    `;
  }

});
</script>



<script type="text/javascript">
window.addEventListener("DOMContentLoaded", function () {

  const FORUM_ID = 2;
  const CACHE_KEY = `faces_cache_forum_${FORUM_ID}`;
  const CACHE_TTL = 1000 * 60 * 60;

  let isLoading = false;

  const root = document.getElementById("faces-root");

  if (!root) {
    console.error("❌ НЕТ faces-root");
    return;
  }

  console.log("SCRIPT STARTED");

  // ======================
  // CACHE
  // ======================
  try {
    const cached = localStorage.getItem(CACHE_KEY);

    if (cached) {
      const parsed = JSON.parse(cached);

      if (Date.now() - parsed.time < CACHE_TTL) {
        console.log("CACHE HIT");
        render(parsed.data.males, parsed.data.females);
      } else {
        load();
      }
    } else {
      load();
    }
  } catch (e) {
    console.warn("CACHE ERROR", e);
    load();
  }

  // ======================
  // LOAD
  // ======================
  function load() {

    if (isLoading) return;
    isLoading = true;

    console.log("LOADING TOPICS...");

    fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
      .then(r => r.json())
      .then(d => {

        const topics = d.response || [];

        console.log("TOPICS TEST:", topics[0]); // 🔥 TEST 1

        return Promise.all(
          topics.map(t =>
            fetch(`/viewtopic.php?id=${t.id}`)
              .then(r => r.text())
              .then(html => {

                const temp = document.createElement("div");
                temp.innerHTML = html;

                // ======================
                // ПЕРВЫЙ ПОСТ ТЕМЫ
                // ======================
                const firstPost = temp.querySelector(".post");

                // ======================
                // ID АВТОРА
                // ======================
                const userId = firstPost?.dataset?.userId;

                console.log("DEBUG USER ID:", userId, "TOPIC:", t.id); // 🔥 TEST 2

                // ======================
                // АНКЕТНЫЕ ДАННЫЕ
                // ======================
                return {
                  id: userId,
                  name: temp.querySelector(".m-name")?.innerText.trim() || "NO NAME",
                  face: temp.querySelector(".m-face")?.innerText.trim() || "",
                  gender: (temp.querySelector(".m-gender")?.innerText || "").toLowerCase()
                };

              })
          )
        );
      })
      .then(results => {

        const characters = results
          .filter(Boolean)
          .filter(c => c.face);

// ======================
// ДУБЛИ ВНЕШНОСТЕЙ
// ======================
const faceCount = {};

characters.forEach(c => {
  const key = (c.face || "").toLowerCase().trim();
  faceCount[key] = (faceCount[key] || 0) + 1;
});

characters.forEach(c => {
  const key = (c.face || "").toLowerCase().trim();
  c.isDuplicate = faceCount[key] > 1;
});

        console.log("CHARACTERS TEST:", characters[0]); // 🔥 TEST 3

        const males = [];
        const females = [];

        const maleWords = ["м", "муж", "male", "man", "m"];
        const femaleWords = ["ж", "жен", "female", "woman", "f"];

        characters.forEach(c => {
          if (femaleWords.includes(c.gender)) females.push(c);
          else if (maleWords.includes(c.gender)) males.push(c);
          else females.push(c);
        });

        localStorage.setItem(CACHE_KEY, JSON.stringify({
          time: Date.now(),
          data: { males, females }
        }));

        render(males, females);

        isLoading = false;
      })
      .catch(err => {
        console.error("API ERROR", err);
        isLoading = false;
      });
  }

  // ======================
  // GROUPING
  // ======================
  function groupByLetters(list) {

    const groups = {
      "a-b-c-d": [],
      "e-f-g-h": [],
      "i-j-k-l": [],
      "m-n-o-p": [],
      "q-r-s-t": [],
      "u-v-w-x-y-z": []
    };

    list.forEach(c => {
      const first = (c.face || "").trim().charAt(0).toLowerCase();

      if ("abcd".includes(first)) groups["a-b-c-d"].push(c);
      else if ("efgh".includes(first)) groups["e-f-g-h"].push(c);
      else if ("ijkl".includes(first)) groups["i-j-k-l"].push(c);
      else if ("mnop".includes(first)) groups["m-n-o-p"].push(c);
      else if ("qrst".includes(first)) groups["q-r-s-t"].push(c);
      else groups["u-v-w-x-y-z"].push(c);
    });

    return groups;
  }

  // ======================
  // RENDER
  // ======================
  function renderColumn(title, list) {

    const sorted = list.slice().sort((a, b) =>
      (a.face || "").toLowerCase().localeCompare((b.face || "").toLowerCase())
    );

    const groups = groupByLetters(sorted);

    return `
      <div class="faces-column">
        <h2>${title}</h2>

        ${Object.entries(groups).map(([group, items]) => {
          if (!items.length) return "";

          return `
            <div class="face-group">
              <div class="face-letter">${group}</div>

              ${items.map(c => `
                <div class="face-item">
                  <a href="/profile.php?id=${c.id}">
                    ${c.face}${c.isDuplicate ? " ★" : ""} — ${c.name}
                  </a>
                </div>
              `).join("")}

            </div>
          `;
        }).join("")}

      </div>
    `;
  }

  function render(males, females) {

    root.innerHTML = `
      <div style="display:flex; justify-content:flex-end; margin-bottom:10px;">
        <button id="faces-refresh-btn">Обновить</button>
      </div>

      <div class="faces-wrapper">
        <div class="faces-columns">
          ${renderColumn("Мужские внешности", males)}
          ${renderColumn("Женские внешности", females)}
        </div>
      </div>
    `;

    document.getElementById("faces-refresh-btn").onclick = () => {
      localStorage.removeItem(CACHE_KEY);
      load();
    };
  }

});
</script>

0

8

Код:
<script type="text/javascript">
window.addEventListener("DOMContentLoaded", function () {

  const FORUM_ID = 2;
  const CACHE_KEY = `characters_cache_${FORUM_ID}`;
  const CACHE_TTL = 1000 * 60 * 60;

  const facesRoot = document.getElementById("faces-root");
  const namesRoot = document.getElementById("names-root");

  if (!facesRoot && !namesRoot) return;

  console.log("SCRIPT STARTED");

  // ======================
  // CACHE
  // ======================
  try {
    const cached = localStorage.getItem(CACHE_KEY);

    if (cached) {
      const parsed = JSON.parse(cached);

      if (Date.now() - parsed.time < CACHE_TTL) {
        renderAll(parsed.data);
      } else {
        load();
      }
    } else {
      load();
    }
  } catch (e) {
    console.warn("CACHE ERROR", e);
    load();
  }

  // ======================
  // HELPERS
  // ======================
  function getField(root, cls) {
    return (root?.querySelector(`.${cls}`)?.innerText || "").trim();
  }

  // ======================
  // LOAD DATA
  // ======================
  function load() {

    console.log("LOADING...");

    fetch(`/api.php?method=topic.get&forum_id=${FORUM_ID}`)
      .then(r => r.json())
      .then(d => {

        const topics = d.response || [];

        return Promise.all(
          topics.map(t =>
            fetch(`/viewtopic.php?id=${t.id}`)
              .then(r => r.text())
              .then(html => {

                const temp = document.createElement("div");
                temp.innerHTML = html;

                const firstPost = temp.querySelector(".post");
                const userId = firstPost?.dataset?.userId;

                const ank = temp.querySelector(".m-ank");

                const name = getField(ank, "m-name");
                const face = getField(ank, "m-face");

                // 💥 ВАЖНО: берём ВСЁ как текст (обход битой кодировки)
                const genderRaw = (ank?.innerText || "").toLowerCase();

                return {
                  id: userId,
                  name,
                  face,
                  genderRaw
                };

              })
          )
        );
      })
      .then(characters => {

        characters = characters.filter(c => c.face || c.name);

        // ======================
        // ДУБЛИ ВНЕШНОСТЕЙ
        // ======================
        const faceCount = {};

        characters.forEach(c => {
          const key = (c.face || "").toLowerCase().trim();
          faceCount[key] = (faceCount[key] || 0) + 1;
        });

        characters.forEach(c => {
          const key = (c.face || "").toLowerCase().trim();
          c.isDuplicate = faceCount[key] > 1;
        });

        // ======================
        // ПОЛ (СТАБИЛЬНО ЧЕРЕЗ TEXT)
        // ======================
        const males = [];
        const females = [];

        const maleWords = ["м", "муж", "male", "man"];
        const femaleWords = ["ж", "жен", "female", "woman"];

        characters.forEach(c => {

          const g = c.genderRaw;

          if (femaleWords.some(w => g.includes(w))) {
            females.push(c);
          } else if (maleWords.some(w => g.includes(w))) {
            males.push(c);
          } else {
            females.push(c); // дефолт
          }

        });

        // ======================
        // ИМЕНА / ФАМИЛИИ
        // ======================
        const firstNames = [];
        const lastNames = [];

        characters.forEach(c => {

          const parts = (c.name || "").split(/\s+/);

          const first = (parts[0] || "").toLowerCase();
          const last = (parts.slice(1).join(" ") || "").toLowerCase();

          if (first) {
            firstNames.push({ key: first, label: c.name, id: c.id });
          }

          if (last) {
            lastNames.push({ key: last, label: c.name, id: c.id });
          }

        });

        const data = { males, females, firstNames, lastNames };

        localStorage.setItem(CACHE_KEY, JSON.stringify({
          time: Date.now(),
          data
        }));

        renderAll(data);
      })
      .catch(err => {
        console.error("API ERROR", err);
      });
  }

  // ======================
  // GROUPING
  // ======================
  function groupByLetters(list, keyName) {

    const groups = {
      "a-b-c-d": [],
      "e-f-g-h": [],
      "i-j-k-l": [],
      "m-n-o-p": [],
      "q-r-s-t": [],
      "u-v-w-x-y-z": []
    };

    list.forEach(c => {

      const first = (c[keyName] || "")
        .trim()
        .charAt(0)
        .toLowerCase();

      if ("abcd".includes(first)) groups["a-b-c-d"].push(c);
      else if ("efgh".includes(first)) groups["e-f-g-h"].push(c);
      else if ("ijkl".includes(first)) groups["i-j-k-l"].push(c);
      else if ("mnop".includes(first)) groups["m-n-o-p"].push(c);
      else if ("qrst".includes(first)) groups["q-r-s-t"].push(c);
      else groups["u-v-w-x-y-z"].push(c);
    });

    return groups;
  }

  // ======================
  // RENDER FACES
  // ======================
  function renderFaces(root, males, females) {

    function column(title, list) {

      const sorted = list.slice().sort((a, b) =>
        (a.face || "").localeCompare(b.face || "")
      );

      const groups = groupByLetters(sorted, "face");

      return `
        <div class="faces-column">
          <h2>${title}</h2>

          ${Object.entries(groups).map(([g, items]) => {
            if (!items.length) return "";

            return `
              <div class="face-group">
                <div class="face-letter">${g}</div>

                ${items.map(c => `
                  <div class="face-item">
                    <a href="/profile.php?id=${c.id}">
                      ${c.face}${c.isDuplicate ? " ★" : ""} — ${c.name}
                    </a>
                  </div>
                `).join("")}

              </div>
            `;
          }).join("")}

        </div>
      `;
    }

    root.innerHTML = `
      <div style="display:flex; justify-content:flex-end; margin-bottom:10px;">
        <button id="refresh-all">Обновить</button>
      </div>

      <div class="faces-wrapper">
        <div class="faces-columns">
          ${column("Мужские внешности", males)}
          ${column("Женские внешности", females)}
        </div>
      </div>
    `;
  }

  // ======================
  // RENDER NAMES
  // ======================
  function renderNames(root, firstNames, lastNames) {

    function column(title, list) {

      const sorted = list.slice().sort((a, b) =>
        a.key.localeCompare(b.key)
      );

      const groups = groupByLetters(sorted, "key");

      return `
        <div class="faces-column">
          <h2>${title}</h2>

          ${Object.entries(groups).map(([g, items]) => {
            if (!items.length) return "";

            return `
              <div class="face-group">
                <div class="face-letter">${g}</div>

                ${items.map(c => `
                  <div class="face-item">
                    <a href="/profile.php?id=${c.id}">
                      ${c.key} — ${c.label}
                    </a>
                  </div>
                `).join("")}

              </div>
            `;
          }).join("")}

        </div>
      `;
    }

    root.innerHTML = `
      <div class="faces-wrapper">
        <div class="faces-columns">
          ${column("Имена", firstNames)}
          ${column("Фамилии", lastNames)}
        </div>
      </div>
    `;
  }

  // ======================
  // RENDER ALL
  // ======================
  function renderAll(data) {

    if (facesRoot) {
      renderFaces(facesRoot, data.males, data.females);
    }

    if (namesRoot) {
      renderNames(namesRoot, data.firstNames, data.lastNames);
    }

    const btn = document.getElementById("refresh-all");
    if (btn) {
      btn.onclick = () => {
        localStorage.removeItem(CACHE_KEY);
        load();
      };
    }
  }

});
</script>

0


Вы здесь » test skadi » Тестовый форум » Тестовое сообщение


Рейтинг форумов | Создать форум бесплатно