Bookmark Twitter Users (Discrete Follow)

6/2/2024, 12:07:28 AM

目前为 2024-06-02 提交的版本。查看 最新版本

// ==UserScript==
// @name        Bookmark Twitter Users (Discrete Follow)
// @namespace   Violentmonkey Scripts
// @match       https://x.com/*
// @grant       none
// @version     1.0
// @author      -
// @description 6/2/2024, 12:07:28 AM
// @license     MIT
// ==/UserScript==

// Add FontAwesome library
var faLink = document.createElement('link');
faLink.rel = 'stylesheet';
faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css';
document.head.appendChild(faLink);

// modal vars
const modal = document.createElement('div');
modal.className = 'bookmarkModal';
const modalContent = document.createElement('div');
modalContent.classList.add('bookmarkContent');
const closeModal = document.createElement('button');
closeModal.classList.add('r-37j5jr', 'closeBookmarkModal');
const bookmarkUl = document.createElement('ul');

// Execute addElement function at window load
window.onload = function() {

    const bookmarkStyle = document.createElement('style');

    // Define your CSS rules
    const css = `
      .bookmarkHover:hover {
        transform: scale(1.05);
        filter: brightness(1.5);
      }
      .bookmarkHover:active {
        transform: scale(1);
      }
    `;

    // Set the CSS rules to the style element
    bookmarkStyle.innerHTML = css;

    // Append the style element to the document body
    document.body.appendChild(bookmarkStyle);

  // Load bookmarks from local storage
  loadBookmarks();

  // Use a setInterval to check if the sidebar is available
  const checkSidebarInterval = setInterval(() => {
    const sidebarNav = document.querySelector('nav[aria-label="Primary"]');
    if (sidebarNav) {
      clearInterval(checkSidebarInterval); // Stop checking once the element is found
      addElement(sidebarNav); // Call the addElement function with the sidebarNav element
    }
  }, 100); // Check every 100ms

  // add bookmark option to user actions
  // Use a setInterval to check if the user actions is available
  const checkUserActionsInterval = setInterval(() => {
    const userActionBtns = document.querySelector('div[class="css-175oi2r r-obd0qt r-18u37iz r-1w6e6rj r-1h0z5md r-dnmrzs"]');
    userActionBtns.style.cssText = `align-items: center;`;
    if (userActionBtns) {
      clearInterval(checkUserActionsInterval); // Stop checking once the element is found
      addBookmarkBtn(userActionBtns); // Call the addElement function with the sidebarNav element
    }
  }, 100); // Check every 100ms
};

// Function to load bookmarks from local storage
function loadBookmarks() {
  const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
  bookmarkUl.innerHTML = ''; // Clear the existing bookmarks

  bookmarks.forEach((bookmark, index) => {
    const newBookmark = document.createElement('li');
    newBookmark.innerHTML = `
      <p>
        <a href="${bookmark.link}">${bookmark.userName}</a>${bookmark.notes ? ` -   ${bookmark.notes}` : ''}
        <span class="edit-notes bookmarkHover" style="color: yellow; margin-left: 10px;" data-bookmark-index="${index}">[ Edit  | </span>
        <span class="delete-bookmark bookmarkHover" style="color: red;" data-bookmark-index="${index}">  Delete ]</span>
      </p>
    `;
    bookmarkUl.appendChild(newBookmark);
  });
}

// Add event listener for edit notes and delete bookmark
bookmarkUl.addEventListener('click', function(event) {
  const target = event.target;
  if (target.classList.contains('edit-notes')) {
    editNotes(event);
  } else if (target.classList.contains('delete-bookmark')) {
    deleteBookmark(event);
  }
});


// Function to edit notes
function editNotes(event) {
  const bookmarkIndex = event.target.dataset.bookmarkIndex;
  const bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
  const newNotes = prompt("Edit notes:", bookmarks[bookmarkIndex].notes);

  if (newNotes !== null) {
    bookmarks[bookmarkIndex].notes = newNotes;
    localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
    loadBookmarks(); // Reload bookmarks to update the UI
  }
}

// Function to delete bookmark
function deleteBookmark(event) {
  const bookmarkIndex = event.target.dataset.bookmarkIndex;
  const bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
  bookmarks.splice(bookmarkIndex, 1);
  localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
  loadBookmarks(); // Reload bookmarks to update the UI
}

// Function to add bookmark button on profiles
function addBookmarkBtn(userActionBtns) {
  const bookmarkUserBtn = document.createElement('div');
  bookmarkUserBtn.innerHTML = `
    <div class="css-175oi2r">
      <svg viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-dnmrzs r-bnwqim r-lrvibr r-m6rgpd r-1nao33i r-lwhw9o r-cnnz9e">
        <g><path d="M4 4.5C4 3.12 5.119 2 6.5 2h11C18.881 2 20 3.12 20 4.5v18.44l-8-5.71-8 5.71V4.5zM6.5 4c-.276 0-.5.22-.5.5v14.56l6-4.29 6 4.29V4.5c0-.28-.224-.5-.5-.5h-11z"></path></g>
      </svg>
    </div>
  `;
  bookmarkUserBtn.style.cssText = `
    background-color: transparent;
    border-radius: 100%;
    font-family: TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  `;
  userActionBtns.appendChild(bookmarkUserBtn);

  bookmarkUserBtn.onclick = () => {
    addUserToBookmarks();
  };
}

function addUserToBookmarks() {
  let newBookmarkLink = window.location.href;
  let bookmarkUserName = document.querySelector('div[data-testid="UserName"] span[class="css-1jxf684 r-bcqeeo r-1ttztb7 r-qvutc0 r-poiln3"]').textContent;
  console.log('NEW BOOKMARK: ' + newBookmarkLink);
  populateBookmarks(newBookmarkLink, bookmarkUserName);
}

function populateBookmarks(link, bookmarkUserName) {
  let bookmarkModal = document.querySelector('.bookmarkContent');
  let notes = prompt("Add additional notes: ");
  if (notes !== null && notes !== '') {
    notes = notes;
  } else {
    notes = '';
  }

  const newBookmark = {
    link,
    userName: bookmarkUserName,
    notes
  };

  const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || [];
  bookmarks.push(newBookmark);
  localStorage.setItem('bookmarks', JSON.stringify(bookmarks));

  loadBookmarks(); // Reload bookmarks to update the UI
}

// Function to add the button to the sidebar
function addElement(sidebarNav) {
  console.log('NAV ' + sidebarNav);
  const bookmarkUserBtn = document.createElement('a');
  bookmarkUserBtn.classList.add('css-175oi2r', 'r-6koalj', 'r-eqz5dr', 'r-16y2uox', 'r-1habvwh', 'r-cnw61z', 'r-13qz1uu', 'r-1ny4l3l', 'r-1loqt21', '.r-1hdo0pc', '.r-o7ynqc');
  bookmarkUserBtn.innerHTML = `
  <div class="css-175oi2r r-sdzlij r-dnmrzs r-1awozwy r-18u37iz r-1777fci r-xyw6el r-o7ynqc r-6416eg">
    <div class="css-175oi2r">
      <svg viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-dnmrzs r-bnwqim r-lrvibr r-m6rgpd r-1nao33i r-lwhw9o r-cnnz9e">
        <g><path d="M4 4.5C4 3.12 5.119 2 6.5 2h11C18.881 2 20 3.12 20 4.5v18.44l-8-5.71-8 5.71V4.5zM6.5 4c-.276 0-.5.22-.5.5v14.56l6-4.29 6 4.29V4.5c0-.28-.224-.5-.5-.5h-11z"></path></g>
      </svg>
    </div>
    <div dir="ltr" class="css-146c3p1 r-dnmrzs r-1udh08x r-3s2u2q r-bcqeeo r-1ttztb7 r-qvutc0 r-37j5jr r-adyw6z r-135wba7 r-16dba41 r-dlybji r-nazi8o" style="text-overflow: unset; color: rgb(231, 233, 234);">
      <span class="css-1jxf684 r-bcqeeo r-1ttztb7 r-qvutc0 r-poiln3" style="text-overflow: unset;">Bookmarked Users</span>
    </div>
  </div>
  `;

  // Get the 4th to last child and insert the button after it
  const children = sidebarNav.children;
  const fourthToLastChild = children[children.length - 5];

  if (fourthToLastChild) {
    fourthToLastChild.insertAdjacentElement('afterend', bookmarkUserBtn);
  } else {
    // If there are less than 4 children, just append the button to the sidebar
    sidebarNav.appendChild(bookmarkUserBtn);
  }

  bookmarkUserBtn.onclick = () => {
    openModal();
  };
}

function openModal() {
  // create the modal
  modal.style.cssText = `
    font: inherit;
    display: flex;
    justify-content: center;
    align-items: center;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 100000;
  `;

  modalContent.style.cssText = `
    font: inherit;
    position: relative;
    width: 40%;
    height: 40%;
    background-color: #161616;
    border: 1px solid rgba(255,255,255,0.5);
    border-radius: 3px;
    overflow-y: auto;
    padding: 20px;
    -webkit-box-shadow: 0px 0px 92px 50px rgba(0,0,0,0.55);
    -moz-box-shadow: 0px 0px 92px 50px rgba(0,0,0,0.55);
    box-shadow: 0px 0px 92px 50px rgba(0,0,0,0.55);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.2) rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-content: center;
    font-family: TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    place-content: start !important;
  `;

  closeModal.textContent = 'Close';
  closeModal.style.cssText = `
    font: inherit;
    position: absolute;
    top: 10px;
    right: 10px;
    background-color: #161616;
    color: white;
    border: rgba(255,255,255,0.5) 1px solid;
    border-radius: 3px;
    z-index: 1000000;
    font-family: TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  `;

  bookmarkUl.style.cssText = `
    display: flex;
    flex-direction: column;
    gap: 10px;
  `;

  closeModal.onclick = () => {
    closeModalFunc();
  };

  modalContent.appendChild(closeModal);
  modalContent.appendChild(bookmarkUl);
  modal.appendChild(modalContent);
  document.body.appendChild(modal);
}

function closeModalFunc() {
  modal.style.display = 'none';
  modalContent.innerHTML = ''; // Clear the modal content
}

// Close modal when clicking outside the inner modalContent
modal.onclick = (event) => {
  if (event.target === modal) {
    closeModalFunc();
  }
};

// Prevent modal from closing when clicking inside the modalContent
modalContent.onclick = (event) => {
  event.stopPropagation();
};

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址