Greasy Fork is available in English.

Pixiv瀑布流

以瀑布流样式刷P站

// ==UserScript==
// @name         Pixiv瀑布流
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  以瀑布流样式刷P站
// @author       wlm3201
// @match        https://www.pixiv.net/discovery+
// @icon         https://www.pixiv.net/favicon.ico
// @grant        none
// @license MIT
// ==/UserScript==
(function () {
  let template = `<!DOCTYPE html>
<html lang="zh">
  <head>
    <title>[pixiv] 发现</title>
    <meta name="color-scheme" content="dark" />
<style>body {
  margin: 0;
  background-color: black;
  color: white;
  overflow-y: scroll;
}
#imgbox {
  display: flex;
  flex-wrap: wrap;
  line-height: 0;
  column-gap: 20px;
  row-gap: 20px;
}
#imgbox::after {
  content: "";
  flex-grow: 114514;
}
.wrap {
  position: relative;
  min-height: 300px;
}
.wrap > img {
  width: 100%;
  border-radius: 20px;
  cursor: pointer;
}
.info {
  display: none;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 50px;
  line-height: normal;
  border-radius: 10px;
  background-color: rgba(0, 0, 0, 0.5);
}
.wrap:hover > .info {
  display: block;
}
.title {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  display: flex;
  justify-content: center;
}
.user {
  position: absolute;
  left: 60px;
  top: 0;
}
.profile {
  cursor: pointer;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 50px;
  height: 50px;
  border-radius: 25px;
}
.like {
  cursor: pointer;
  position: absolute;
  bottom: 5px;
  right: 5px;
  font-size: 20px;
  user-select: none;
}
</style>
</head>
  <body>
    <div id="imgbox"></div>
  </body>
</html>
`;
  document.documentElement.innerHTML = template;

  let imgbox = document.getElementById("imgbox");
  let loading = 0;
  if (localStorage.getItem("x-csrf-token") === null) {
    fetch("https://www.pixiv.net").then(async (r) =>
      localStorage.setItem(
        "x-csrf-token",
        (await r.text()).match(/"token":"(\w+)"/)[1]
      )
    );
  }
  async function loadimgs() {
    loading = 1;
    let r = await fetch(
      "https://www.pixiv.net/ajax/discovery/artworks?mode=all&limit=100&lang=zh",
      { method: "GET", credentials: "include" }
    );
    let data = await r.json();
    for (let illust of data.body.thumbnails.illust) {
      let wrap = document.createElement("div");
      wrap.className = "wrap";
      let ratio = illust.width / illust.height;
      wrap.style.flexBasis = ratio * 300 + "px";
      wrap.style.flexGrow = ratio;

      let img = new Image();
      img.loading = "lazy";
      img.illust = illust;
      img.src = illust.urls["1200x1200"].replace(
        "img-master",
        "c/600x1200_90/img-master"
      );
      img.onclick = () =>
        window.open(`https://www.pixiv.net/artworks/${illust.id}`);
      wrap.appendChild(img);

      let info = document.createElement("div");
      info.className = "info";
      wrap.appendChild(info);

      let profile = new Image();
      profile.className = "profile";
      profile.loading = "lazy";
      profile.src = illust.profileImageUrl;
      info.appendChild(profile);
      profile.onclick = () =>
        window.open(`https://www.pixiv.net/users/${illust.userId}`, "_blank");

      let title = document.createElement("div");
      title.className = "title";
      title.innerText = illust.title;
      info.appendChild(title);

      let user = document.createElement("div");
      user.className = "user";
      user.innerText = illust.userName;
      info.appendChild(user);

      let like = document.createElement("div");
      like.className = "like";
      like.innerText = "🤍";
      info.appendChild(like);
      like.onclick = () => {
        if (!img.like) {
          fetch("https://www.pixiv.net/ajax/illusts/bookmarks/add", {
            headers: {
              "content-type": "application/json; charset=utf-8",
              "x-csrf-token": localStorage.getItem("x-csrf-token"),
            },
            body: `{"illust_id":"${illust.id}","restrict":0,"comment":"","tags":[]}`,
            method: "POST",
            credentials: "include",
          }).then(async (r) => {
            if (!r.ok) return;
            let data = await r.json();
            illust.bookmark_id = data.body.last_bookmark_id;
            img.like = true;
            like.innerText = "❤️";
          });
        } else {
          fetch("https://www.pixiv.net/ajax/illusts/bookmarks/delete", {
            headers: {
              "content-type":
                "application/x-www-form-urlencoded; charset=utf-8",
              "x-csrf-token": localStorage.getItem("x-csrf-token"),
            },
            referrer: "https://www.pixiv.net/users/44921523/bookmarks/artworks",
            body: `bookmark_id=${illust.bookmark_id}`,
            method: "POST",
            credentials: "include",
          }).then((r) => {
            if (!r.ok) return;
            delete illust.bookmark_id;
            img.like = false;
            like.innerText = "🤍";
          });
        }
      };

      imgbox.appendChild(wrap);
    }
    loading = 0;
  }

  function loadNext() {
    if (loading) return;
    if (
      document.documentElement.scrollTop +
        document.documentElement.clientHeight <
      document.documentElement.scrollHeight -
        document.documentElement.clientHeight
    )
      return;
    loadimgs();
  }

  document.addEventListener("scroll", loadNext);

  loadimgs();
})();