妖火站内信提醒

自动获取新私信,并在页面内通过Toast弹窗提示用户

  1. // ==UserScript==
  2. // @name 妖火站内信提醒
  3. // @namespace https://www.yaohuo.me/bbs/userinfo.aspx?touserid=20740
  4. // @version 1.0.7
  5. // @description 自动获取新私信,并在页面内通过Toast弹窗提示用户
  6. // @author SiXi
  7. // @match *://www.yaohuo.me/*
  8. // @match *://yaohuo.me/*
  9. // @icon https://yaohuo.me/css/favicon.ico
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @run-at document-start
  14. // @license MIT
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. // 配置项
  21. const CHECK_INTERVAL = 15000; // 30秒检查一次
  22. const MESSAGE_URL = 'https://www.yaohuo.me/bbs/messagelist.aspx';
  23.  
  24. // 本地存储的键
  25. const MESSAGES_STORAGE_KEY = 'yaohuoMessages';
  26.  
  27. // 创建Toast提醒
  28. function showToast(messages) {
  29. // 先移除旧的toast
  30. const oldToasts = document.querySelectorAll('.toast');
  31. oldToasts.forEach(toast => toast.remove());
  32.  
  33. // 创建新的toast容器
  34. const toastContainer = document.createElement('div');
  35. toastContainer.className = 'toast-container';
  36. document.body.appendChild(toastContainer);
  37.  
  38. // 按顺序添加每条消息的toast
  39. messages.forEach((msg, index) => {
  40. const toast = document.createElement('div');
  41. toast.className = 'toast';
  42. toast.innerHTML = `
  43. 新私信:${msg.from} <small>${msg.date}</small><br>
  44. 内 容:<a href="https://www.yaohuo.me${msg.url}" target="_blank">${msg.text}</a>
  45. `;
  46. toastContainer.appendChild(toast);
  47.  
  48. // 设置toast动画
  49. setTimeout(() => {
  50. toast.classList.add('show');
  51. }, 100);
  52.  
  53. // 自动关闭Toast
  54. setTimeout(() => {
  55. toast.classList.remove('show');
  56. setTimeout(() => {
  57. toast.remove();
  58. }, 300); // 延时删除Toast元素
  59. }, 8000);
  60. });
  61. }
  62.  
  63. // 添加CSS样式
  64. function addToastStyles() {
  65. const style = document.createElement('style');
  66. style.innerHTML = `
  67. .toast-container {
  68. position: fixed;
  69. bottom: 20px;
  70. right: 20px;
  71. z-index: 9999;
  72. display: flex;
  73. flex-direction: column-reverse; /* 从下往上排列 */
  74. gap: 10px; /* 每条toast之间的间距 */
  75. }
  76.  
  77. .toast {
  78. background-color: #333;
  79. color: white;
  80. padding: 10px 20px;
  81. border-radius: 5px;
  82. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  83. opacity: 0;
  84. transition: opacity 0.3s, transform 0.3s;
  85. transform: translateY(10px);
  86. }
  87.  
  88. .toast.show {
  89. opacity: 1;
  90. transform: translateY(0);
  91. }
  92.  
  93. .toast a {
  94. color: #4CAF50;
  95. text-decoration: underline;
  96. }
  97. `;
  98. document.head.appendChild(style);
  99. }
  100.  
  101. // 本地存储获取和设置
  102. function saveMessages(messages) {
  103. GM_setValue(MESSAGES_STORAGE_KEY, messages);
  104. }
  105.  
  106. function getMessages() {
  107. return GM_getValue(MESSAGES_STORAGE_KEY, []);
  108. }
  109.  
  110. // 获取站内信
  111. function fetchMessages() {
  112. console.log('正在请求站内信...');
  113. GM_xmlhttpRequest({
  114. method: 'GET',
  115. url: MESSAGE_URL,
  116. onload: function(response) {
  117. console.log('站内信请求成功');
  118. const data = response.responseText;
  119. const parser = new DOMParser();
  120. const doc = parser.parseFromString(data, 'text/html');
  121. const messageElements = doc.querySelectorAll('.listmms.line1, .listmms.line2');
  122. const newMessages = [];
  123.  
  124. messageElements.forEach(element => {
  125. // 检查是否有新站内信标志
  126. const newIcon = element.querySelector('img[src="/NetImages/new.gif"]');
  127. if (newIcon) {
  128. // 提取信息
  129. const linkElement = element.querySelector('a');
  130. const fromElement = element.querySelector('span.laizi');
  131. const dateElement = element.textContent.match(/\d{4}\/\d{1,2}\/\d{1,2} \d{1,2}:\d{2}/);
  132.  
  133. if (linkElement && fromElement && dateElement) {
  134. const url = linkElement.getAttribute('href');
  135. const text = linkElement.textContent.trim();
  136. const from = fromElement.nextSibling.textContent.trim();
  137. const date = dateElement[0];
  138.  
  139. newMessages.push({ url, text, from, date });
  140. }
  141. }
  142. });
  143.  
  144. // 比较新站内信与本地存储的站内信
  145. const oldMessages = getMessages();
  146. const uniqueNewMessages = newMessages.filter(msg => !oldMessages.some(old => old.url === msg.url));
  147.  
  148. if (uniqueNewMessages.length > 0) {
  149. console.log('发现新站内信:', uniqueNewMessages);
  150. // 保存新数据
  151. saveMessages([...oldMessages, ...uniqueNewMessages]);
  152.  
  153. // 显示所有新消息的toast
  154. showToast(uniqueNewMessages);
  155. } else {
  156. console.log('没有新站内信');
  157. }
  158. },
  159. onerror: function(err) {
  160. console.error('获取站内信失败:', err);
  161. showToast([{ from: '系统', date: '', url: '', text: '获取站内信失败' }]);
  162. }
  163. });
  164. }
  165.  
  166. // 设置定时器
  167. setInterval(() => {
  168. fetchMessages();
  169. }, CHECK_INTERVAL);
  170.  
  171. // 首次加载时立即获取一次
  172. addToastStyles();
  173. fetchMessages();
  174. })();

QingJ © 2025

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