mirror of
https://github.com/snachodog/tok-to-insta-follower-bridge.git
synced 2025-04-10 14:11:22 -06:00
refactor: migrate list search to x's service
This commit is contained in:
parent
4d917f0e98
commit
4229a39aae
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sky-follower-bridge",
|
"name": "sky-follower-bridge",
|
||||||
"version": "1.3.0",
|
"version": "1.4.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sky-follower-bridge",
|
"name": "sky-follower-bridge",
|
||||||
"version": "1.3.0",
|
"version": "1.4.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atproto/api": "^0.13.12",
|
"@atproto/api": "^0.13.12",
|
||||||
"@changesets/cli": "^2.27.1",
|
"@changesets/cli": "^2.27.1",
|
||||||
|
@ -110,3 +110,5 @@ export const BSKY_DOMAIN =
|
|||||||
export const BSKY_PROFILE_LABEL = {
|
export const BSKY_PROFILE_LABEL = {
|
||||||
IMPERSONATION: "impersonation",
|
IMPERSONATION: "impersonation",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const DEFAULT_LIST_NAME = "Imported List from X";
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import type { CrawledUserInfo } from "~types";
|
|
||||||
import { BSKY_DOMAIN } from "./constants";
|
|
||||||
|
|
||||||
export const getUserCells = ({
|
export const getUserCells = ({
|
||||||
queryParam,
|
queryParam,
|
||||||
filterInsertedElement,
|
filterInsertedElement,
|
||||||
@ -22,27 +19,12 @@ export const getUserCells = ({
|
|||||||
return Array.from(userCells);
|
return Array.from(userCells);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const extractUserData = (userCell: Element): CrawledUserInfo => {
|
export const scrapeListNameFromPage = (): string => {
|
||||||
const anchors = Array.from(userCell.querySelectorAll("a"));
|
const listNameElement = document.querySelector(
|
||||||
const [avatarEl, displayNameEl] = anchors;
|
'div[aria-label="Timeline: List"] span',
|
||||||
const accountName = avatarEl?.getAttribute("href")?.replace("/", "");
|
);
|
||||||
const accountNameRemoveUnderscore = accountName.replaceAll("_", ""); // bsky does not allow underscores in handle, so remove them.
|
if (listNameElement) {
|
||||||
const accountNameReplaceUnderscore = accountName.replaceAll("_", "-");
|
return listNameElement.textContent.trim();
|
||||||
const displayName = displayNameEl?.textContent;
|
}
|
||||||
const bskyHandle =
|
return "Imported List from X";
|
||||||
userCell.textContent?.match(
|
|
||||||
new RegExp(`([^/\\s]+\\.${BSKY_DOMAIN})`),
|
|
||||||
)?.[1] ??
|
|
||||||
userCell.textContent
|
|
||||||
?.match(/bsky\.app\/profile\/([^/\s]+)…?/)?.[1]
|
|
||||||
?.replace("…", "") ??
|
|
||||||
"";
|
|
||||||
|
|
||||||
return {
|
|
||||||
accountName,
|
|
||||||
displayName,
|
|
||||||
accountNameRemoveUnderscore,
|
|
||||||
accountNameReplaceUnderscore,
|
|
||||||
bskyHandle,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ import { BskyServiceWorkerClient } from "~lib/bskyServiceWorkerClient";
|
|||||||
import {
|
import {
|
||||||
ACTION_MODE,
|
ACTION_MODE,
|
||||||
BSKY_USER_MATCH_TYPE,
|
BSKY_USER_MATCH_TYPE,
|
||||||
|
DEFAULT_LIST_NAME,
|
||||||
MESSAGE_NAME_TO_ACTION_MODE_MAP,
|
MESSAGE_NAME_TO_ACTION_MODE_MAP,
|
||||||
STORAGE_KEYS,
|
STORAGE_KEYS,
|
||||||
} from "~lib/constants";
|
} from "~lib/constants";
|
||||||
@ -21,13 +22,6 @@ export const useBskyUserManager = () => {
|
|||||||
},
|
},
|
||||||
(v) => (v === undefined ? [] : v),
|
(v) => (v === undefined ? [] : v),
|
||||||
);
|
);
|
||||||
const [listName, setListName] = React.useState<string>("");
|
|
||||||
React.useEffect(() => {
|
|
||||||
chrome.storage.local.get("listName", (result) => {
|
|
||||||
const name = result.listName || "Imported List from X";
|
|
||||||
setListName(name);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const bskyClient = React.useRef<BskyServiceWorkerClient | null>(null);
|
const bskyClient = React.useRef<BskyServiceWorkerClient | null>(null);
|
||||||
const [actionMode, setActionMode] = React.useState<
|
const [actionMode, setActionMode] = React.useState<
|
||||||
@ -128,8 +122,12 @@ export const useBskyUserManager = () => {
|
|||||||
// Import list
|
// Import list
|
||||||
const importList = React.useCallback(async () => {
|
const importList = React.useCallback(async () => {
|
||||||
if (!bskyClient.current) return;
|
if (!bskyClient.current) return;
|
||||||
|
const storage = new Storage({
|
||||||
|
area: "local",
|
||||||
|
});
|
||||||
|
const listName = await storage.get(STORAGE_KEYS.LIST_NAME);
|
||||||
const listUri = await bskyClient.current.createListAndAddUsers({
|
const listUri = await bskyClient.current.createListAndAddUsers({
|
||||||
name: listName,
|
name: listName || DEFAULT_LIST_NAME,
|
||||||
description: "List imported via Sky Follower Bridge",
|
description: "List imported via Sky Follower Bridge",
|
||||||
userDids: filteredUsers.map((user) => user.did),
|
userDids: filteredUsers.map((user) => user.did),
|
||||||
});
|
});
|
||||||
@ -137,7 +135,7 @@ export const useBskyUserManager = () => {
|
|||||||
// const myProfile = await bskyClient.current.getMyProfile();
|
// const myProfile = await bskyClient.current.getMyProfile();
|
||||||
// return `https://bsky.app/profile/${myProfile.handle}/lists/${listUri}`;
|
// return `https://bsky.app/profile/${myProfile.handle}/lists/${listUri}`;
|
||||||
return "https://bsky.app/lists";
|
return "https://bsky.app/lists";
|
||||||
}, [filteredUsers, listName]);
|
}, [filteredUsers]);
|
||||||
|
|
||||||
// Follow All
|
// Follow All
|
||||||
const followAll = React.useCallback(async () => {
|
const followAll = React.useCallback(async () => {
|
||||||
@ -247,7 +245,6 @@ export const useBskyUserManager = () => {
|
|||||||
return {
|
return {
|
||||||
handleClickAction,
|
handleClickAction,
|
||||||
users,
|
users,
|
||||||
listName,
|
|
||||||
actionMode,
|
actionMode,
|
||||||
matchTypeFilter,
|
matchTypeFilter,
|
||||||
changeMatchTypeFilter,
|
changeMatchTypeFilter,
|
||||||
|
@ -10,7 +10,7 @@ import type { AbstractService } from "~lib/services/abstractService";
|
|||||||
import { XService } from "~lib/services/xService";
|
import { XService } from "~lib/services/xService";
|
||||||
import type { BskyUser, CrawledUserInfo, MessageName } from "~types";
|
import type { BskyUser, CrawledUserInfo, MessageName } from "~types";
|
||||||
|
|
||||||
const getService = (messageName: string): AbstractService => {
|
const getService = (messageName: MessageName): AbstractService => {
|
||||||
return match(messageName)
|
return match(messageName)
|
||||||
.with(
|
.with(
|
||||||
P.when((name) =>
|
P.when((name) =>
|
||||||
@ -25,16 +25,6 @@ const getService = (messageName: string): AbstractService => {
|
|||||||
.otherwise(() => new XService(messageName));
|
.otherwise(() => new XService(messageName));
|
||||||
};
|
};
|
||||||
|
|
||||||
const scrapeListNameFromPage = (): string => {
|
|
||||||
const listNameElement = document.querySelector(
|
|
||||||
'div[aria-label="Timeline: List"] span',
|
|
||||||
);
|
|
||||||
if (listNameElement) {
|
|
||||||
return listNameElement.textContent.trim();
|
|
||||||
}
|
|
||||||
return "Imported List from X";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useRetrieveBskyUsers = () => {
|
export const useRetrieveBskyUsers = () => {
|
||||||
const bskyClient = React.useRef<BskyServiceWorkerClient | null>(null);
|
const bskyClient = React.useRef<BskyServiceWorkerClient | null>(null);
|
||||||
const [users, setUsers] = useStorage<BskyUser[]>(
|
const [users, setUsers] = useStorage<BskyUser[]>(
|
||||||
@ -46,15 +36,6 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
},
|
},
|
||||||
(v) => (v === undefined ? [] : v),
|
(v) => (v === undefined ? [] : v),
|
||||||
);
|
);
|
||||||
const [listName, setListName] = useStorage<string>(
|
|
||||||
{
|
|
||||||
key: STORAGE_KEYS.LIST_NAME,
|
|
||||||
instance: new Storage({
|
|
||||||
area: "local",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
(v) => (v === undefined ? "" : v),
|
|
||||||
);
|
|
||||||
const [loading, setLoading] = React.useState(true);
|
const [loading, setLoading] = React.useState(true);
|
||||||
const [errorMessage, setErrorMessage] = React.useState("");
|
const [errorMessage, setErrorMessage] = React.useState("");
|
||||||
const [isBottomReached, setIsBottomReached] = React.useState(false);
|
const [isBottomReached, setIsBottomReached] = React.useState(false);
|
||||||
@ -104,7 +85,7 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
|
|
||||||
const abortControllerRef = React.useRef<AbortController | null>(null);
|
const abortControllerRef = React.useRef<AbortController | null>(null);
|
||||||
const startRetrieveLoop = React.useCallback(
|
const startRetrieveLoop = React.useCallback(
|
||||||
async (messageName: string) => {
|
async (messageName: MessageName) => {
|
||||||
abortControllerRef.current = new AbortController();
|
abortControllerRef.current = new AbortController();
|
||||||
const signal = abortControllerRef.current.signal;
|
const signal = abortControllerRef.current.signal;
|
||||||
|
|
||||||
@ -139,13 +120,6 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
[retrieveBskyUsers, isBottomReached],
|
[retrieveBskyUsers, isBottomReached],
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
chrome.storage.local.set({
|
|
||||||
users: JSON.stringify(users),
|
|
||||||
listName: listName,
|
|
||||||
});
|
|
||||||
}, [users, listName]);
|
|
||||||
|
|
||||||
const stopRetrieveLoop = React.useCallback(() => {
|
const stopRetrieveLoop = React.useCallback(() => {
|
||||||
if (abortControllerRef.current) {
|
if (abortControllerRef.current) {
|
||||||
abortControllerRef.current.abort();
|
abortControllerRef.current.abort();
|
||||||
@ -169,8 +143,6 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
|
|
||||||
bskyClient.current = new BskyServiceWorkerClient(session);
|
bskyClient.current = new BskyServiceWorkerClient(session);
|
||||||
|
|
||||||
setListName(scrapeListNameFromPage());
|
|
||||||
|
|
||||||
startRetrieveLoop(messageName).catch((e) => {
|
startRetrieveLoop(messageName).catch((e) => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
setErrorMessage(e.message);
|
setErrorMessage(e.message);
|
||||||
@ -201,7 +173,6 @@ export const useRetrieveBskyUsers = () => {
|
|||||||
return {
|
return {
|
||||||
initialize,
|
initialize,
|
||||||
users,
|
users,
|
||||||
listName,
|
|
||||||
loading,
|
loading,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
isRateLimitError,
|
isRateLimitError,
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
|
import { Storage } from "@plasmohq/storage";
|
||||||
import { MESSAGE_NAMES } from "~lib/constants";
|
import { MESSAGE_NAMES } from "~lib/constants";
|
||||||
import { BSKY_DOMAIN } from "~lib/constants";
|
import { BSKY_DOMAIN } from "~lib/constants";
|
||||||
|
import { STORAGE_KEYS } from "~lib/constants";
|
||||||
|
import { scrapeListNameFromPage } from "~lib/domHelpers";
|
||||||
import { wait } from "~lib/utils";
|
import { wait } from "~lib/utils";
|
||||||
import type { CrawledUserInfo } from "~types";
|
import type { CrawledUserInfo, MessageName } from "~types";
|
||||||
import { AbstractService } from "./abstractService";
|
import { AbstractService } from "./abstractService";
|
||||||
|
|
||||||
export class XService extends AbstractService {
|
export class XService extends AbstractService {
|
||||||
|
constructor(messageName: MessageName) {
|
||||||
|
// Set the list name in the storage if it's a list members page
|
||||||
|
if (messageName === MESSAGE_NAMES.SEARCH_BSKY_USER_ON_LIST_MEMBERS_PAGE) {
|
||||||
|
const listName = scrapeListNameFromPage();
|
||||||
|
new Storage({
|
||||||
|
area: "local",
|
||||||
|
}).set(STORAGE_KEYS.LIST_NAME, listName);
|
||||||
|
}
|
||||||
|
super(messageName);
|
||||||
|
}
|
||||||
|
|
||||||
extractUserData(userCell: Element): CrawledUserInfo {
|
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user