mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
commit
81cbb79dfd
207
registry/lib/components/utils/auto-like/blackList.vue
Normal file
207
registry/lib/components/utils/auto-like/blackList.vue
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<VPopup
|
||||||
|
ref="popup"
|
||||||
|
v-model="isOpen"
|
||||||
|
class="like-black-list"
|
||||||
|
fixed
|
||||||
|
:lazy="false"
|
||||||
|
:trigger-element="triggerElement"
|
||||||
|
>
|
||||||
|
<div class="black-list-header">
|
||||||
|
<VIcon class="title-icon" icon="mdi-sort" :size="24"></VIcon>
|
||||||
|
<div class="title">添加黑名单</div>
|
||||||
|
<div class="close" @click="isOpen = false">
|
||||||
|
<VIcon icon="close" :size="18"></VIcon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="black-list-content">
|
||||||
|
<div class="black-list-section">
|
||||||
|
<div class="black-list-section-title">添加到黑名单</div>
|
||||||
|
<div class="black-list-section-input">
|
||||||
|
<TextBox :text="name" @change="changeName" />
|
||||||
|
<VButton @click="add">添加</VButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="black-list-section">
|
||||||
|
<div class="black-list-section-title">黑名单列表</div>
|
||||||
|
<div class="black-list-section-description">点击×图标可以删除名单.</div>
|
||||||
|
<VLoading v-if="!isLoaded" />
|
||||||
|
<div
|
||||||
|
v-show="isLoaded"
|
||||||
|
ref="black-listSortList"
|
||||||
|
class="black-list-section-content black-list-sort-list"
|
||||||
|
>
|
||||||
|
<div v-for="item of list" :key="item" class="black-list-sort-item" :data-name="item">
|
||||||
|
<div class="item-name">
|
||||||
|
{{ item }}
|
||||||
|
</div>
|
||||||
|
<div class="toggle-visible">
|
||||||
|
<VIcon :size="18" icon="close" @click="toggleVisible(item)"></VIcon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VPopup>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { VPopup, TextBox, VIcon, VButton } from '@/ui'
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
components: {
|
||||||
|
VPopup,
|
||||||
|
TextBox,
|
||||||
|
VIcon,
|
||||||
|
VButton,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
triggerElement: {
|
||||||
|
type: HTMLElement,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
titleName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isOpen: false,
|
||||||
|
isLoaded: false,
|
||||||
|
name: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.isLoaded = true
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggle() {
|
||||||
|
this.$refs.popup.toggle()
|
||||||
|
},
|
||||||
|
changeName(val: string) {
|
||||||
|
this.name = val
|
||||||
|
},
|
||||||
|
add() {
|
||||||
|
if (this.name.length && !this.list.includes(this.name)) {
|
||||||
|
// eslint-disable-next-line vue/no-mutating-props
|
||||||
|
this.list.push(this.name)
|
||||||
|
}
|
||||||
|
this.name = ''
|
||||||
|
},
|
||||||
|
toggleVisible(item: string) {
|
||||||
|
// eslint-disable-next-line vue/no-mutating-props
|
||||||
|
this.list.splice(this.list.indexOf(item), 1)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import 'common';
|
||||||
|
.like-black-list {
|
||||||
|
@include popup();
|
||||||
|
width: 400px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 12px 12px 12px 18px;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateX(-50%) translateY(-50%) scale(0.95);
|
||||||
|
transition: 0.2s ease-out;
|
||||||
|
z-index: 100002;
|
||||||
|
&.open {
|
||||||
|
transform: translateX(-50%) translateY(-50%) scale(1);
|
||||||
|
}
|
||||||
|
.black-list-header {
|
||||||
|
@include h-center();
|
||||||
|
justify-content: space-between;
|
||||||
|
.title {
|
||||||
|
margin-left: 6px;
|
||||||
|
font-size: 18px;
|
||||||
|
@include semi-bold();
|
||||||
|
}
|
||||||
|
.grow {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.close {
|
||||||
|
padding: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.2s ease-out;
|
||||||
|
&:hover {
|
||||||
|
color: var(--theme-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.black-list-content {
|
||||||
|
.black-list-section {
|
||||||
|
margin-top: 12px;
|
||||||
|
> :not(:last-child) {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
&-title {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
&-input {
|
||||||
|
display: flex;
|
||||||
|
div {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-description {
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.6;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
&-content {
|
||||||
|
@include h-center();
|
||||||
|
flex-wrap: wrap;
|
||||||
|
.be-slider {
|
||||||
|
margin: 0 4px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.padding-value {
|
||||||
|
margin-left: 12px;
|
||||||
|
width: 50px;
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
.black-list-sort-item {
|
||||||
|
@include card();
|
||||||
|
@include h-center();
|
||||||
|
transition: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 6px;
|
||||||
|
padding-left: 8px;
|
||||||
|
margin: 0 4px 4px 0;
|
||||||
|
cursor: move;
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--theme-color);
|
||||||
|
}
|
||||||
|
&.black-list-hidden {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
&.sortable-ghost {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
&.sortable-chosen {
|
||||||
|
box-shadow: 0 4px 16px 0 rgb(0 0 0 / 16%);
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
&.sortable-drag {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
&.sortable-drag.black-list-hidden {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.toggle-visible {
|
||||||
|
margin-left: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1 +1,4 @@
|
|||||||
进入视频 / 查看动态时, 自动点赞.
|
进入视频 / 查看动态时, 自动点赞\
|
||||||
|
无法触发未加载动态的点赞,当启用手动对动态点赞后可手动触发,启用后不会触发动态自动点赞\
|
||||||
|
安装快捷键扩展后可以点击【l】键或【L】键触发\
|
||||||
|
还可以添加动态点赞的黑名单\
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { defineComponentMetadata } from '@/components/define'
|
import { defineComponentMetadata } from '@/components/define'
|
||||||
import { forEachFeedsCard } from '@/components/feeds/api'
|
|
||||||
import { select } from '@/core/spin-query'
|
import { select } from '@/core/spin-query'
|
||||||
import { matchUrlPattern, playerReady } from '@/core/utils'
|
import { matchUrlPattern, playerReady } from '@/core/utils'
|
||||||
import { feedsUrls, videoAndBangumiUrls } from '@/core/utils/urls'
|
import { feedsUrls, videoAndBangumiUrls } from '@/core/utils/urls'
|
||||||
|
import { KeyBindingAction } from '../keymap/bindings'
|
||||||
|
import { forEachFeedsCard } from '@/components/feeds/api'
|
||||||
|
import { BlackListDataKey, loadlikeButton } from './vm'
|
||||||
|
import { getData, registerData } from '@/plugins/data'
|
||||||
|
|
||||||
const feedsLikeQueue = [] as HTMLElement[]
|
const feedsLikeQueue = [] as HTMLElement[]
|
||||||
export const component = defineComponentMetadata({
|
export const component = defineComponentMetadata({
|
||||||
@ -10,6 +13,10 @@ export const component = defineComponentMetadata({
|
|||||||
displayName: '自动点赞',
|
displayName: '自动点赞',
|
||||||
tags: [componentsTags.utils, componentsTags.feeds, componentsTags.video],
|
tags: [componentsTags.utils, componentsTags.feeds, componentsTags.video],
|
||||||
urlInclude: [...videoAndBangumiUrls, ...feedsUrls],
|
urlInclude: [...videoAndBangumiUrls, ...feedsUrls],
|
||||||
|
author: {
|
||||||
|
name: 'CrazyboyQCD',
|
||||||
|
link: 'https://github.com/CrazyboyQCD',
|
||||||
|
},
|
||||||
options: {
|
options: {
|
||||||
video: {
|
video: {
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
@ -19,7 +26,17 @@ export const component = defineComponentMetadata({
|
|||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
displayName: '对动态点赞',
|
displayName: '对动态点赞',
|
||||||
},
|
},
|
||||||
|
manualFeed: {
|
||||||
|
defaultValue: true,
|
||||||
|
displayName: '手动对动态点赞',
|
||||||
|
},
|
||||||
|
users: {
|
||||||
|
displayName: '黑名单',
|
||||||
|
defaultValue: [] as string[],
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
extraOptions: () => import('./settings.vue').then(m => m.default),
|
||||||
entry: async ({ settings: { options } }) => {
|
entry: async ({ settings: { options } }) => {
|
||||||
if (options.video && videoAndBangumiUrls.some(url => matchUrlPattern(url))) {
|
if (options.video && videoAndBangumiUrls.some(url => matchUrlPattern(url))) {
|
||||||
await playerReady()
|
await playerReady()
|
||||||
@ -32,22 +49,51 @@ export const component = defineComponentMetadata({
|
|||||||
likeButton.click()
|
likeButton.click()
|
||||||
}
|
}
|
||||||
if (options.feed && feedsUrls.some(url => matchUrlPattern(url))) {
|
if (options.feed && feedsUrls.some(url => matchUrlPattern(url))) {
|
||||||
window.setInterval(() => {
|
const blackListData = {
|
||||||
if (feedsLikeQueue.length === 0) {
|
users: options.users,
|
||||||
return
|
}
|
||||||
}
|
registerData(BlackListDataKey, blackListData)
|
||||||
const button = feedsLikeQueue.shift()
|
if (options.manualFeed) {
|
||||||
button?.click()
|
loadlikeButton()
|
||||||
}, 1000)
|
} else {
|
||||||
forEachFeedsCard({
|
window.setInterval(() => {
|
||||||
added: card => {
|
if (feedsLikeQueue.length === 0) {
|
||||||
const likeButton = dq(card.element, '.bili-dyn-action.like') as HTMLElement
|
|
||||||
if (!likeButton || likeButton.classList.contains('active')) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
feedsLikeQueue.push(likeButton)
|
const button = feedsLikeQueue.shift()
|
||||||
},
|
button?.click()
|
||||||
})
|
}, 1000)
|
||||||
|
const blackList = getData(BlackListDataKey)
|
||||||
|
forEachFeedsCard({
|
||||||
|
added: card => {
|
||||||
|
if (blackList.includes(card.username)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const likeButtons = dq(card.element, '.bili-dyn-action.like') as HTMLElement
|
||||||
|
if (!likeButtons || likeButtons.classList.contains('active')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
feedsLikeQueue.push(likeButtons)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
plugin: {
|
||||||
|
displayName: '点赞 - 手动',
|
||||||
|
setup: ({ addData }) => {
|
||||||
|
addData('keymap.actions', (actions: Record<string, KeyBindingAction>) => {
|
||||||
|
actions.manuallike = {
|
||||||
|
displayName: '手动触发对动态点赞',
|
||||||
|
run: context => {
|
||||||
|
const { clickElement } = context
|
||||||
|
return clickElement('.manual-like', context)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
addData('keymap.presets', (presetBase: Record<string, string>) => {
|
||||||
|
presetBase.manuallike = 'l L'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
84
registry/lib/components/utils/auto-like/like.vue
Normal file
84
registry/lib/components/utils/auto-like/like.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<VButton round class="manual-like" @click="like">
|
||||||
|
<div id="text" :class="{ like: isLike }">正在点赞: {{ curLikeCnt }} / {{ totalLikeCnt }}</div>
|
||||||
|
<VIcon v-show="!isLike" colored icon="like" :size="20" />
|
||||||
|
</VButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { VButton, VIcon } from '@/ui'
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
components: {
|
||||||
|
VButton,
|
||||||
|
VIcon,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isClick: false,
|
||||||
|
isLike: false,
|
||||||
|
totalLikeCnt: 0,
|
||||||
|
curLikeCnt: 0,
|
||||||
|
feedsLikeQueue: [] as HTMLElement[],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
like() {
|
||||||
|
if (this.isClick) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.isClick = true
|
||||||
|
// forEachFeedsCard异步执行顺序有问题,不能及时同步,用dqa代替
|
||||||
|
const likeButtons = (dqa('.bili-dyn-title__text') as HTMLElement[]).flatMap(e => {
|
||||||
|
if (this.list.includes(e.textContent)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const likeButton = e.closest('.bili-dyn-item__main').querySelector('.bili-dyn-action.like')
|
||||||
|
return likeButton && !likeButton.classList.contains('active') ? likeButton : []
|
||||||
|
})
|
||||||
|
this.feedsLikeQueue.push(...likeButtons)
|
||||||
|
this.totalLikeCnt = this.feedsLikeQueue.length
|
||||||
|
this.curLikeCnt = 0
|
||||||
|
this.isLike = true
|
||||||
|
const t = window.setInterval(() => {
|
||||||
|
if (this.feedsLikeQueue.length === 0) {
|
||||||
|
this.isLike = false
|
||||||
|
this.isClick = false
|
||||||
|
clearInterval(t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const button = this.feedsLikeQueue.shift()
|
||||||
|
button?.click()
|
||||||
|
this.curLikeCnt++
|
||||||
|
}, 1200)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.manual-like {
|
||||||
|
left: 5px;
|
||||||
|
z-index: 1001;
|
||||||
|
height: 30px;
|
||||||
|
position: fixed;
|
||||||
|
* {
|
||||||
|
color: rgb(251, 114, 153);
|
||||||
|
}
|
||||||
|
#text {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 0px;
|
||||||
|
transition: max-width 0.4s linear !important;
|
||||||
|
&.like {
|
||||||
|
max-width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
50
registry/lib/components/utils/auto-like/settings.vue
Normal file
50
registry/lib/components/utils/auto-like/settings.vue
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="custom-black-list-extra-options">
|
||||||
|
<VButton ref="button" @mouseover="setBlackListProps" @click="toggleBlackList">
|
||||||
|
黑名单
|
||||||
|
<VIcon icon="right-arrow" :size="16" />
|
||||||
|
</VButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { VIcon, VButton } from '@/ui'
|
||||||
|
import { loadBlackList, setBlackListProps, toggleBlackList } from './vm'
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
components: {
|
||||||
|
VIcon,
|
||||||
|
VButton,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isFirstLoad: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggle() {
|
||||||
|
this.$refs.popup.toggle()
|
||||||
|
},
|
||||||
|
async setBlackListProps() {
|
||||||
|
if (this.isFirstLoad) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.isFirstLoad = await loadBlackList()
|
||||||
|
if (this.isFirstLoad) {
|
||||||
|
const triggerButton = this.$refs.button.$el as HTMLElement
|
||||||
|
setBlackListProps(triggerButton)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleBlackList,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.custom-black-list-extra-options {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
48
registry/lib/components/utils/auto-like/vm.ts
Normal file
48
registry/lib/components/utils/auto-like/vm.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { select } from '@/core/spin-query'
|
||||||
|
import { mountVueComponent } from '@/core/utils'
|
||||||
|
import { getData } from '@/plugins/data'
|
||||||
|
|
||||||
|
export const BlackListDataKey = 'like-black-List.data'
|
||||||
|
|
||||||
|
type SettingsVmType = Vue & {
|
||||||
|
toggle: () => void
|
||||||
|
triggerElement: HTMLElement
|
||||||
|
list: string[]
|
||||||
|
titleName: string
|
||||||
|
}
|
||||||
|
let blacklistVM: SettingsVmType = null
|
||||||
|
|
||||||
|
export const setBlackListProps = (element: HTMLElement) => {
|
||||||
|
if (!blacklistVM) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
blacklistVM.triggerElement = element
|
||||||
|
const blackList = getData(BlackListDataKey)
|
||||||
|
blacklistVM.list = blackList[0].users
|
||||||
|
blacklistVM.titleName = '黑名单'
|
||||||
|
}
|
||||||
|
export const loadlikeButton = async () => {
|
||||||
|
const LikeButton = await import('./like.vue').then(m => m.default)
|
||||||
|
const blackList = getData(BlackListDataKey)
|
||||||
|
const likebuttonVM: Vue & { list: string[] } = mountVueComponent(LikeButton)
|
||||||
|
likebuttonVM.list = blackList[0].users
|
||||||
|
const bg = (await select('#app')) as HTMLElement
|
||||||
|
bg.insertAdjacentElement('afterbegin', likebuttonVM.$el)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loadBlackList = async () => {
|
||||||
|
if (blacklistVM) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const blackList = await import('./blackList.vue').then(m => m.default)
|
||||||
|
blacklistVM = mountVueComponent(blackList)
|
||||||
|
document.body.insertAdjacentElement('beforeend', blacklistVM.$el)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toggleBlackList = async () => {
|
||||||
|
if (!blacklistVM) {
|
||||||
|
await loadBlackList()
|
||||||
|
}
|
||||||
|
blacklistVM?.toggle()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user