Skip to content

Commit

Permalink
feat: support watched profiles following list has new activity can be…
Browse files Browse the repository at this point in the history
… call snap's notify
  • Loading branch information
dmoosocool committed Oct 31, 2023
1 parent 4135399 commit 01363ba
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 19 deletions.
2 changes: 1 addition & 1 deletion packages/snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/NaturalSelectionLabs/RSS3-MetaMask-Snap.git"
},
"source": {
"shasum": "l+dcwmstbQR/2SVBE97+stCQ/PxlzKW1aR81AQmQtVY=",
"shasum": "LzxqoM9rAkicT97UYNE2inSY4KoE/532tFOShDZgR5U=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
24 changes: 20 additions & 4 deletions packages/snap/src/crossbell.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isValidWalletAddress } from './utils';
import { getMultiple } from './fetch';
import { diffMonitor, getMultiple } from './fetch';
import { SocialMonitor } from './state';
import { Platform, TProfile, TRelationChainResult } from '.';

const API = `https://indexer.crossbell.io/v1`;
Expand Down Expand Up @@ -136,8 +137,14 @@ async function getCharacterId(handle: string) {
* Retrieves the followers for the given character ID from the Crossbell API.
*
* @param id - The character ID to retrieve the followers for.
* @param olderMonitor - The older monitor.
* @param handle - The handle.
*/
export async function getFollowingByCharacterId(id: string) {
export async function getFollowingByCharacterId(
id: string,
olderMonitor: SocialMonitor,
handle: string,
) {
const following: TProfile[] = [];
let hasNextPage = true;
let cursor: string | undefined;
Expand Down Expand Up @@ -184,10 +191,17 @@ export async function getFollowingByCharacterId(id: string) {
});

if (findOut) {
const lastActivities = diffMonitor(
olderMonitor,
findOut.activities,
handle,
item.handle,
);

return {
...item,
activities: findOut.activities,
lastActivities: findOut.oldActivities,
lastActivities,
};
}
}
Expand Down Expand Up @@ -217,11 +231,13 @@ export function format(profiles: TCSBProfile[]): TProfile[] {
* Retrieves the relation chain for the given handle from the Crossbell API.
*
* @param handle - The handle to retrieve the relation chain for.
* @param oldMonitor - The old monitor.
* @param fetchMethod - The method to use to fetch the following.
* @returns The relation chain for the given handle.
*/
export async function handler(
handle: string,
oldMonitor: SocialMonitor,
fetchMethod: typeof getFollowingByCharacterId = getFollowingByCharacterId,
): Promise<TRelationChainResult> {
// 1. Get owner profile
Expand Down Expand Up @@ -265,7 +281,7 @@ export async function handler(
}

// 2. Get following
const following = await fetchMethod(data.characterId);
const following = await fetchMethod(data.characterId, oldMonitor, handle);

// 3. Return result
return {
Expand Down
28 changes: 23 additions & 5 deletions packages/snap/src/farcaster.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getMultiple } from './fetch';
import { diffMonitor, getMultiple } from './fetch';
import { SocialMonitor } from './state';
import { Platform, TProfile, TRelationChainResult } from '.';

const API = 'https://api.warpcast.com/v2';
Expand Down Expand Up @@ -142,9 +143,15 @@ export async function format(data: TFarcasterUser[]): Promise<TProfile[]> {
* Returns the following profiles for a given Farcaster ID.
*
* @param fid - The Farcaster ID to get the following profiles for.
* @param olderMonitor - The older monitor.
* @param handle - The handle.
* @returns An array of TProfile objects representing the following profiles.
*/
export async function getFollowingByFid(fid: number) {
export async function getFollowingByFid(
fid: number,
olderMonitor: SocialMonitor,
handle: string,
) {
let cursor: string | undefined;
let hasNextPage = true;
const following: TProfile[] = [];
Expand Down Expand Up @@ -179,10 +186,17 @@ export async function getFollowingByFid(fid: number) {
});

if (findOut) {
const lastActivities = diffMonitor(
olderMonitor,
findOut.activities,
handle,
item.handle,
);

return {
...item,
activities: findOut.activities,
lastActivities: findOut.oldActivities,
lastActivities,
};
}
}
Expand All @@ -195,9 +209,13 @@ export async function getFollowingByFid(fid: number) {
* Returns the relation chain for a given Farcaster handle.
*
* @param handle - The Farcaster handle to get the relation chain for.
* @param olderMonitor - The older monitor.
* @returns The relation chain for the given Farcaster handle.
*/
export async function handler(handle: string): Promise<TRelationChainResult> {
export async function handler(
handle: string,
olderMonitor: SocialMonitor,
): Promise<TRelationChainResult> {
const owner = await getOwnerProfileByUsername(handle);
if (!owner.fid) {
return {
Expand All @@ -211,7 +229,7 @@ export async function handler(handle: string): Promise<TRelationChainResult> {
};
}

const following = await getFollowingByFid(owner.fid);
const following = await getFollowingByFid(owner.fid, olderMonitor, handle);
return {
owner: {
handle: owner.handle,
Expand Down
89 changes: 84 additions & 5 deletions packages/snap/src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@rss3/js-sdk';

import { themePlain } from '@rss3/js-sdk/lib/readable/activity/theme';
import { CronActivity } from './state';
import { CronActivity, SocialMonitor } from './state';

export const getSocialActivitiesUrl = (address: string) =>
`https://testnet.rss3.io/data/accounts/${address}/activities?tag=social&direction=out`;
Expand Down Expand Up @@ -98,8 +98,8 @@ export async function getMultiple(addresses: string[]) {

const executeAddresses = filtedAddresses;

// 1 day ago
const timestamp = moment().subtract(1, 'day').unix();
// 1 hour ago
const timestamp = moment().subtract(1, 'hour').unix();
while (hasNextPage) {
const params = {
action_limit: 10,
Expand Down Expand Up @@ -151,13 +151,92 @@ export async function getMultiple(addresses: string[]) {
return {
owner: addr,
activities: groupBy,
oldActivities: [],
};
}
return {
owner: addr,
activities: [],
oldActivities: [],
};
});
}

/**
* Social monitor.
*
* @param olderMonitor - The old monitor.
* @param newer - The newer cron activities.
* @param ownerHandle - The owner handle.
* @param handle - The handle.
* @returns The difference between the cached social activities and the fetched social activities.
*/
export function diffMonitor(
olderMonitor: SocialMonitor,
newer: CronActivity[],
ownerHandle: string,
handle: string,
) {
let lastActivities: CronActivity[] = newer;

const cachedProfiles = olderMonitor.watchedProfiles?.find(
(wProfile) =>
wProfile.owner.handle.toLocaleLowerCase() ===
ownerHandle.toLocaleLowerCase(),
);
if (cachedProfiles) {
const cachedProfilesFollowingProfiles = cachedProfiles.following;
if (cachedProfilesFollowingProfiles) {
const cachedProfilesFollowingProfile =
cachedProfilesFollowingProfiles.find(
(cProfile) =>
cProfile.handle.toLocaleLowerCase() === handle.toLocaleLowerCase(),
);
if (cachedProfilesFollowingProfile) {
const cachedProfilesFollowingProfilesActivities =
cachedProfilesFollowingProfile.activities;

if (cachedProfilesFollowingProfilesActivities !== undefined) {
lastActivities = newer
.map((activity) => {
if (
!cachedProfilesFollowingProfilesActivities.some(
(cacheActivity) => cacheActivity.id === activity.id,
)
) {
return activity;
}
return null;
})
.filter((item) => item !== null) as CronActivity[];
}
}
}
}
return lastActivities;
}

// /**
// * Get the last updated following social activities.
// *
// * @param monitors - The social monitors.
// */
// export function getLastUpdatedFollowingSocialActivities(
// monitors: SocialMonitor[],
// ) {
// const followingSocialActivities: CronActivity[] = [];
// monitors.forEach((monitor) => {
// if (monitor.watchedProfiles) {
// monitor.watchedProfiles.forEach((wProfile) => {
// if (wProfile.following) {
// wProfile.following.forEach((followingProfile) => {
// if (followingProfile.lastActivities) {
// followingSocialActivities.push(
// ...followingProfile.lastActivities,
// );
// }
// });
// }
// });
// }
// });
// return followingSocialActivities;
// }
32 changes: 30 additions & 2 deletions packages/snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => {
const watchedProfiles: TRelationChainResult[] = [];
const promises = handles.map(async (exec) => {
if (exec?.handle) {
const fol = await exec.execute(exec.handle);
const fol = await exec.execute(exec.handle, item);
if (fol) {
watchedProfiles.push(fol);
}
Expand All @@ -470,12 +470,40 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => {
watchedProfiles,
};
});

const monitor = await Promise.all(monitorPromises);
await setState({
...state,
monitor,
});

// notify the latest social activities by the monitor
const content: any[] = [];
monitor.forEach((item) => {
item.watchedProfiles?.forEach((profile) => {
const lastActivities = profile.following?.flatMap(
(follower) =>
follower.lastActivities?.map((activity) => activity.text) ?? [],
);
lastActivities?.length &&
content.push(
heading(
`${profile.owner.handle}'s following has new activities.`,
),
text(lastActivities.join('\n')),
divider(),
);
});
});

if (content.length > 0) {
await snap.request({
method: 'snap_dialog',
params: {
type: DialogType.Alert,
content: panel(content),
},
});
}
return true;
}

Expand Down
15 changes: 13 additions & 2 deletions packages/snap/src/lens.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Client, cacheExchange, fetchExchange, gql } from '@urql/core';
import { isValidWalletAddress } from './utils';
import { getMultiple } from './fetch';
import { diffMonitor, getMultiple } from './fetch';
import { SocialMonitor } from './state';
import { TRelationChainResult, type TProfile, Platform } from '.';

// only need handle, ownedBy and picture.
Expand Down Expand Up @@ -180,12 +181,14 @@ export async function getAddressByHandle(handle: string) {
* Returns an object containing information about a user's relation chain.
*
* @param handle - The user's handle.
* @param olderMonitor - The older monitor.
* @param limit - The pagination limit.
* @param queryMethod - The query method.
* @returns An object containing the user's relation chain information.
*/
export async function handler(
handle: string,
olderMonitor: SocialMonitor,
limit = 20,
queryMethod: typeof query = query,
): Promise<TRelationChainResult> {
Expand Down Expand Up @@ -231,6 +234,7 @@ export async function handler(
.map((item) => item.address)
.filter((addr) => addr !== undefined) as string[];
const fetchedAddresses = await getMultiple(addresses);

const fetchedFollowing = following.map((item) => {
if (item.address !== undefined) {
const findOut = fetchedAddresses.find((addr) => {
Expand All @@ -241,10 +245,17 @@ export async function handler(
});

if (findOut) {
const lastActivities = diffMonitor(
olderMonitor,
findOut.activities,
handle,
item.handle,
);

return {
...item,
activities: findOut.activities,
lastActivities: findOut.oldActivities,
lastActivities,
};
}
}
Expand Down
Loading

0 comments on commit 01363ba

Please sign in to comment.