Skip to content

Conversation

@maksPodstawski
Copy link
Member

@maksPodstawski maksPodstawski commented Aug 18, 2025

Description

Briefly explain what this PR does. Is it a bug fix, new feature, or a refactor?

Testing

Select all the environments you tested this PR with:

  • BetterTTV (BTTV)
  • FrankerFaceZ (FFZ)
  • 7TV
  • Native Twitch

Please describe how you tested this change in the selected environments.

Related Issues

If this PR addresses an issue, link it here (e.g., Closes #123).

Description by Callstackai

This PR introduces a new feature that allows sharing followed channels across platforms, specifically between Twitch and Kick. It includes the implementation of follow synchronization and settings for enabling/disabling this feature.

Diagrams of code changes
sequenceDiagram
    participant User
    participant Platform
    participant SharedFollowsModule
    participant FollowSyncer
    participant CommonDataService
    participant WorkerService
    participant CommonDatabase

    User->>Platform: Enable follow sharing
    Platform->>SharedFollowsModule: Initialize module
    SharedFollowsModule->>FollowSyncer: Start sync timer
    
    loop Every few minutes
        FollowSyncer->>Platform: Get followed channels
        Platform-->>FollowSyncer: Return channel list
        FollowSyncer->>CommonDataService: Update shared follows
        CommonDataService->>WorkerService: Send update request
        WorkerService->>CommonDatabase: Store follows data
        CommonDatabase-->>WorkerService: Confirm storage
        WorkerService-->>CommonDataService: Return success
    end

    Note over Platform,CommonDatabase: Follows are now shared between platforms
    
    User->>Platform: View follows from other platform
    Platform->>CommonDataService: Request shared follows
    CommonDataService->>WorkerService: Get common data
    WorkerService->>CommonDatabase: Retrieve follows
    CommonDatabase-->>WorkerService: Return follows data
    WorkerService-->>CommonDataService: Return data
    CommonDataService-->>Platform: Return follows list
    Platform-->>User: Display combined follows
Loading
Files Changed
FileSummary
src/platforms/kick/kick.constants.tsAdded new settings for sharing and showing follows from other platforms.
src/platforms/kick/kick.module.tsUpdated the constructor to include CommonDataService.
src/platforms/kick/kick.platform.tsImported and initialized SharedFollowsModule.
src/platforms/kick/modules/settings/settings.module.tsxAdded new settings definitions for sharing and showing follows.
src/platforms/kick/modules/shared-follows/kick.follow-syncer.tsImplemented follow synchronization logic for Kick.
src/platforms/kick/modules/shared-follows/shared-follows.module.tsxCreated SharedFollowsModule to manage follow synchronization.
src/platforms/twitch/twitch.constants.tsAdded new settings for sharing and showing follows from other platforms.
src/platforms/twitch/twitch.module.tsUpdated the constructor to include CommonDataService.
src/platforms/twitch/modules/settings/settings.module.tsxAdded new settings definitions for sharing and showing follows.
src/platforms/twitch/modules/shared-follows/shared-follows.module.tsxCreated SharedFollowsModule to manage follow synchronization.

Copy link
Contributor

@callstackai callstackai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key Issues

The code lacks proper error handling, with empty catch blocks and missing try-catch wrappers for async operations, risking unhandled errors and application crashes. Unsafe type assertions and null handling could lead to runtime errors if the response structure is unexpected. There is a logic error in data labeling, where Twitch data is incorrectly marked as Kick data, potentially causing data misinterpretation.

try {
const kick = await this.commonUtils().getAssetFile(this.workerService(), "brands/kick.svg");
this.platformIcons = { kick };
} catch {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Possible Bug
The empty catch block silently ignores any errors that occur while loading platform icons. This makes it difficult to diagnose issues if the icon fails to load. The error should be logged to help with debugging.

Suggested change
} catch {}
} catch (error) { this.logger.warn('Failed to load Kick platform icon', error); }

Comment on lines 39 to 40
await this.loadStreamersFromCommon();
await this.refreshStatuses();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Possible Bug
The calls to loadStreamersFromCommon() and refreshStatuses() are not wrapped in try-catch blocks. If these async operations fail, they will result in unhandled promise rejections that could crash the application.

Suggested change
await this.loadStreamersFromCommon();
await this.refreshStatuses();
try {
await this.loadStreamersFromCommon();
await this.refreshStatuses();
} catch (error) {
this.logger.error('Failed to initialize Kick streamers module', error);
}

private async loadStreamersFromCommon(): Promise<void> {
try {
const res = await this.workerService().send("getCommon", { platform: "twitch", key: "kickStreamers" });
const value = (res && (res as { value: unknown | null }).value) as unknown;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Possible Bug
The type assertion and null handling for the response from workerService().send() is unsafe. The code assumes the response will have a value property without proper validation. If res is null or doesn't match the expected structure, the type assertion could cause runtime errors.

Suggested change
const value = (res && (res as { value: unknown | null }).value) as unknown;
const value = res?.value ?? null;

Comment on lines 24 to 28
await this.workerService().send("setCommon", {
platform: "kick",
key: COMMON_KEYS.kick.twitchStreamers,
value: twitchFollowList,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Possible Bug
The code is storing Twitch follow list data but setting the platform as 'kick'. This appears to be a logic error as the data source is from Twitch but is being labeled as Kick data.

Suggested change
await this.workerService().send("setCommon", {
platform: "kick",
key: COMMON_KEYS.kick.twitchStreamers,
value: twitchFollowList,
});
await this.workerService().send("setCommon", {
platform: "twitch",
key: COMMON_KEYS.kick.twitchStreamers,
value: twitchFollowList,
});

headers: { Authorization: authorization },
credentials: "include",
});
if (!res.ok) break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Possible Bug
The code breaks the loop on any non-OK response (!res.ok) without checking the specific error. This could mask important API errors like rate limiting or auth issues, leading to incomplete data collection.

Suggested change
if (!res.ok) break;
if (!res.ok) throw new Error(`API request failed with status ${res.status}`);

@igorovh igorovh changed the title Feat/kick streamers feat/enhanced-follow-list Aug 18, 2025
Copy link
Contributor

@callstackai callstackai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key Issues

The PR review highlights critical issues including the failure to create necessary database indexes during version upgrades, leading to an invalid database state; unchecked access to potentially undefined properties causing runtime errors; and a performance regression due to sequential data fetching instead of concurrent requests.

Co-authored-by: callstackai[bot] <186726322+callstackai[bot]@users.noreply.github.com>
Copy link
Contributor

@callstackai callstackai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key Issues

The error handling logic is flawed as it does not differentiate between common being null or undefined and common.data being absent, potentially leading to misleading error messages.

igorovh and others added 2 commits August 23, 2025 20:17
Co-authored-by: callstackai[bot] <186726322+callstackai[bot]@users.noreply.github.com>
@igorovh igorovh changed the base branch from master to dev October 27, 2025 22:21
@igorovh igorovh changed the base branch from dev to master October 29, 2025 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants