Swag.live Downloader

This is a video downloader for theswag.live website.

  1. // ==UserScript==
  2. // @name Swag.live Downloader
  3. // @name:ZH-CN Swag 下载器
  4. // @name:zh-TW Swag 下載器
  5. // @description This is a video downloader for theswag.live website.
  6. // @description:zh-TW 下载已经在 swag 上购买的视频(Token 登錄專用)
  7. // @description:zh-CN 下载已经在 swag 上购买的视频(Token 专用)
  8. // @namespace https://swag.heyra.uk/
  9. // @version 1.1
  10. // @author Swager
  11. // @match *://*swag.live/archive?*
  12. // @grant GM_addStyle
  13. // @license MIT
  14. // @icon https://swag.heyra.uk/favicon.ico
  15. // ==/UserScript==
  16.  
  17. (function () {
  18. 'use strict';
  19.  
  20. // Create floating button
  21. const floatingBtn = document.createElement('div');
  22. floatingBtn.id = 'floating-icon';
  23. floatingBtn.innerHTML = `<img src="https://swag.heyra.uk/favicon.ico" alt="icon" style="width:100%;height:100%;">`;
  24. document.body.appendChild(floatingBtn);
  25.  
  26. // Create dialog
  27. const dialog = document.createElement('div');
  28. dialog.id = 'custom-dialog';
  29. dialog.innerHTML = `
  30. <div id="dialog-content">
  31. <p id="dialog-message">Dialog content here. Replace with your logic.</p>
  32. <div id="dialog-actions">
  33. <button id="cancel-btn">取消</button>
  34. <button id="confirm-btn">复制并下载</button>
  35. </div>
  36. </div>
  37. `;
  38. document.body.appendChild(dialog);
  39.  
  40. // Add styles
  41. GM_addStyle(`
  42. #floating-icon {
  43. position: fixed;
  44. top: 50%;
  45. right: 20px;
  46. transform: translateY(-50%);
  47. width: 50px;
  48. height: 50px;
  49. background: #007BFF;
  50. border-radius: 50%;
  51. display: flex;
  52. align-items: center;
  53. justify-content: center;
  54. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  55. cursor: pointer;
  56. transition: transform 0.3s ease;
  57. z-index: 1000;
  58. border: 4px solid rgb(0, 226, 203);
  59. }
  60. #floating-icon:hover {
  61. transform: translateY(-50%) scale(1.1);
  62. }
  63. #custom-dialog {
  64. position: fixed;
  65. top: 50%;
  66. left: 50%;
  67. transform: translate(-50%, -50%) scale(0);
  68. width: 300px;
  69. padding: 20px;
  70. background: white;
  71. box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  72. border-radius: 10px;
  73. z-index: 1001;
  74. opacity: 0;
  75. transition: transform 0.3s ease, opacity 0.3s ease;
  76. }
  77. #custom-dialog.active {
  78. transform: translate(-50%, -50%) scale(1);
  79. opacity: 1;
  80. }
  81. #dialog-content {
  82. color: rgba(0, 0, 0, 0.6);
  83. text-align: center;
  84. }
  85. #dialog-actions {
  86. display: flex;
  87. justify-content: space-between;
  88. margin-top: 20px;
  89. }
  90. #dialog-actions button {
  91. padding: 10px 20px;
  92. border: none;
  93. border-radius: 5px;
  94. cursor: pointer;
  95. transition: background 0.2s ease;
  96. }
  97. #cancel-btn {
  98. color: white;
  99. background: rgb(220, 38, 38);
  100. }
  101. #cancel-btn:hover {
  102. color: white;
  103. background: rgb(220, 38, 38);
  104. }
  105. #confirm-btn {
  106. background: rgb(0, 226, 203);
  107. color: white;
  108. }
  109. #confirm-btn:hover {
  110. background: rgb(0, 226, 203);
  111. }
  112. `);
  113.  
  114. // Toggle dialog visibility
  115. function toggleDialog(show) {
  116. if (show) {
  117. dialog.classList.add('active');
  118. } else {
  119. dialog.classList.remove('active');
  120. }
  121. }
  122.  
  123. // Event listeners
  124. floatingBtn.addEventListener('click', () => { toggleDialog(true); dialogLogic() });
  125. document.getElementById('cancel-btn').addEventListener('click', () => toggleDialog(false));
  126. document.getElementById('confirm-btn').addEventListener('click', () => confirmAction());
  127.  
  128. function copyToClipboard(text) {
  129. if (navigator.clipboard && window.isSecureContext) {
  130. // 使用现代异步 Clipboard API
  131. navigator.clipboard.writeText(text).then(() => {
  132. console.log('Text copied to clipboard:', text);
  133. }).catch(err => {
  134. console.error('Failed to copy text to clipboard:', err);
  135. });
  136. } else {
  137. // 退回到旧方法,使用 document.execCommand
  138. const textArea = document.createElement('textarea');
  139. textArea.value = text;
  140. textArea.style.position = 'fixed'; // 避免滚动条影响
  141. textArea.style.opacity = '0'; // 隐藏元素
  142. document.body.appendChild(textArea);
  143. textArea.select();
  144. try {
  145. const successful = document.execCommand('copy');
  146. if (successful) {
  147. console.log('Text copied to clipboard:', text);
  148. } else {
  149. console.error('Failed to copy text to clipboard using execCommand.');
  150. }
  151. } catch (err) {
  152. console.error('Failed to copy text to clipboard:', err);
  153. } finally {
  154. document.body.removeChild(textArea);
  155. }
  156. }
  157. }
  158.  
  159. // Placeholder for confirm logic
  160. function confirmAction() {
  161. toggleDialog(false);
  162. window.open("https://swag.heyra.uk/", "_blank")
  163. }
  164.  
  165. // Placeholder for dialog logic
  166. function dialogLogic() {
  167. var db
  168. var request = indexedDB.open('localforage', 3)
  169. request.onsuccess = function () {
  170. db = request.result
  171. var tx = db.transaction('keyvaluepairs', 'readonly')
  172. var store = tx.objectStore('keyvaluepairs')
  173. var _request = store.getAll('_refreshToken')
  174. _request.onsuccess = function () {
  175. var token = _request.result.toString()
  176. copyToClipboard(token)
  177. document.getElementById('dialog-message').innerText = "Token 获取成功";
  178. }
  179. }
  180. }
  181. })();