mirror of
https://github.com/snachodog/tok-to-insta-follower-bridge.git
synced 2025-04-23 20:12:22 -06:00
refactor: create abstract class
This commit is contained in:
parent
20b04b9322
commit
a14e5395e5
@ -2,11 +2,25 @@ import type { AtpSessionData } from "@atproto/api";
|
|||||||
import { Storage } from "@plasmohq/storage";
|
import { Storage } from "@plasmohq/storage";
|
||||||
import { useStorage } from "@plasmohq/storage/hook";
|
import { useStorage } from "@plasmohq/storage/hook";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { match, P } from "ts-pattern";
|
||||||
import { BskyServiceWorkerClient } from "~lib/bskyServiceWorkerClient";
|
import { BskyServiceWorkerClient } from "~lib/bskyServiceWorkerClient";
|
||||||
import { type MESSAGE_NAMES, STORAGE_KEYS } from "~lib/constants";
|
import { MESSAGE_NAMES, STORAGE_KEYS } from "~lib/constants";
|
||||||
import { searchBskyUser } from "~lib/searchBskyUsers";
|
import { searchBskyUser } from "~lib/searchBskyUsers";
|
||||||
import { XService } from "~lib/services/x";
|
import type { AbstractService } from "~lib/services/abstractService";
|
||||||
import type { BskyUser, CrawledUserInfo } from "~types";
|
import { XService } from "~lib/services/xService";
|
||||||
|
import type { BskyUser, CrawledUserInfo, MessageName } from "~types";
|
||||||
|
|
||||||
|
const getService = (messageName: string): AbstractService => {
|
||||||
|
return match(messageName)
|
||||||
|
.with(P.when((name) => [
|
||||||
|
MESSAGE_NAMES.SEARCH_BSKY_USER_ON_FOLLOW_PAGE,
|
||||||
|
MESSAGE_NAMES.SEARCH_BSKY_USER_ON_LIST_MEMBERS_PAGE,
|
||||||
|
MESSAGE_NAMES.SEARCH_BSKY_USER_ON_BLOCK_PAGE,
|
||||||
|
].includes(name as MessageName)),
|
||||||
|
() => new XService(messageName),
|
||||||
|
)
|
||||||
|
.otherwise(() => new XService(messageName));
|
||||||
|
};
|
||||||
|
|
||||||
export const useRetrieveBskyUsers = () => {
|
export const useRetrieveBskyUsers = () => {
|
||||||
const bskyClient = React.useRef<BskyServiceWorkerClient | null>(null);
|
const bskyClient = React.useRef<BskyServiceWorkerClient | null>(null);
|
||||||
@ -75,7 +89,7 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
|
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
const xService = new XService(messageName);
|
const service = getService(messageName);
|
||||||
|
|
||||||
// loop until we get to the bottom
|
// loop until we get to the bottom
|
||||||
while (!isBottomReached) {
|
while (!isBottomReached) {
|
||||||
@ -83,10 +97,10 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = xService.getCrawledUsers();
|
const data = service.getCrawledUsers();
|
||||||
await retrieveBskyUsers(data);
|
await retrieveBskyUsers(data);
|
||||||
|
|
||||||
const isEnd = await xService.performScrollAndCheckEnd();
|
const isEnd = await service.performScrollAndCheckEnd();
|
||||||
|
|
||||||
if (isEnd) {
|
if (isEnd) {
|
||||||
setIsBottomReached(true);
|
setIsBottomReached(true);
|
||||||
|
37
src/lib/services/abstractService.ts
Normal file
37
src/lib/services/abstractService.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { MESSAGE_NAME_TO_QUERY_PARAM_MAP } from "~lib/constants";
|
||||||
|
import type { CrawledUserInfo, MessageName } from "~types";
|
||||||
|
|
||||||
|
export abstract class AbstractService {
|
||||||
|
messageName: MessageName;
|
||||||
|
crawledUsers: Set<string>;
|
||||||
|
|
||||||
|
constructor(messageName: string) {
|
||||||
|
this.messageName = messageName as MessageName;
|
||||||
|
this.crawledUsers = new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract extractUserData(userCell: Element): CrawledUserInfo;
|
||||||
|
|
||||||
|
getCrawledUsers(): CrawledUserInfo[] {
|
||||||
|
const userCells = Array.from(
|
||||||
|
document.querySelectorAll(
|
||||||
|
MESSAGE_NAME_TO_QUERY_PARAM_MAP[this.messageName],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const users = Array.from(userCells).map((userCell) =>
|
||||||
|
this.extractUserData(userCell),
|
||||||
|
)
|
||||||
|
.filter((user) => {
|
||||||
|
const isNewUser = !this.crawledUsers.has(user.accountName);
|
||||||
|
if (isNewUser) {
|
||||||
|
this.crawledUsers.add(user.accountName);
|
||||||
|
}
|
||||||
|
return isNewUser;
|
||||||
|
});
|
||||||
|
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract performScrollAndCheckEnd(): Promise<boolean>;
|
||||||
|
}
|
@ -1,20 +1,11 @@
|
|||||||
import { MESSAGE_NAMES } from "~lib/constants";
|
import { MESSAGE_NAMES } from "~lib/constants";
|
||||||
import { BSKY_DOMAIN, MESSAGE_NAME_TO_QUERY_PARAM_MAP } from "~lib/constants";
|
import { BSKY_DOMAIN, MESSAGE_NAME_TO_QUERY_PARAM_MAP } from "~lib/constants";
|
||||||
import { wait } from "~lib/utils";
|
import { wait } from "~lib/utils";
|
||||||
import type { CrawledUserInfo, MessageName } from "~types";
|
import { AbstractService } from "./abstractService";
|
||||||
|
import type { CrawledUserInfo } from "~types";
|
||||||
|
|
||||||
export class XService {
|
export class XService extends AbstractService {
|
||||||
// 対象のdomを取得する処理
|
extractUserData(userCell: Element): CrawledUserInfo {
|
||||||
messageName: MessageName;
|
|
||||||
crawledUsers: Set<string>;
|
|
||||||
|
|
||||||
constructor(messageName: string) {
|
|
||||||
// TODO: add type check
|
|
||||||
this.messageName = messageName as MessageName;
|
|
||||||
this.crawledUsers = new Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
private extractUserData(userCell: Element): CrawledUserInfo {
|
|
||||||
const anchors = Array.from(userCell.querySelectorAll("a"));
|
const anchors = Array.from(userCell.querySelectorAll("a"));
|
||||||
const [avatarEl, displayNameEl] = anchors;
|
const [avatarEl, displayNameEl] = anchors;
|
||||||
const accountName = avatarEl?.getAttribute("href")?.replace("/", "");
|
const accountName = avatarEl?.getAttribute("href")?.replace("/", "");
|
||||||
@ -39,25 +30,6 @@ export class XService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getCrawledUsers(): CrawledUserInfo[] {
|
|
||||||
const userCells = Array.from(
|
|
||||||
document.querySelectorAll(
|
|
||||||
MESSAGE_NAME_TO_QUERY_PARAM_MAP[this.messageName],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
const users = userCells
|
|
||||||
.map((userCell) => this.extractUserData(userCell))
|
|
||||||
.filter((user) => !this.crawledUsers.has(user.accountName));
|
|
||||||
|
|
||||||
this.crawledUsers = new Set([
|
|
||||||
...this.crawledUsers,
|
|
||||||
...users.map((user) => user.accountName),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
async performScrollAndCheckEnd(): Promise<boolean> {
|
async performScrollAndCheckEnd(): Promise<boolean> {
|
||||||
const isListMembersPage =
|
const isListMembersPage =
|
||||||
this.messageName === MESSAGE_NAMES.SEARCH_BSKY_USER_ON_LIST_MEMBERS_PAGE;
|
this.messageName === MESSAGE_NAMES.SEARCH_BSKY_USER_ON_LIST_MEMBERS_PAGE;
|
Loading…
x
Reference in New Issue
Block a user