• 微博超话签到Js脚本


     脚本连接

    1. // ==UserScript==
    2. // @name 微博超话自动签到
    3. // @description 用户登录后进入微博主页,获取超级话题并自动签到
    4. // @homepageURL https://github.com/Deuscx/WB_SIGN_EXT
    5. // @supportURL https://github.com/Deuscx/WB_SIGN_EXT/issues
    6. // @grant none
    7. // @version 2.0.3
    8. // @author deus
    9. // @match https://weibo.com/*
    10. // @match https://www.weibo.com/*
    11. // @require https://cdn.jsdelivr.net/combine/npm/@violentmonkey/dom@1,npm/@violentmonkey/ui@0.4
    12. // @require https://cdn.jsdelivr.net/npm/axios@0.21.0/dist/axios.min.js
    13. // @namespace https://deuscx.github.io/
    14. // ==/UserScript==
    15. (function() {
    16. "use strict";
    17. var css_248z = ".configContainer{display:flex;flex-direction:column;position:fixed;--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity));z-index:10;border-radius:.25rem;border-width:1px;--border-opacity:1;border-color:#cbd5e0;border-color:rgba(203,213,224,var(--border-opacity));padding:.75rem .5rem;max-width:190px;bottom:80px;right:0;transform:translateX(100%);transition-duration:.5s;transition-timing-function:cubic-bezier(.22,1,.36,1);transition-property:transform}.configContainer .cItem{font-size:.875rem;display:flex;justify-content:space-between;cursor:pointer}.configContainer .cItem .des{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}#TIMEOUT{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;width:60px}.configContainer .action{padding-top:.5rem;padding-bottom:.5rem;border-radius:.25rem;background-color:#fff;cursor:pointer;position:absolute;top:50%;left:0;transform:translate3d(-100%,-50%,0)}.configContainer .action:hover{color:#ccc}.active{transform:translateX(0)}";
    18. const tz_offset = (new Date).getTimezoneOffset() + 480;
    19. const ts_ms = Date.now;
    20. const isNewDay = ts => {
    21. if (!ts) return true;
    22. const t = new Date(ts);
    23. t.setMinutes(t.getMinutes() + tz_offset);
    24. t.setHours(0, 0, 0, 0);
    25. const d = new Date;
    26. d.setMinutes(t.getMinutes() + tz_offset);
    27. return d - t > 864e5;
    28. };
    29. const Store = function() {
    30. const set = function(key, data) {
    31. localStorage.setItem(key, JSON.stringify(data));
    32. };
    33. const get = function(key) {
    34. const v = localStorage.getItem(key);
    35. try {
    36. return JSON.parse(v);
    37. } catch (error) {
    38. return v;
    39. }
    40. };
    41. const remove = function(key) {
    42. localStorage.removeItem(key);
    43. };
    44. const has = function(key) {
    45. return Reflect.has(localStorage, key);
    46. };
    47. return {
    48. set: set,
    49. get: get,
    50. remove: remove,
    51. has: has
    52. };
    53. }();
    54. const getId = (i => () => i++)(0);
    55. const NAME = "WB";
    56. const SIGNED_ARR = `${NAME}_SIGNED_ARR`;
    57. const WB_CONFIG_CONSTANT = "WB_CONFIG";
    58. const TOAST_TYPE = {
    59. DEFAULT: "default",
    60. SUCCESS: "success",
    61. ERROR: "error",
    62. INFO: "info",
    63. WARNING: "warning"
    64. };
    65. let CONFIG = Store.get(WB_CONFIG_CONSTANT);
    66. function ConfigPanel() {
    67. const handleAutoSign = e => {
    68. const v = e.target.checked;
    69. const newConfig = Object.assign({}, CONFIG, {
    70. AUTO_SIGN: v
    71. });
    72. CONFIG = newConfig;
    73. Store.set(WB_CONFIG_CONSTANT, CONFIG);
    74. };
    75. const handleShowToast = e => {
    76. const v = e.target.checked;
    77. const newConfig = Object.assign({}, CONFIG, {
    78. SHOW_TOAST: v
    79. });
    80. CONFIG = newConfig;
    81. Store.set(WB_CONFIG_CONSTANT, CONFIG);
    82. };
    83. const handleTimeout = e => {
    84. const v = e.target.value;
    85. const newConfig = Object.assign({}, CONFIG, {
    86. TIMEOUT: v
    87. });
    88. CONFIG = newConfig;
    89. Store.set(WB_CONFIG_CONSTANT, CONFIG);
    90. };
    91. const toggleClassList = () => {
    92. document.querySelector(".configContainer").classList.toggle("active");
    93. };
    94. return VM.createElement(VM.Fragment, null, VM.createElement("div", {
    95. className: "configContainer"
    96. }, VM.createElement("label", {
    97. htmlFor: "AUTO_SIGN",
    98. className: "cItem"
    99. }, VM.createElement("span", {
    100. className: "des"
    101. }, "自动签到"), VM.createElement("input", {
    102. id: "AUTO_SIGN",
    103. type: "checkbox",
    104. onInput: handleAutoSign,
    105. checked: CONFIG.AUTO_SIGN
    106. })), VM.createElement("label", {
    107. htmlFor: "SHOW_TOAST",
    108. className: "cItem"
    109. }, VM.createElement("span", {
    110. className: "des"
    111. }, "是否展示气泡"), VM.createElement("input", {
    112. id: "SHOW_TOAST",
    113. type: "checkbox",
    114. onInput: handleShowToast,
    115. checked: CONFIG.SHOW_TOAST
    116. })), VM.createElement("label", {
    117. htmlFor: "TIMEOUT",
    118. className: "cItem"
    119. }, VM.createElement("span", {
    120. className: "des"
    121. }, "气泡展示时间"), VM.createElement("input", {
    122. id: "TIMEOUT",
    123. type: "number",
    124. onInput: handleTimeout,
    125. min: "0",
    126. value: parseInt(CONFIG.TIMEOUT, 10),
    127. placeholder: "单位为毫秒"
    128. })), VM.createElement("div", {
    129. className: "action",
    130. onClick: toggleClassList
    131. }, "收放")), VM.createElement("style", null, css_248z));
    132. }
    133. var css_248z$1 = ".msgContainer{position:fixed;background-color:initial;top:4rem;right:40px}@keyframes slide-in-right{0%{transform:translateX(1000px);opacity:0}to{transform:translateX(0);opacity:1}}@keyframes slide-out-right{0%{transform:translateX(0);opacity:1}to{transform:translateX(1000px);opacity:0}}.removing{animation:slide-out-right .5s cubic-bezier(.55,.085,.68,.53) both}.toastItem{background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity));border-width:1px;--border-opacity:1;border-color:#cbd5e0;border-color:rgba(203,213,224,var(--border-opacity));border-radius:.375rem;max-width:20rem;--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity));z-index:10;padding:1rem 1.5rem;cursor:pointer;--bg-opacity:1;background-color:#3182ce;background-color:rgba(49,130,206,var(--bg-opacity));opacity:.8;margin-bottom:.5rem;animation:slide-in-right .5s cubic-bezier(.25,.46,.45,.94) both}.toast-info{--bg-opacity:1;background-color:#63b3ed;background-color:rgba(99,179,237,var(--bg-opacity))}.toast-default{--bg-opacity:1;background-color:#3182ce;background-color:rgba(49,130,206,var(--bg-opacity))}.toast-success{--bg-opacity:1;background-color:#48bb78;background-color:rgba(72,187,120,var(--bg-opacity))}.toast-error{background-color:#ff5252}.toast-warning{--bg-opacity:1;background-color:#f6e05e;background-color:rgba(246,224,94,var(--bg-opacity))}";
    134. const MAX_TOAST = 8;
    135. let totalToast = 0;
    136. const innerToast = props => {
    137. const {content: content, type: type, timeout: timeout} = props;
    138. function remove() {
    139. const current = document.querySelector(`[data-tid='${props.id}']`);
    140. current.classList.add("removing");
    141. requestAnimationFrame((() => {
    142. current.parentNode.removeChild(current);
    143. totalToast--;
    144. }));
    145. }
    146. timeout && setTimeout((() => {
    147. remove();
    148. }), timeout);
    149. return VM.createElement(VM.Fragment, null, VM.createElement("div", {
    150. "data-tid": props.id,
    151. className: `toastItem toast-${type}`,
    152. onClick: remove
    153. }, content));
    154. };
    155. const ToastContainer = () => VM.createElement("div", {
    156. className: "msgContainer"
    157. }, VM.createElement("style", null, css_248z$1));
    158. const defaultOptions = {
    159. type: TOAST_TYPE.INFO,
    160. timeout: 5e3
    161. };
    162. const toastFactory = () => {
    163. const c = ToastContainer();
    164. const container = document.body.appendChild(c);
    165. const toast = (content, options) => {
    166. if (!Store.get(WB_CONFIG_CONSTANT).SHOW_TOAST) return;
    167. const newOptions = Object.assign({}, defaultOptions, {
    168. id: getId()
    169. }, options, {
    170. content: content
    171. });
    172. if (totalToast < MAX_TOAST) {
    173. totalToast++;
    174. container.appendChild(innerToast(newOptions));
    175. }
    176. };
    177. toast.success = (content, options) => toast(content, Object.assign({}, options, {
    178. type: TOAST_TYPE.SUCCESS
    179. }));
    180. toast.error = (content, options) => toast(content, Object.assign({}, options, {
    181. type: TOAST_TYPE.ERROR
    182. }));
    183. toast.info = (content, options) => toast(content, Object.assign({}, options, {
    184. type: TOAST_TYPE.INFO
    185. }));
    186. toast.warn = (content, options) => toast(content, Object.assign({}, options, {
    187. type: TOAST_TYPE.WARNING
    188. }));
    189. return toast;
    190. };
    191. const toast = toastFactory();
    192. const WB_DEFAULT_CONFIG = {
    193. AUTO_SIGN: true,
    194. SHOW_TOAST: true,
    195. TIMEOUT: 1e3
    196. };
    197. const instance = axios.create({
    198. baseURL: "https://weibo.com/",
    199. timeout: 1e3 * 5
    200. });
    201. instance.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
    202. instance.interceptors.request.use((config => config), (error => Promise.error(error)));
    203. instance.interceptors.response.use((res => 200 === res.status ? Promise.resolve(res) : Promise.reject(res)), (error => {
    204. const {response: response} = error;
    205. if (response) {
    206. console.log("发送请求失败", response);
    207. return Promise.reject(response);
    208. }
    209. if (!window.navigator.onLine) console.error("断网"); else return Promise.reject(error);
    210. }));
    211. class BaseFeature {
    212. constructor({name: name}) {
    213. this.launch = () => {};
    214. this.name = name;
    215. }
    216. get store() {
    217. const res = Store.get(this.name);
    218. if (res) return res;
    219. Store.set(this.name, void 0);
    220. return;
    221. }
    222. set store(v) {
    223. Store.set(this.name, v);
    224. }
    225. init() {
    226. return new Promise(((resolve, reject) => {
    227. try {
    228. this.launch();
    229. resolve(this);
    230. } catch (error) {
    231. console.log(`run ${this.name} error`);
    232. reject(error);
    233. }
    234. }));
    235. }
    236. }
    237. function isCheck() {
    238. return Store.get("isCheck") || false;
    239. }
    240. const lastCheck = Store.get("lastCheck");
    241. const signInterestAPI = id => instance({
    242. url: "p/aj/general/button",
    243. params: {
    244. ajwvr: 6,
    245. api: "http://i.huati.weibo.com/aj/super/checkin",
    246. texta: encodeURI("签到"),
    247. textb: encodeURI("已签到"),
    248. status: 0,
    249. id: id,
    250. __rnd: (new Date).getTime()
    251. }
    252. });
    253. let SignedArr = Store.get(SIGNED_ARR) || [];
    254. const signInterest = ({id: id, name: name}) => new Promise(((resolve, reject) => {
    255. signInterestAPI(id).then((response => {
    256. const {data: data} = response;
    257. if ("100000" === data.code) {
    258. window.toast.success(`[${name}签到成功]${data.msg} ---${data.data.alert_title}`);
    259. Store.set("lastCheck", ts_ms());
    260. SignedArr.push(name);
    261. SignedArr = Array.from(new Set(SignedArr));
    262. Store.set(SIGNED_ARR, SignedArr);
    263. } else {
    264. window.toast.warn(`[${name}超话签到]${data.msg}`);
    265. if (382004 !== data.code) reject("error"); else {
    266. Store.set("lastCheck", ts_ms());
    267. SignedArr.push(name);
    268. SignedArr = Array.from(new Set(SignedArr));
    269. Store.set(SIGNED_ARR, SignedArr);
    270. }
    271. }
    272. resolve();
    273. }), (err => {
    274. reject(err);
    275. window.toast.error(`[${name}超话签到]签到失败,请检查网络`);
    276. }));
    277. }));
    278. function getInterestNameAId(page = 1) {
    279. return new Promise(((resolve, reject) => {
    280. instance({
    281. url: `ajax/profile/topicContent?tabid=231093_-_chaohua&page=${page}`
    282. }).then((response => {
    283. const {data: {data: data, ok: ok}} = response;
    284. if (1 !== ok) reject({
    285. err: "获取关注超话失败",
    286. data: data
    287. });
    288. const list = data.list;
    289. const total_number = data.total_number;
    290. function extractId(oid) {
    291. return oid.slice(5);
    292. }
    293. const simList = list.map((({oid: oid, topic_name: topic_name}) => ({
    294. id: extractId(oid),
    295. name: topic_name
    296. })));
    297. if (0 !== total_number) getInterestNameAId(page + 1).then((li => {
    298. resolve(simList.concat(li));
    299. })); else resolve(simList);
    300. }), (err => {
    301. console.error(`[${NAME}]`, err);
    302. reject("获取hash失败");
    303. }));
    304. }));
    305. }
    306. class Interest extends BaseFeature {
    307. constructor() {
    308. super({
    309. name: WB_CONFIG_CONSTANT
    310. });
    311. this.launch = async () => {
    312. const config = super.store;
    313. if (!config.AUTO_SIGN) return;
    314. if (isCheck() && !isNewDay(lastCheck)) {
    315. window.toast.info("今日已签到");
    316. return;
    317. }
    318. if (isNewDay(lastCheck)) {
    319. Store.remove(SIGNED_ARR);
    320. Store.set("isCheck", false);
    321. }
    322. let idNameList = await getInterestNameAId();
    323. const signedArr = Store.get(SIGNED_ARR);
    324. if (signedArr && signedArr.length) idNameList = idNameList.filter((v => !signedArr.includes(v.name)));
    325. Promise.all(idNameList.map((({name: name, id: id}) => signInterest({
    326. id: id,
    327. name: name
    328. })))).then((() => {
    329. Store.set("isCheck", true);
    330. }));
    331. };
    332. }
    333. run() {
    334. this.init().then((self => {}));
    335. }
    336. }
    337. var Interest$1 = new Interest;
    338. function initConfig() {
    339. if (!Store.get(WB_CONFIG_CONSTANT)) Store.set(WB_CONFIG_CONSTANT, WB_DEFAULT_CONFIG);
    340. }
    341. function initDOM() {
    342. return new Promise(((resolve, reject) => {
    343. try {
    344. const mainI = ConfigPanel();
    345. document.body.appendChild(mainI);
    346. } catch (error) {
    347. throw new Error("初始化DOM失败");
    348. }
    349. }));
    350. }
    351. function BaseInit() {
    352. initConfig();
    353. window.toast = toast;
    354. }
    355. function OtherInit() {
    356. initDOM();
    357. }
    358. function main() {
    359. BaseInit();
    360. OtherInit();
    361. Interest$1.run();
    362. }
    363. main();
    364. })();

  • 相关阅读:
    Linux (Ubuntu)文件系统结构(入门必看)
    golang编译go build -ldflags "-s -w"的 解释
    Kotlin 协程之取消与异常处理探索之旅(下)
    [附源码]Python计算机毕业设计Django社区住户信息管理系统
    Python的异常处理
    电脑使用技巧
    DAO 的使用原则和适用范围
    Mysql Order单条记录出现在两页
    Python异常
    PWmat案例赏析:计算精度高、速度快的第一性原理计算,研究表面终端结构对NV色心影响
  • 原文地址:https://blog.csdn.net/gs1we1/article/details/133036977