Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

导出 Following 数据时,如果有 Suspended 用户,会中止,提示 Error: Cannot read properties of undefined (reading 'screen_name') #25

Open
justdn opened this issue May 8, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@justdn
Copy link

justdn commented May 8, 2024

来自 Twitter 的粉丝,非常感谢作者能开发这个工具。

直接导出时卡住,Console 有输出错误。

错误信息如下:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'created_at')
    at VMalzsdyq82vt.columnHelper.accessor.id [as accessorFn] (Twitter Web Exporter.user.js:2764:71)
    at Object.getValue (Twitter Web Exporter.user.js:19:46141)
    at Object.getValue (Twitter Web Exporter.user.js:19:45538)
    at onExport (Twitter Web Exporter.user.js:1299:30)
    at HTMLButtonElement.T (Twitter Web Exporter.user.js:3:4503)

相同界面,分页浏览 Following 数据时出现的错误

错误提示截图:
image
错误文本:

Something went wrong.
Error: Cannot read properties of undefined (reading 'screen_name')

原因分析

原因是 Twitter 返回的数据中,混有 Suspended 用户。

Suspended 用户数据示例如下:

...
                                    },
                                    {
                                        "entryId": "user-1723415153759150080",
                                        "sortIndex": "1788044944628252472",
                                        "content": {
                                            "entryType": "TimelineTimelineItem",
                                            "__typename": "TimelineTimelineItem",
                                            "itemContent": {
                                                "itemType": "TimelineUser",
                                                "__typename": "TimelineUser",
                                                "user_results": {
                                                    "result": {
                                                        "__typename": "UserUnavailable",
                                                        "message": "User is suspended",
                                                        "reason": "Suspended"
                                                    }
                                                },
                                                "userDisplayType": "User"
                                            },
                                            "clientEventInfo": {
                                                "component": "FollowingSgs",
                                                "element": "user"
                                            }
                                        }
                                    },
                                    {
...

处理建议

浏览或导出时可能需要忽略 Suspended 用户数据。

找到问题就发出来了,完全不懂暴力猴工程,接下来可能会尝试修正一下,成功了来 PR 😌

@justdn
Copy link
Author

justdn commented May 8, 2024

在 GPT 的帮助下,修改文件 src/modules/following/api.ts

diff --git a/src/modules/following/api.ts b/src/modules/following/api.ts
index 1e3184a..a7142a8 100644
--- a/src/modules/following/api.ts
+++ b/src/modules/following/api.ts
@@ -31,12 +31,15 @@ export const FollowingInterceptor: Interceptor = (req, res) => {
   }
 
   try {
-    const newData = extractDataFromResponse<FollowingResponse, User>(
+    const extractedData = extractDataFromResponse<FollowingResponse, User>(
       res,
       (json) => json.data.user.result.timeline.timeline.instructions,
       (entry) => entry.content.itemContent.user_results.result,
     );
 
+    // 使用 Array.filter() 方法过滤掉 __typename 不是 'User' 的数据项
+    const newData = extractedData.filter(user => user.__typename === 'User');
+
     // Add captured data to the global store.
     followingSignal.value = [...followingSignal.value, ...newData];

有效,但还是不要 PR 了,可能这不是最好的方法 ☹️

@prinsss
Copy link
Owner

prinsss commented May 8, 2024

哦哦,我没有考虑到这种情况,感谢你的反馈!

我后面有时间会针对这种情况修复一下。如果你愿意,也可以参考以下流程发个 PR,我很欢迎~(如果要 PR 的话,麻烦你基于 idb 分支修改,目前我是在这个分支上开发的)


你上面的修改只针对 Following 数据导出有效,但这个问题在导出其他用户列表时应该也可能会出现。所以更通用的解决方法是这样修改(所有用到了 extractDataFromResponse 的用户模块都需要修改):

// src/modules/following/api.ts

const newData = extractDataFromResponse<FollowingResponse, User>(
  res,
  (json) => json.data.user.result.timeline.timeline.instructions,
- (entry) => entry.content.itemContent.user_results.result,
+ (entry) => extractTimelineUser(entry.content.itemContent),
);

然后在 src/utils/api.tsextractTimelineTweet 方法的下面,类似地添加一个 extractTimelineUser 方法:

/**
 * Extract the user object from the timeline entry, ignoring unavailable users.
 */
export function extractTimelineUser(itemContent: TimelineUser): User | null {
  const user = itemContent.user_results.result;

  if (!user || user.__typename !== 'User') {
    logger.warn(
      "TimelineUser is empty. This could happen when the user's account is suspended or deleted.",
      itemContent,
    );
    return null;
  }

  return user;
}

最后,完善类型定义 src/types/user.ts

export interface TimelineUser {
  itemType: 'TimelineUser';
  __typename: 'TimelineUser';
  user_results: {
-   result: User;
+   result: User | UserUnavailable;
  };
  userDisplayType: string;
}

+export interface UserUnavailable {
+  __typename: 'UserUnavailable';
+  message: string;
+  reason: string;
+}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants