Skip to content

Commit

Permalink
feat: add fetching user followings (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chilfish authored Mar 29, 2024
1 parent 5c7e2b7 commit 56d7de8
Show file tree
Hide file tree
Showing 20 changed files with 387 additions and 61 deletions.
12 changes: 10 additions & 2 deletions apps/monkey/src/Config.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ const dateRange = computed({
clearable
/>

<div class="center flex-wrap justify-start gap-2">
<div
v-if="!config.followingsOnly"
class="center flex-wrap justify-start gap-2"
>
<n-checkbox
v-model:checked="config.largePic"
label="导出原图"
Expand Down Expand Up @@ -65,6 +68,7 @@ const dateRange = computed({
</template>
默认开始前都会清空之前的状态
</n-tooltip>

<button
class="py-1 text-3.5 btn bg-#18a058! hover:bg-green-7!"
@click="() => {
Expand All @@ -74,7 +78,11 @@ const dateRange = computed({
重置为所有微博
</button>
</div>

<n-checkbox
v-model:checked="config.followingsOnly"
label="只导出关注列表"
size="small"
/>
<div
v-show="config.hasComment"
class="flex items-center gap-4"
Expand Down
67 changes: 42 additions & 25 deletions apps/monkey/src/Ctrl.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<script setup lang="ts">
import { useMessage } from 'naive-ui'
import { saveAs } from 'file-saver'
import { storeToRefs } from 'pinia'
import { exportData } from '@core/utils'
import { fetchFollowings } from '@core/services'
import { useConfigStore, usePostStore } from './stores'
import Config from './Config.vue'
Expand All @@ -15,37 +14,31 @@ const configStore = useConfigStore()
const isStart = ref(false)
const isStop = ref(false)
const isFinish = ref(false)
const isFetchingFollowings = ref(false)
const { config } = storeToRefs(configStore)
const percentage = computed(() => config.value.fetchedCount / postStore.total * 100)
const progressText = computed(() => () => `${config.value.fetchedCount}/${postStore.total} 条`)
/**
* 导出数据
*/
async function exportDatas() {
const posts = await postStore.getAll()
console.log('导出的数量:', posts.length)
const res = await exportData(posts, postStore.userInfo)
if (!res)
return
const scripts = 'https://github.com/Chilfish/Weibo-archiver/raw/monkey/scripts.zip'
saveAs(scripts, 'scripts.zip')
}
const { pause, start } = fetchPosts({
fetchOptions: () => ({
...config.value,
savePost: post => postStore.add(post),
}),
setTotal: total => postStore.total = total,
onFinish: async () => {
message.success('获取完毕~,正在获取关注列表')
isFetchingFollowings.value = true
await fetchFollowings(
config.value.uid,
async data => postStore.addFollowings(data),
)
await postStore.exportDatas()
isStart.value = false
isFinish.value = true
config.value.curPage--
exportDatas()
},
})
Expand All @@ -55,18 +48,32 @@ async function startFetch() {
})
postStore.setDB()
await postStore.setCount()
isStart.value = true
isFinish.value = false
isStop.value = false
isFetchingFollowings.value = false
// 如果只获取关注列表
if (config.value.followingsOnly) {
isFetchingFollowings.value = true
await fetchFollowings(
config.value.uid,
async data => postStore.addFollowings(data),
)
await postStore.exportFollowings()
isStart.value = false
isFinish.value = true
return
}
// 如果是重新开始,不保留上次 fetch 的状态
if (!config.value.restore || !config.value.isFetchAll)
await postStore.reset()
await postStore.setCount()
await postStore.setUser()
isStart.value = true
isFinish.value = false
isStop.value = false
start()
await start()
}
window.$message = message
Expand Down Expand Up @@ -94,6 +101,16 @@ function toggleStop() {
else
start()
}
const startButtonText = computed(() => {
if (config.value.followingsOnly)
return '获取关注列表'
if (isStop.value)
return `重新开始获取 ${config.value.isFetchAll ? '全部' : '部分'} 微博`
return `开始获取 ${config.value.isFetchAll ? '全部' : '部分'} 微博`
})
</script>

<template>
Expand Down Expand Up @@ -141,14 +158,14 @@ function toggleStop() {
v-show="!isStart || isStop"
@click="startFetch"
>
{{ isStop ? '重新' : '' }}开始获取 <strong>{{ config.isFetchAll ? '全部' : '部分' }}</strong> 微博
{{ startButtonText }}
</button>

<div
v-show="isStart && !isFinish && !isStop"
class="center"
>
获取中~
正在获取{{ isFetchingFollowings ? '关注列表' : '微博' }} ~
</div>

<button
Expand All @@ -160,7 +177,7 @@ function toggleStop() {

<button
v-show="isFinish || isStop"
@click="exportDatas"
@click="postStore.exportDatas"
>
导出
</button>
Expand Down
1 change: 1 addition & 0 deletions apps/monkey/src/stores/configStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const useConfigStore = defineStore('config', () => {
hasComment: true,
hasFavorite: true,
commentCount: 6,
followingsOnly: false,
dateRange: [now, now],
}

Expand Down
33 changes: 32 additions & 1 deletion apps/monkey/src/stores/postStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineStore, storeToRefs } from 'pinia'
import type { Post, UID, UserInfo } from '@types'
import type { Post, UID, UserBio, UserInfo } from '@types'
import { EmptyIDB, IDB } from '@core/utils/storage'
import saveAs from 'file-saver'
import { useConfigStore } from './configStore'

export const usePostStore = defineStore('post', () => {
Expand Down Expand Up @@ -84,6 +85,33 @@ export const usePostStore = defineStore('post', () => {
await idb.value.setUserInfo(user)
}

async function addFollowings(followings: UserBio[]) {
await waitIDB()
await idb.value.addFollowings(followings)
}

async function exportFollowings() {
await waitIDB()
const data = await idb.value.getFollowings()
return await exportData([], userInfo.value, data)
}

/**
* 导出数据
*/
async function exportDatas() {
const posts = await getAll()
console.log('导出的数量:', posts.length)

const followings = await idb.value.getFollowings()

const res = await exportData(posts, userInfo.value, followings)
if (!res)
return
const scripts = 'https://github.com/Chilfish/Weibo-archiver/raw/monkey/scripts.zip'
saveAs(scripts, 'scripts.zip')
}

return {
total,
pageSize,
Expand All @@ -95,5 +123,8 @@ export const usePostStore = defineStore('post', () => {
getAll,
setCount,
setUser,
exportDatas,
addFollowings,
exportFollowings,
}
})
68 changes: 67 additions & 1 deletion packages/core/src/services/userService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { UserInfo } from '@types'
import type { UserBio, UserInfo } from '@types'
import { weiFetch } from '../utils/fetch'
import { parseFollowing } from '../utils'

export async function userInfo(
{ id, name }: { id?: string, name?: string },
Expand Down Expand Up @@ -55,3 +56,68 @@ export async function userDetail(
...detail,
}
}

export async function getFollowings(
uid: string,
page: number,
) {
const { users, total_number } = await weiFetch<{
users: any[]
total_number: number
}>('/friendships/friends', {
params: {
uid,
page,
},
})

return {
users: users.map(parseFollowing),
total: total_number,
}
}

export async function getMyFollowings(
page: number,
) {
const { data } = await weiFetch<{ data: {
follows: { users: any[] }
total_number: number
} }>('/profile/followContent', {
params: {
page,
},
})

return {
users: data.follows.users.map(parseFollowing),
total: data.total_number,
}
}

export function isMe(uid: string) {
// 获取头像的链接
const links = Array.from(document.querySelector('[role=navigation]')?.querySelectorAll('a') || [])
const matched = links[links.length - 1]?.href.match(/\d+/)?.[0] || ''

return matched === uid
}

export async function fetchFollowings(
uid: string,
saveData: (users: UserBio[], total: number) => Promise<void>,
) {
let page = 1
const _isMe = isMe(uid)
while (true) {
await delay(3000)
const { users, total } = _isMe
? await getMyFollowings(page)
: await getFollowings(uid, page)

await saveData(users, total)
page += 1
if (users.length === 0)
break
}
}
18 changes: 17 additions & 1 deletion packages/core/src/stores/post.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { defineStore } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import type { Post, UID, UserInfo } from '@types'
import type { Post, UID, UserBio, UserInfo } from '@types'
import { EmptyIDB, IDB } from '../utils/storage'

export const usePostStore = defineStore('post', () => {
const publicStore = usePublicStore()
const followings = shallowRef<UserBio[]>([])

const idb = ref(new EmptyIDB())
watchImmediate(() => publicStore.curUid, async (uid) => {
Expand All @@ -16,6 +17,8 @@ export const usePostStore = defineStore('post', () => {

idb.value = new IDB(wrappedUid)
await updateTotal()

followings.value = await getFollowings()
})

const route = useRoute()
Expand Down Expand Up @@ -72,10 +75,14 @@ export const usePostStore = defineStore('post', () => {
async function set(
data: Post[],
user: UserInfo,
followings?: UserBio[],
isReplace = false,
) {
await waitIDB()

if (followings && followings.length)
await idb.value.addFollowings(followings)

const { count, search } = await idb.value.addDBPosts(data, isReplace)
totalDB.value = count
total.value = count
Expand Down Expand Up @@ -196,12 +203,20 @@ export const usePostStore = defineStore('post', () => {
return posts
}

async function getFollowings() {
await waitIDB()
return await idb.value
.getFollowings()
.then(data => data.sort((a, b) => a.name.localeCompare(b.name)))
}

return {
total,
totalDB,
pages,
pageSize,
curPage,
followings,

get,
set,
Expand All @@ -226,5 +241,6 @@ export const usePostStore = defineStore('post', () => {
getByTime,
searchPost,
searchAndTime,
getFollowings,
}
})
9 changes: 7 additions & 2 deletions packages/core/src/stores/public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ export const usePublicStore = defineStore('public', () => {
})

function addUser(user: UserInfo | null | undefined) {
if (!user || users.value.find(u => u.uid === user.uid))
if (!user)
return

users.value.push(user)
const idx = users.value.findIndex(u => u.uid === user.uid)

if (idx < 0)
users.value.push(user)
else
users.value.splice(idx, 1, user)
}

function rmUser() {
Expand Down
Loading

0 comments on commit 56d7de8

Please sign in to comment.