Conversation
* Get basic working * adds rss feeds * added stablewatch founder and stablecoin intern from messaria as approvers on stablecoins feed * fixes to config for grants, sui, and telegram channels (#102) * add query param for selective processing (#103) * adds query param to process * add query param for processing * simplify * add tags * Feat: implement frontend leaderboard (#93) * feat: implement frontend leaderboard * feat: implement a leaderboard in frontend * feat: implemented leaderboard * fix: rebuild implement leaderboard * fix: prettier * fix: prettier * fix: reimplement frontend leaderboard * fix: implement frontend leaderboard * approval rate * sets approval rate and hides curator --------- Co-authored-by: Elliot Braem <elliot@ejlbraem.com> * remove tailwind-scrollbar * added bob to desci feed * Get basic working * set .env.example * nitpicks --------- Co-authored-by: Elliot Braem <elliot@ejlbraem.com> Co-authored-by: codingshot <45281667+codingshot@users.noreply.github.com> Co-authored-by: Elliot Braem <elliot@everything.dev> Co-authored-by: Louis <112561517+louisdevzz@users.noreply.github.com>
* Explore Page - commit-1 * Explore Page - commit-2 * explore page - commit-3 * explore page - commit - 4 * explore page - commit - prettier * explore page responsiveness + code Rabbit Comments * code Rabbit Comments resolved * css updates * css changes 2 * header update + mobile responsive * conflicts resolved * Rebase and changes * Fix fmt
* Explore Page - commit-1 * Explore Page - commit-2 * explore page - commit-3 * explore page - commit - 4 * explore page - commit - prettier * explore page responsiveness + code Rabbit Comments * code Rabbit Comments resolved * css updates * css changes 2 * header update + mobile responsive * conflicts resolved * Rebase and changes * Fix fmt * Header Updates + Web3Auth getUserInfo + Explore Page changes * fmt * coderabbit comments resolved
* Update the FE to have the profile page (header and tabs init) * Move tabs to it's own component * Add stats and top badges to overview * Finish the overview tab * Update overview page and init content page * feat(profile-page): add Content and My Feed tags * feat(profile-page): finish profile page static UI * refactor: fmt
* Curate Engine Step 1 * content-progress-configuration step-1 * Curation Settings Part 2 and 3 * CodeRabbit Comments Resolved + Mobile Responsive * Responsiveness: empty State, JSON check --------- Co-authored-by: Elliot Braem <elliot@everything.dev>
* Submissions Page + Feed Page + Mobile Responsiveness * fixes * craete-feed authenticated user condition * fmt * remove sqlite --------- Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
* feat: Add connect button to feed page * fix: recommit * added back to stablecoins feed since stablewatch forked their own * fix packages, update pg, and ignore cloudflare sockets * fmt --------- Co-authored-by: ethnclark <ethanclark1310@gmail.com> Co-authored-by: codingshot <45281667+codingshot@users.noreply.github.com> Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
This reverts commit cd12908.
* fix: Sort By Oldest * fix: Sort By Oldest * fix: Fix RecentSubmissions Sort Order Update * fix: All feed should be hidden, remove double title --------- Co-authored-by: vohuunhan1310@gmail.com <ethanclark1310@gmail.com>
* UI fixes * fmt --------- Co-authored-by: Elliot Braem <elliot@everything.dev>
* fix: Leaderboard improvements * fix: fmt * reorganize * remove unused * rename * clean up * fmt --------- Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/api/src/services/moderation.service.ts (1)
136-136: Replace hardcoded platform string with enum or constant.The hardcoded
"twitter"string is used throughout the file, creating maintenance overhead and potential for typos.Extract this to a constant or use a
SubmissionPlatformenum:+const SUBMISSION_PLATFORM = "twitter" as const; - const submissionPlatform = "twitter"; + const submissionPlatform = SUBMISSION_PLATFORM;This same pattern appears at lines 393 and should be consistently addressed.
🧹 Nitpick comments (3)
apps/api/src/services/moderation.service.ts (3)
173-197: Consider extracting permission check logic for better maintainability.While the duplication mentioned in past reviews has been partially addressed, the permission checking logic is still complex and could benefit from extraction.
Consider extracting the authorization logic:
+ private async checkModerationAuthorization( + actingAccountId: string, + submissionPlatform: string, + configuredApproverPlatformIds: string[] + ): Promise<{ isAuthorized: boolean; adminIdForHistory: string }> { + // Check if super admin first + if (isSuperAdmin(actingAccountId, this.superAdminAccounts)) { + return { isAuthorized: true, adminIdForHistory: actingAccountId }; + } + + // Check against configured platform-specific approvers + for (const configuredApproverId of configuredApproverPlatformIds) { + if (await this.canModerateSubmission(actingAccountId, submissionPlatform, configuredApproverId)) { + return { isAuthorized: true, adminIdForHistory: configuredApproverId }; + } + } + + return { isAuthorized: false, adminIdForHistory: actingAccountId }; + } - let isAuthorized = false; - let adminIdForHistory = actingAccountId; // Default to NEAR ID (for super admins or if no specific platform match is made but still authorized) - - // Check if super admin first - if (isSuperAdmin(actingAccountId, this.superAdminAccounts)) { - isAuthorized = true; - // adminIdForHistory remains actingAccountId (NEAR ID) for super admin actions - } else { - // If not super admin, check against configured platform-specific approvers - for (const configuredApproverId of configuredApproverPlatformIds) { - // configuredApproverId is a platform username like "twitterUser123" - // canModerateSubmission checks if actingAccountId (NEAR) is linked to this configuredApproverId (platform username) - if ( - await this.canModerateSubmission( - actingAccountId, - submissionPlatform, - configuredApproverId, - ) - ) { - isAuthorized = true; - adminIdForHistory = configuredApproverId; // Log the platform-specific ID that granted permission - break; - } - } - } + const { isAuthorized, adminIdForHistory } = await this.checkModerationAuthorization( + actingAccountId, + submissionPlatform, + configuredApproverPlatformIds + );
284-294: Improve error handling consistency in updateStatusAndProcess.The error handling improvements look good, but consider the error message consistency and logging patterns.
The error handling is well-structured. Consider making the error message more descriptive:
- throw new NotFoundError( - `Feed configuration for feed ${feedEntry.feedId}`, - ); + throw new NotFoundError( + "Feed configuration", + `feed ${feedEntry.feedId}` + );
409-431: Potential performance concern with sequential API calls.The method loops through configured approvers and makes sequential calls to
canModerateSubmission, each potentially calling the Crosspost API.Consider optimizing by fetching connected accounts once:
+ private async getConnectedAccountsForUser(actingAccountId: string): Promise<ConnectedAccountsResponse['accounts'] | null> { + try { + const crosspost = new CrosspostClient(); + crosspost.setAccountHeader(actingAccountId); + const response = await crosspost.auth.getConnectedAccounts(); + return response.success ? response.data?.accounts || null : null; + } catch (error) { + this.logger.error({ actingAccountId, error }, "Failed to fetch connected accounts"); + return null; + } + }Then modify the permission check to use the cached connected accounts instead of making repeated API calls.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/api/src/services/moderation.service.ts(7 hunks)apps/app/src/components/FeedItem.tsx(8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/app/src/components/FeedItem.tsx
🔇 Additional comments (1)
apps/api/src/services/moderation.service.ts (1)
446-474: Excellent addition of schema validation for API responses.The addition of
ModerationActionSchema.parse()validation ensures data integrity and type safety for API responses.This approach prevents potential runtime errors from malformed data and provides better error messages when validation fails.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
apps/api/src/services/moderation.service.ts (3)
54-110: Address performance and error handling concerns from previous review.This method still creates a new
CrosspostClientinstance on every permission check and has the error handling issues previously identified.The concerns raised in the previous review about optimizing CrosspostClient usage and improving error handling remain valid and should be addressed.
144-221: Extract duplicated authorization logic and eliminate magic strings.This permission checking code duplicates the same authorization pattern found in
canModerateSubmissionandcheckUserFeedModerationPermission. The hardcoded"twitter"string should also be replaced with a constant.As mentioned in the previous review, consolidate the duplicated permission logic by extracting a single private helper method that all public methods can delegate to. Also replace the magic string with a proper constant or enum.
+ private static readonly DEFAULT_SUBMISSION_PLATFORM = "twitter"; + + private async _isAuthorizedModerator( + actingAccountId: string, + feedId: string, + platform: string = ModerationService.DEFAULT_SUBMISSION_PLATFORM + ): Promise<{ isAuthorized: boolean; adminIdForHistory: string }> { + // Consolidated authorization logic here + } - const submissionPlatform = "twitter"; + const submissionPlatform = ModerationService.DEFAULT_SUBMISSION_PLATFORM;
368-455: Consolidate the duplicated permission checking logic.This method re-implements the same authorization logic as
canModerateSubmissionand the permission checks increateModerationAction, violating the DRY principle.Extract the repeated super admin check and platform approver validation into a shared private helper method as mentioned in the previous review. This will reduce maintenance overhead and prevent future divergence.
🧹 Nitpick comments (1)
apps/api/src/services/moderation.service.ts (1)
1-1: Fix Prettier formatting issues.The pipeline indicates formatting issues that need to be resolved.
Run the following command to fix the formatting:
npx prettier --write apps/api/src/services/moderation.service.ts
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/api/src/services/moderation.service.ts(7 hunks)apps/app/src/lib/near.ts(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
apps/api/src/services/moderation.service.ts
[warning] 1-1: Prettier formatting warning: Code style issues found. Run Prettier with --write to fix.
apps/app/src/lib/near.ts
[error] 7-7: Prettier syntax error: ':' expected at line 7. Syntax issue likely due to malformed type annotation or export statement.
🪛 Biome (1.9.4)
apps/app/src/lib/near.ts
[error] 6-7: expected : but instead found export
Remove export
(parse)
[error] 7-7: Shouldn't redeclare 'near'. Consider to delete it or rename it.
'near' is defined here:
(lint/suspicious/noRedeclare)
🔇 Additional comments (3)
apps/api/src/services/moderation.service.ts (3)
1-45: LGTM on imports and constructor changes.The new imports for Crosspost SDK, error types, and auth utilities are well-organized and support the enhanced moderation functionality. The constructor update to include
superAdminAccountsis appropriate.
288-360: Well-implemented error handling and transaction management.The enhanced error handling with custom error types and comprehensive logging in this helper method is excellent. The transaction-based approach ensures data consistency.
458-486: Good use of schema validation in data retrieval methods.The new data retrieval methods properly use
ModerationActionSchema.parse()for validation, ensuring type safety and data consistency.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
apps/api/src/services/moderation.service.ts (2)
47-69: Consolidate duplicated authorization logic.The permission checking logic is duplicated between
checkModerationAuthorization,canModerateSubmission, andcheckUserFeedModerationPermission. This increases maintenance overhead and risks divergence.Extract the common authorization logic into a private helper method to eliminate duplication and ensure consistency across all permission checks.
Also applies to: 356-443
480-480: Optimize CrosspostClient instantiation.Creating a new
CrosspostClientinstance for each permission check impacts performance and doesn't leverage connection pooling or caching.Consider initializing a single
CrosspostClientinstance as a class property to reuse across multiple calls, or implement a caching mechanism for connected accounts.
🧹 Nitpick comments (2)
apps/api/src/services/config.service.ts (2)
15-15: Remove unnecessary constructor.The constructor is empty and unnecessary. TypeScript will automatically generate a default constructor.
- public constructor() {}
10-12: Simplify Boolean conversion logic.The
Boolean()wrapper is redundant since the|| falsealready handles falsy values correctly.export const featureFlags = { - enableDistribution: Boolean(process.env.ENABLE_DISTRIBUTION) || false, + enableDistribution: !!process.env.ENABLE_DISTRIBUTION, };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/api/src/services/config.service.ts(1 hunks)apps/api/src/services/distribution.service.ts(5 hunks)apps/api/src/services/moderation.service.ts(7 hunks)apps/api/src/utils/service-provider.ts(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/api/src/utils/service-provider.ts
🧰 Additional context used
🪛 Biome (1.9.4)
apps/api/src/services/config.service.ts
[error] 15-15: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
🔇 Additional comments (4)
apps/api/src/services/distribution.service.ts (2)
5-5: LGTM! Clean refactoring to use dynamic feature flags.The dependency injection of
ConfigServiceand replacement of staticisStagingchecks with dynamic feature flag evaluation is well-implemented. This provides better runtime control and flexibility.Also applies to: 16-16, 43-43
58-61: Good addition of feature flag state to error context.Including the current feature flag state in error details will help with debugging and monitoring. This provides valuable context for understanding the system state when errors occur.
Also applies to: 83-86
apps/api/src/services/moderation.service.ts (2)
122-270: Approve comprehensive permission checking implementation.The
createModerationActionmethod implements robust authorization checks with proper error handling and transaction management. The integration with feed configuration and platform-specific approvers is well-designed.
446-452: Good addition of schema validation for API responses.The use of
ModerationActionSchema.parse()for validating moderation data ensures type safety and runtime validation, which is a best practice for API boundaries.Also applies to: 454-462, 467-474
| feedEntry, | ||
| submissionStatusZodEnum.Enum.approved, | ||
| tx, | ||
| const submissionPlatform = "twitter"; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Replace hardcoded platform string with enum.
The hardcoded "twitter" string is used throughout the codebase, creating a maintenance risk and potential for typos.
+enum SubmissionPlatform {
+ TWITTER = "twitter"
+}
-const submissionPlatform = "twitter";
+const submissionPlatform = SubmissionPlatform.TWITTER;Also applies to: 393-393
🤖 Prompt for AI Agents
In apps/api/src/services/moderation.service.ts at lines 154 and 393, replace the
hardcoded string "twitter" with the appropriate enum value representing the
Twitter platform. Identify the enum used for platforms in the codebase and
substitute the string with that enum constant to ensure consistency and reduce
maintenance risks.
| if (response.success && response.data?.accounts) { | ||
| return response.data.accounts; | ||
| } | ||
| this.logger.warn( | ||
| { actingAccountId, error: response.errors }, // Assuming 'errors' is the correct property | ||
| "Failed to fetch connected accounts from Crosspost API or no accounts found.", | ||
| ); | ||
| return null; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Improve error handling for Crosspost API calls.
The current error handling assumes response.errors exists but should handle cases where the response structure might be different.
if (response.success && response.data?.accounts) {
return response.data.accounts;
}
this.logger.warn(
- { actingAccountId, error: response.errors }, // Assuming 'errors' is the correct property
+ { actingAccountId, error: response.success ? 'No accounts found' : response.error },
"Failed to fetch connected accounts from Crosspost API or no accounts found.",
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (response.success && response.data?.accounts) { | |
| return response.data.accounts; | |
| } | |
| this.logger.warn( | |
| { actingAccountId, error: response.errors }, // Assuming 'errors' is the correct property | |
| "Failed to fetch connected accounts from Crosspost API or no accounts found.", | |
| ); | |
| return null; | |
| if (response.success && response.data?.accounts) { | |
| return response.data.accounts; | |
| } | |
| this.logger.warn( | |
| { actingAccountId, error: response.success ? 'No accounts found' : response.error }, | |
| "Failed to fetch connected accounts from Crosspost API or no accounts found.", | |
| ); | |
| return null; |
🤖 Prompt for AI Agents
In apps/api/src/services/moderation.service.ts around lines 484 to 491, improve
error handling by checking if the response contains an errors property before
logging it. If errors are not present, log a generic error message or the entire
response to ensure all failure cases are captured. Update the logger.warn call
to handle different response structures gracefully without assuming the presence
of response.errors.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Removals
Chores