Innei/Shiro

是否可以添加LeetCode的LinkCard

liyown opened this issue · 3 comments

Feature description

可以根据题目获取相关信息,展示卡片,例如
<LinkCard source="leetcode" id="median-of-two-sorted-arrays" />

我大概参考源码的数据获取函数写了一个函数,但是开发环境不太好搭建,可以麻烦大佬测试加上去嘛。

const fetchLeetCodeQuestionData: FetchObject = {
    isValid: (id) => {
      // 检查 titleSlug 是否是一个有效的字符串
      return typeof id === 'string' && id.length > 0;
    },
    fetch: async (id, setCardInfo, setFullUrl) => {
      try {
        // 第一个请求:获取题目基本信息
        const questionTitleResponse = await fetchLeetCodeApi({
          query: `
            query questionTitle($titleSlug: String!) {
              question(titleSlug: $titleSlug) {
                questionId
                title
                isPaidOnly
                difficulty
                likes
                dislikes
                categoryTitle
              }
            }
          `,
          variables: { titleSlug: id },
        });
        const questionTitleData = camelcaseKeys(questionTitleResponse.data.question);
  
        // 第二个请求:获取题目翻译
        const translationResponse = await fetchLeetCodeApi({
          query: `
            query questionTranslations($titleSlug: String!) {
              question(titleSlug: $titleSlug) {
                translatedTitle
                translatedContent
              }
            }
          `,
          variables: { titleSlug: id },
        });
        const translationData = camelcaseKeys(translationResponse.data.question);
  
        // 第三个请求:获取题目标签
        const tagsResponse = await fetchLeetCodeApi({
          query: `
            query singleQuestionTopicTags($titleSlug: String!) {
              question(titleSlug: $titleSlug) {
                topicTags {
                  name
                  translatedName
                }
              }
            }
        `,
        variables: { titleSlug: id },
      });
      const tagsData = camelcaseKeys(tagsResponse.data.question);
      
      // 设置卡片信息
      setCardInfo({
        title: (
          <span className="flex items-center gap-2">
            <span className="flex-1">{translationData.translatedTitle || questionTitleData.title}</span>
            <span className="shrink-0 self-end justify-self-end">
              {questionTitleData.likes > 0 && (
                <span className="inline-flex shrink-0 items-center gap-1 self-center text-sm text-orange-400 dark:text-yellow-500">
                  <i className="icon-[mingcute--thumb-up-line]" />
                  <span className="font-sans font-medium">
                    {questionTitleData.likes}
                  </span>
                </span>
              )}
            </span>
          </span>
        ),
        desc: tagsData.topicTags.map(tag => tag.translatedName || tag.name).join(', '),
        image: "https://upload.wikimedia.org/wikipedia/commons/1/19/LeetCode_logo_black.png",
        color: getDifficultyColor(questionTitleData.difficulty), 
      });

      setFullUrl(`https://leetcode.cn/problems/${id}/`);
    } catch (err) {
      console.error('Error fetching LeetCode question data:', err);
      throw err;
    }
  },
};

// 通用的 GraphQL 请求函数
async function fetchLeetCodeApi(requestBody) {
  const response = await fetch('https://leetcode.cn/graphql/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(requestBody),
  });

  if (!response.ok) {
    throw new Error('Failed to fetch data from LeetCode API');
  }

  return await response.json();
}

// 映射难度到颜色的函数
function getDifficultyColor(difficulty) {
  switch (difficulty) {
    case 'Easy':
      return '#00BFA5';
    case 'Medium':
      return '#FFA726';
    case 'Hard':
      return '#F44336';
    default:
      return '#757575';
  }
}
  

Validations

  • You know your feature request won't be accepted.

你可以使用你自己的 api 进行测试,PR welcome

PR 已经提交,请大佬 review and decide merge

Merged