// ==UserScript==
// @name Bilibili哔哩哔哩互相关注检测脚本
// @namespace http://blog.853lab.com/
// @version 0.9
// @description 检测互关的人
// @author Sonic853
// @include https://space.bilibili.com/*
// @require https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// @run-at document-end
// @license MIT License
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// @grant GM_getResourceText
// ==/UserScript==
//
// 律师函收到之日,即是我死期到来之时。
// 学写代码学到现在也不过是一枚棋子,随用随弃。
// :)
//
(function () {
'use strict'
const DEV_Log = Boolean(localStorage.getItem("Dev-853"))
const localItem = "Lab8A"
const NAME = "互关检测"
const Console_log = function (...text) {
let d = new Date().toLocaleTimeString()
console.log(`[${NAME}][${d}]: `, ...text)
}
const Console_Devlog = function (...text) {
let d = new Date().toLocaleTimeString()
DEV_Log && (console.log(`[${NAME}][${d}]: `, ...text))
}
const Console_error = function (...text) {
let d = new Date().toLocaleTimeString()
console.error(`[${NAME}][${d}]: `, ...text)
}
const snooze = ms => new Promise(resolve => setTimeout(resolve, ms))
const RList = new class {
time = 500
#list = -1
async Push() {
this.#list++
await snooze(this.#list * this.time)
Promise.resolve().finally(() => {
setTimeout(() => { this.#list-- }, (this.#list + 1) * this.time)
})
}
}
if (typeof GM_xmlhttpRequest === 'undefined' && typeof GM_registerMenuCommand === 'undefined' && typeof GM_setValue === 'undefined' && typeof GM_getValue === 'undefined' && typeof GM_addStyle === 'undefined') {
Console_error("GM is no Ready.")
} else {
Console_log("GM is Ready.")
}
/**
*
* @param {string} url
* @param {string} method
* @param {Object.<string, any>} headers
* @param {string} responseType
* @param {*} successHandler
* @param {*} errorHandler
* @returns
*/
let HTTPsend = function (url, method, headers, responseType, successHandler, errorHandler) {
Console_Devlog(url)
if (typeof GM_xmlhttpRequest != 'undefined') {
return new Promise((rl, rj) => {
try {
GM_xmlhttpRequest({
method,
url,
headers,
responseType,
onerror: function (response) {
Console_Devlog(response.status)
errorHandler && errorHandler(response.status)
rj(response.status)
},
onload: function (response) {
let status
if (response.readyState == 4) { // `DONE`
status = response.status
if (status == 200) {
Console_Devlog(response.response)
successHandler && successHandler(response.response)
rl(response.response)
} else {
Console_Devlog(status)
errorHandler && errorHandler(status)
rj(status)
}
}
},
})
} catch (error) {
rj(error)
}
})
} else {
return new Promise((rl, rj) => {
try {
let xhr = new XMLHttpRequest()
xhr.open(method, url, true)
xhr.withCredentials = true
xhr.responseType = responseType
xhr.onreadystatechange = function () {
let status
if (xhr.readyState == 4) { // `DONE`
status = xhr.status
if (status == 200) {
Console_log(xhr.response)
successHandler && successHandler(xhr.response)
rl(xhr.response)
} else {
Console_log(status)
errorHandler && errorHandler(status)
rj(status)
}
}
}
xhr.send()
} catch (error) {
rj(error)
}
})
}
}
let BLab8A = class {
// attribute 为0表示只关注了我,1表示我悄悄关注了他,2表示只有我关注了他,6表示互相关注
// 其中悄悄关注无法知道他是否关注我,所以只有我关注了他才会是2,互相关注则是6
/**
* @type {Object.<string, {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[]>} data
*/
data
constructor() {
this.data = this.load()
}
load() {
Console_log("正在加载数据")
const defaultData = "{\"uid\":1,\"follow\":[],\"follow2\":[],\"unfollowed\":[],\"unfollowed2\":[],\"fans\":[],\"unfans\":[],\"whispers\":[],\"unwhispers\":[],\"whispersfollow\":[]}"
if (typeof GM_getValue !== 'undefined') {
let gdata = GM_getValue(localItem, JSON.parse(defaultData))
return gdata
} else {
let ldata = JSON.parse(localStorage.getItem(localItem) === null ? defaultData : localStorage.getItem(localItem))
return ldata
}
}
save(d) {
Console_log("正在保存数据")
d === undefined ? (d = this.data) : (this.data = d)
typeof GM_getValue != 'undefined' ? GM_setValue(localItem, d) : localStorage.setItem(localItem, JSON.stringify(d))
return this
}
}
let bLab8A = new BLab8A()
const BilibiliFollowChecker = new class {
/**
* @type {number}
*/
vmid = typeof bLab8A.data.uid == 'string' ? parseInt(bLab8A.data.uid) : bLab8A.data.uid
/**
* @type {number}
*/
ps = 20
/**
* @type {number}
*/
pn = 1
/**
* @type {number}
*/
total = 0
/**
* @type {number}
*/
fansTotal = 0
/**
* @type {number}
*/
fansMaxpn = 50
get stat() {
return `https://api.bilibili.com/x/relation/stat?vmid=${this.vmid}&jsonp=jsonp`
}
get followUrl() {
return `https://api.bilibili.com/x/relation/followings?vmid=${this.vmid}&pn=${this.pn}&ps=${this.ps}&order=desc&order_type=`
}
get followReferer() {
return `https://space.bilibili.com/${this.vmid}/fans/follow`
}
get fansUrl() {
return `https://api.bilibili.com/x/relation/followers?vmid=${this.vmid}&pn=${this.pn}&ps=${this.ps}&order=desc&order_type=attention`
}
get fansReferer() {
return `https://space.bilibili.com/${this.vmid}/fans/fans`
}
get whispersUrl() {
return `https://api.bilibili.com/x/relation/whispers?pn=${this.pn}&ps=${this.ps}`
}
get whispersReferer() {
return `https://space.bilibili.com/${this.vmid}/fans/follow`
}
checkuid = 0
get relationUrl() {
return `https://api.bilibili.com/x/space/acc/relation?mid=${this.checkuid}`
}
get relationReferer() {
return `https://space.bilibili.com/${this.checkuid}`
}
async getFollowings() {
this.pn = 1
Console_log(`正在获取第${this.pn}页关注列表`)
/**
* @type {{
* code: number,
* message: string,
* ttl: number,
* data: {
* list: {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[],
* re_version: number,
* total: number
* }
* }}
*/
const data = JSON.parse(await HTTPsend(this.followUrl, "GET", { "Referer": this.followReferer }))
if (data && data.code === 0) {
this.total = data.data.total
/**
* @type {{
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[]}
*/
let list = data.data.list
if (list.length > 0 && list.length < this.total) {
this.pn += 1
for (; this.pn <= Math.ceil(this.total / this.ps); this.pn++) {
await RList.Push()
Console_log(`正在获取第${this.pn}页关注列表`)
/**
* @type {{
* code: number,
* message: string,
* ttl: number,
* data: {
* list: {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[],
* re_version: number,
* total: number
* }
* }}
*/
const data1 = JSON.parse(await HTTPsend(this.followUrl, "GET", { "Referer": this.followReferer }))
if (data1 && data1.code === 0) {
list = list.concat(data1.data.list)
}
else return Promise.reject(data1)
}
}
return list
} else {
return Promise.reject(data)
}
}
async getFollowers(page1) {
this.pn = 1
Console_log(`正在获取第${this.pn}页粉丝列表`)
/**
* @type {{
* code: number,
* message: string,
* ttl: number,
* data: {
* list: {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[],
* re_version: number,
* total: number
* }
* }}
*/
const data = JSON.parse(await HTTPsend(this.fansUrl, "GET", { "Referer": this.fansReferer }))
if (data && data.code === 0) {
this.fansTotal = data.data.total
/**
* @type {{
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[]}
*/
let list = data.data.list
if (!page1 && list.length > 0 && list.length < this.fansTotal) {
this.pn += 1
let maxpn = Math.ceil(this.fansTotal / this.ps) > this.fansMaxpn ? this.fansMaxpn : Math.ceil(this.fansTotal / this.ps)
for (; this.pn <= maxpn; this.pn++) {
await RList.Push()
Console_log(`正在获取第${this.pn}页粉丝列表`)
const data1 = JSON.parse(await HTTPsend(this.fansUrl, "GET", { "Referer": this.fansReferer }))
if (data1 && data1.code === 0) {
list = list.concat(data1.data.list)
}
else return Promise.reject(data1)
}
}
return list
} else {
return Promise.reject(data)
}
}
async getWhispers() {
/**
* @type {{
* code: number,
* message: string,
* ttl: number,
* data: {
* black: number,
* follower: number,
* following: number,
* mid: number,
* whisper: number
* }
* }}
*/
const status = JSON.parse(await HTTPsend(this.stat, "GET", { "Referer": this.whispersReferer }))
/**
* @type {{
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[]}
*/
let list = []
if (status.code === 0) {
if (status.data.whisper > 0) {
for (this.pn = 1; this.pn <= Math.ceil(status.data.whisper / this.ps); this.pn++) {
Console_log(`正在获取第${this.pn}页悄悄关注列表`)
/**
* @type {{
* code: number,
* message: string,
* ttl: number,
* data: {
* list: {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* contract_info: {
* is_contractor: boolean,
* ts: number,
* is_contract: boolean,
* user_attr: number
* },
* uname: string,
* face: string,
* sign: string,
* face_nft: number,
* official_verify: {
* type: number,
* desc: string
* }
* vip: {
* vipType: number,
* vipDueDate: number,
* dueRemark: string,
* accessStatus: number,
* vipStatus: number,
* vipStatusWarn: string,
* themeType: number,
* label: {
* path: string,
* text: string,
* label_theme: string,
* text_color: string,
* bg_style: number,
* bg_color: string,
* border_color: string
* },
* avatar_subscript: number,
* nickname_color: string,
* avatar_subscript_url: string
* }
* }[],
* re_version: number
* }
* }}
*/
const data = JSON.parse(await HTTPsend(this.whispersUrl, "GET", { "Referer": this.whispersReferer }))
if (data && data.code === 0) {
list = list.concat(data.data.list)
} else return Promise.reject(data)
}
}
return list
}
else return Promise.reject(status)
}
/**
* 检查是否已经关注
* @param {number} uid
*/
async checkFollow(uid) {
Console_log(`正在检查${uid}是否已经关注`)
this.checkuid = uid
/**
* @type {{
* code: number,
* message: string,
* ttl: number,
* data: {
* relation: {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* },
* be_relation: {
* mid: number,
* attribute: number,
* mtime: number,
* tag: null,
* special: number,
* }
* }
* }}
*/
const data = JSON.parse(await HTTPsend(this.relationUrl, "GET", { "Referer": this.relationReferer }))
if (data && data.code === 0) {
if (data.data.be_relation.mid === this.vmid) {
return true
}
else return false
}
else return Promise.reject(data)
}
}
const followingsDiff = async () => {
if (bLab8A.data.follow.length === 0 && bLab8A.data.follow2.length === 0) {
Console_log("没有关注列表")
bLab8A.data.follow = await BilibiliFollowChecker.getFollowings()
if (bLab8A.data.follow.length === 0) {
return { newfollow: [], follow: [], follow2: [], unfollowed: [], unfollowed2: [] }
}
bLab8A.data.follow2 = bLab8A.data.follow.filter(item => {
return item.attribute === 6
})
bLab8A.save(bLab8A.data)
return { newfollow: bLab8A.data.follow, follow: bLab8A.data.follow, follow2: bLab8A.data.follow2, unfollowed: [], unfollowed2: [] }
}
else {
let list = await BilibiliFollowChecker.getFollowings()
if (list.length === 0) {
return { newfollow: [], follow: [], follow2: [], unfollowed: bLab8A.data.follow, unfollowed2: [] }
}
let follow = []
let follow2 = []
let wht = []
for (let i = 0; i < list.length; i++) {
switch (list[i].attribute) {
case 6:
follow.push(list[i])
follow2.push(list[i])
break
case 2:
follow.push(list[i])
break
default:
Console_log(list[i].attribute)
wht.push(list[i])
break
}
}
if (wht.length > 0) {
Console_log(`有${wht.length}个未知类型的关注`)
}
Console_log(follow.length)
let newfollow = follow.filter(item => {
return !bLab8A.data.follow.some(item2 => {
return item.mid === item2.mid
})
})
let unfollowed = bLab8A.data.follow.filter(item => {
return !follow.some(item2 => {
return item.mid === item2.mid
})
})
let unfollowed2 = bLab8A.data.follow2.filter(item => {
return !follow2.some(item2 => {
return item.mid === item2.mid
})
})
bLab8A.data.follow = follow
bLab8A.data.follow2 = follow2
bLab8A.data.unfollowed = bLab8A.data.unfollowed.concat(unfollowed)
// 如果取消关注的人重新关注了,则把他从unfollowed中移除
// 你觉得他们还会回来吗?嗯?
bLab8A.data.unfollowed = bLab8A.data.unfollowed.filter(item => {
return !follow.some(item2 => {
return item.mid === item2.mid
})
})
bLab8A.data.unfollowed2 = bLab8A.data.unfollowed2.concat(unfollowed2)
bLab8A.data.unfollowed2 = bLab8A.data.unfollowed2.filter(item => {
return !follow2.some(item2 => {
return item.mid === item2.mid
}) || !follow.some(item2 => {
return item.mid === item2.mid
})
})
bLab8A.save(bLab8A.data)
return { newfollow, follow, follow2, unfollowed: bLab8A.data.unfollowed, unfollowed2: bLab8A.data.unfollowed2 }
}
}
const fansCheck = async (page1) => {
Console_log("开始检查粉丝")
Console_log("由于粉丝列表最多只能获取到50页,所以这里只检查前50页")
if (bLab8A.data.fans.length === 0) {
bLab8A.data.fans = await BilibiliFollowChecker.getFollowers(page1)
bLab8A.save(bLab8A.data)
return { newfans: bLab8A.data.fans, fans: bLab8A.data.fans }
}
else {
let fans = await BilibiliFollowChecker.getFollowers(page1)
let newfans = []
// 与bLab8A.data.fans比较,获取新增的粉丝
newfans = fans.filter(item => {
return !bLab8A.data.fans.some(item2 => {
return item.mid === item2.mid
})
})
// 将fans加入到bLab8A.data.fans中,同时避免重复加入
for (let i = 0; i < fans.length; i++) {
let isExist = false
for (let j = 0; j < bLab8A.data.fans.length; j++) {
if (fans[i].mid === bLab8A.data.fans[j].mid) {
isExist = true
break
}
}
if (!isExist) {
bLab8A.data.fans.push(fans[i])
}
}
bLab8A.save(bLab8A.data)
return { newfans, fans: bLab8A.data.fans }
}
}
const whispersCheck = async () => {
Console_log("开始检查悄悄关注")
if (bLab8A.data.whispers.length === 0) {
bLab8A.data.whispers = await BilibiliFollowChecker.getWhispers()
// bLab8A.data.whispers.map(whispers => {
// Console_log(whispers.mid, whispers.uname, whispers.attribute)
// })
bLab8A.save(bLab8A.data)
return { newwhispers: bLab8A.data.whispers, whispers: bLab8A.data.whispers }
}
else {
let whispers = await BilibiliFollowChecker.getWhispers()
let newwhispers = []
let unwhispers = []
// 与bLab8A.data.whispers比较,获取新增的悄悄关注
newwhispers = whispers.filter(item => {
return !bLab8A.data.whispers.some(item2 => {
return item.mid === item2.mid
})
})
// 与bLab8A.data.whispers比较,获取减少的悄悄关注
unwhispers = bLab8A.data.whispers.filter(item => {
return !whispers.some(item2 => {
return item.mid === item2.mid
})
})
// 将whispers加入到bLab8A.data.whispers中,同时避免重复加入
for (let i = 0; i < whispers.length; i++) {
let isExist = false
for (let j = 0; j < bLab8A.data.whispers.length; j++) {
if (whispers[i].mid === bLab8A.data.whispers[j].mid) {
isExist = true
break
}
}
if (!isExist) {
bLab8A.data.whispers.push(whispers[i])
}
}
// 将unwhispers加入到bLab8A.data.unwhispers中,同时避免重复加入
for (let i = 0; i < unwhispers.length; i++) {
let isExist = false
for (let j = 0; j < bLab8A.data.unwhispers.length; j++) {
if (unwhispers[i].mid === bLab8A.data.unwhispers[j].mid) {
isExist = true
break
}
}
if (!isExist) {
bLab8A.data.unwhispers.push(unwhispers[i])
}
}
// 从bLab8A.data.whispers中移除unwhispers
bLab8A.data.whispers = bLab8A.data.whispers.filter(item => {
return !unwhispers.some(item2 => {
return item.mid === item2.mid
})
})
// 如果悄悄关注变成了关注,则从bLab8A.data.unwhispers中移除
bLab8A.data.unwhispers = bLab8A.data.unwhispers.filter(item => {
return !bLab8A.data.follow.some(item2 => {
return item.mid === item2.mid
})
})
bLab8A.data.unwhispers = bLab8A.data.unwhispers.filter(item => {
return !bLab8A.data.follow2.some(item2 => {
return item.mid === item2.mid
})
})
bLab8A.save(bLab8A.data)
return { newwhispers, unwhispers: bLab8A.data.unwhispers, whispers: bLab8A.data.whispers }
}
}
const whispersFollowCheck = async () => {
for (let i = 0; i < bLab8A.data.whispers.length; i++) {
const whisper = bLab8A.data.whispers[i]
await RList.Push()
await RList.Push()
const isFollowed = await BilibiliFollowChecker.checkFollow(whisper.mid)
Console_log(whisper.mid, whisper.uname, whisper.attribute, isFollowed ? "已关注我" : "未关注我")
if (isFollowed) {
// 将whisper加入到bLab8A.data.whispersfollow中,同时避免重复加入
let isExist = false
for (let j = 0; j < bLab8A.data.whispersfollow.length; j++) {
if (whisper.mid === bLab8A.data.whispersfollow[j].mid) {
isExist = true
break
}
}
if (!isExist) {
bLab8A.data.whispersfollow.push(whisper)
}
}
}
bLab8A.save(bLab8A.data)
return "悄悄关注检查完毕"
}
const saveDataBlob = async () => {
const bLab8AData = new Blob([JSON.stringify(bLab8A.data)], { type: "application/json;charset=utf-8" })
// const defaultData = "{\"follow\":[],\"follow2\":[],\"unfollowed\":[],\"unfollowed2\":[],\"fans\":[],\"unfans\":[],\"whispers\":[],\"unwhispers\":[],\"whispersfollow\":[]}"
const date = Math.round(new Date() / 1000)
saveAs(bLab8AData, `UID_${BilibiliFollowChecker.vmid}_f${bLab8A.data.follow.length}_2f${bLab8A.data.follow2.length}_uf${bLab8A.data.unfollowed.length}_2uf${bLab8A.data.unfollowed2.length}_${date}.json`)
return "数据保存成功"
}
/**
*
* @param {string} file
* @returns {string}
*/
const loadDataBlob = (file) => {
// const file = await openFile()
const parseData = JSON.parse(file)
// 逐个导入follow,follow2,unfollowed,unfollowed2,fans,unfans,whispers,unwhispers,whispersfollow数据,同时避免重复加入
const keys = ["follow", "follow2", "unfollowed", "unfollowed2", "fans", "unfans", "whispers", "unwhispers", "whispersfollow"]
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
Console_log(parseData[key].length, key)
let numbers = 0
for (let j = 0; j < parseData[key].length; j++) {
const item = parseData[key][j]
let isExist = false
for (let k = 0; k < bLab8A.data[key].length; k++) {
if (item.mid === bLab8A.data[key][k].mid) {
isExist = true
break
}
}
if (!isExist) {
bLab8A.data[key].push(item)
numbers++
}
}
Console_log(`${key}有${numbers}条数据加入成功`)
}
bLab8A.save(bLab8A.data)
return "数据加载成功"
}
/**
*
* @returns {Promise<string>}
*/
const openFile = () => {
return new Promise((resolve, reject) => {
let fileInput = document.createElement("input")
// 指定文件类型为json
fileInput.type = 'file'
fileInput.accept = 'application/json'
// fileInput.setAttribute("accept", ".json")
fileInput.style.backgroundColor = '#666'
fileInput.style.position = 'fixed'
fileInput.style.right = '0px'
fileInput.style.bottom = '0px'
fileInput.style.zIndex = '9999'
fileInput.addEventListener('change', (e) => {
const file = fileInput.files[0]
Console_log(file);
if (!file) {
return reject("未选择文件")
}
let reader = new FileReader()
reader.onload = (e1) => {
let contents = e1.target.result
resolve(contents)
document.body.removeChild(fileInput)
}
reader.readAsText(file)
})
document.body.appendChild(fileInput)
})
}
const cleanData = () => {
if (confirm("确定要清空数据吗?")) {
if (confirm("最后一次确认,确定要清空数据吗?")) {
bLab8A.data = { uid: bLab8A.data.uid, follow: [], follow2: [], unfollowed: [], unfollowed2: [], fans: [], unfans: [], whispers: [], unwhispers: [], whispersfollow: [] }
bLab8A.save(bLab8A.data)
}
}
}
const checkData = () => {
// 数据去重
const keys = ["follow", "follow2", "unfollowed", "unfollowed2", "fans", "unfans", "whispers", "unwhispers", "whispersfollow"]
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
let numbers = 0
for (let j = 0; j < bLab8A.data[key].length; j++) {
const item = bLab8A.data[key][j]
let isExist = false
for (let k = 0; k < bLab8A.data[key].length; k++) {
if (j !== k && item.mid === bLab8A.data[key][k].mid) {
isExist = true
break
}
}
if (isExist) {
bLab8A.data[key].splice(j, 1)
numbers++
}
}
Console_log(`${key}有${numbers}条数据去重成功,剩余${bLab8A.data[key].length}条数据:`)
console.log(bLab8A.data[key])
}
bLab8A.save(bLab8A.data)
}
let wanaStop = false
const testC = async () => {
let data = []
for (let i = parseInt(prompt("Enter", 1)); i <= 703223001; i++) {
if (wanaStop) break
try {
Console_log(`${i}/${703223001}`)
if (await BilibiliFollowChecker.checkFollow(i)) {
Console_log(`${i} 已关注我`)
data.push(i)
}
}
catch (e) {
Console_log(e)
break
}
}
const Data = new Blob([JSON.stringify(data)], { type: "application/json;charset=utf-8" })
saveAs(Data, `test${data.length}.json`)
}
GM_registerMenuCommand("获取关注差异", () => { followingsDiff().then(Console_log).catch(console.error) })
GM_registerMenuCommand("检查粉丝", () => { fansCheck().then(Console_log).catch(console.error) })
GM_registerMenuCommand("检查粉丝第一页", () => { fansCheck(true).then(Console_log).catch(console.error) })
GM_registerMenuCommand("更新悄悄关注", () => { whispersCheck().then(Console_log).catch(console.error) })
GM_registerMenuCommand("检查悄悄关注的人", () => { whispersFollowCheck().then(Console_log).catch(console.error) })
GM_registerMenuCommand("导出数据", () => { saveDataBlob().then(Console_log).catch(console.error) })
GM_registerMenuCommand("导入数据(点击后看右下角)", () => { openFile().then(e => { Console_log(loadDataBlob(e)) }).catch(console.error) })
GM_registerMenuCommand("数据检查", () => { checkData() })
GM_registerMenuCommand("清空数据", () => { cleanData() })
GM_registerMenuCommand("你的UID", () => {
const vmid = prompt("请输入你的UID", BilibiliFollowChecker.vmid)
if (vmid) {
BilibiliFollowChecker.vmid = parseInt(vmid)
bLab8A.data.uid = parseInt(vmid)
bLab8A.save(bLab8A.data)
}
})
DEV_Log && GM_registerMenuCommand("测试", () => { testC() })
DEV_Log && GM_registerMenuCommand("想停下来", () => { wanaStop = true })
GM_registerMenuCommand("检查UID", () => { BilibiliFollowChecker.checkFollow(parseInt(prompt("输入UID", BilibiliFollowChecker.checkuid))).then(Console_log).catch(console.error) })
})()