Guest User

Untitled

a guest
Aug 22nd, 2025
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.76 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Avatar Preview - bottom left (last message avatar, auto-update, ignore persona)
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.0
  5. // @description Always shows the avatar from the LAST chat message (ignores persona), updates instantly
  6. // @match http://localhost:3000/*
  7. // @grant none
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. 'use strict';
  12.  
  13. let preview = null;
  14. let lastSrc = null;
  15.  
  16. // Pega o avatar da última mensagem no chat
  17. function getLastMessageAvatar() {
  18. // pega todas as mensagens
  19. let messages = document.querySelectorAll('li[id^="message-"]');
  20. if (messages.length === 0) return null;
  21.  
  22. // última mensagem
  23. let lastMsg = messages[messages.length - 1];
  24.  
  25. // procura avatar dentro dela
  26. let avatarImg = lastMsg.querySelector('img[data-scope="avatar"][data-part="image"][data-state="visible"]');
  27. if (!avatarImg) return null;
  28.  
  29. // ignora se for persona
  30. if (avatarImg.src.includes("/personas/")) return null;
  31.  
  32. return avatarImg;
  33. }
  34.  
  35. function updateAvatar() {
  36. let avatarImg = getLastMessageAvatar();
  37. if (!avatarImg) return;
  38.  
  39. if (!preview) {
  40. preview = document.createElement("img");
  41. preview.id = "tm-avatar-preview";
  42. Object.assign(preview.style, {
  43. position: "fixed",
  44. bottom: "10px",
  45. left: "10px",
  46. width: "470px",
  47. height: "auto",
  48. border: "none",
  49. borderRadius: "15px",
  50. zIndex: "99999",
  51. background: "transparent",
  52. padding: "0",
  53. boxShadow: "none",
  54. display: "none" // inicia minimizado
  55. });
  56. document.body.appendChild(preview);
  57. createButtons(preview);
  58. }
  59.  
  60. // Atualiza instantaneamente se mudou
  61. if (avatarImg.src && avatarImg.src !== lastSrc) {
  62. lastSrc = avatarImg.src;
  63. preview.src = lastSrc;
  64. }
  65. }
  66.  
  67. function createButtons(preview) {
  68. if (document.getElementById("tm-avatar-buttons")) return;
  69.  
  70. const btnContainer = document.createElement("div");
  71. btnContainer.id = "tm-avatar-buttons";
  72. Object.assign(btnContainer.style, {
  73. position: "fixed",
  74. bottom: "10px",
  75. left: "10px",
  76. zIndex: "99999",
  77. display: "flex",
  78. gap: "5px"
  79. });
  80.  
  81. const btnShow = document.createElement("button");
  82. btnShow.textContent = "Show";
  83. Object.assign(btnShow.style, {
  84. padding: "5px 10px",
  85. cursor: "pointer"
  86. });
  87. btnShow.addEventListener("click", () => {
  88. preview.style.display = "block";
  89. });
  90.  
  91. const btnHide = document.createElement("button");
  92. btnHide.textContent = "Hide";
  93. Object.assign(btnHide.style, {
  94. padding: "5px 10px",
  95. cursor: "pointer"
  96. });
  97. btnHide.addEventListener("click", () => {
  98. preview.style.display = "none";
  99. });
  100.  
  101. btnContainer.appendChild(btnShow);
  102. btnContainer.appendChild(btnHide);
  103. document.body.appendChild(btnContainer);
  104. }
  105.  
  106. // Atualiza ao carregar a página
  107. window.addEventListener('load', updateAvatar);
  108.  
  109. // Observa mudanças no DOM (novas mensagens, mudanças de imagem, etc.)
  110. const observer = new MutationObserver(() => {
  111. updateAvatar();
  112. });
  113. observer.observe(document.body, {
  114. childList: true,
  115. subtree: true,
  116. attributes: true,
  117. attributeFilter: ["src", "data-state"]
  118. });
  119.  
  120. })();
Advertisement
Add Comment
Please, Sign In to add comment