├── MANIFEST.in
├── setup.py
├── pyproject.toml
├── LICENSE
├── README.md
└── nonebot_plugin_leetcode2
├── template
└── template.html
├── get_problem_data.py
├── get_user_data.py
└── __init__.py
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include nonebot_plugin_leetcode2/template/template.html
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | setuptools.setup(
4 | name='nonebot_plugin_leetcode2',
5 | version='1.1.3',
6 | author='Nranphy',
7 | author_email='3102002900@qq.com',
8 | url='https://github.com/Nranphy/nonebot_plugin_leetcode2',
9 | description="基于nonebot2的leetcode查询插件。",
10 | long_description=u'一个基于nonebot2的leetcode查询插件,可以查询用户和题目,包含每日一题和随机一题,并可以每日定时发送题目。',
11 | packages=setuptools.find_packages(),
12 | install_requires=[
13 | "httpx",
14 | "nonebot-plugin-htmlrender",
15 | "nonebot-plugin-apscheduler"
16 | ],
17 | )
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "nonebot_plugin_leetcode2"
3 | version = "1.1.3"
4 | description = "基于nonebot2的leetcode查询插件。"
5 | authors = ["Nranphy <3102002900@qq.com>"]
6 | license = "MIT"
7 | readme = "README.md"
8 | homepage = "https://github.com/Nranphy/nonebot_plugin_leetcode2"
9 | repository = "https://github.com/Nranphy/nonebot_plugin_leetcode2"
10 | include = [
11 | "LICENSE",
12 | ]
13 |
14 | [tool.poetry.dependencies]
15 | python = ">=3.7.3"
16 | nonebot2 = ">=2.0.0-beta.2"
17 | nonebot-adapter-onebot = ">=2.0.0-beta.1"
18 | nonebot-plugin-apscheduler = ">=0.1.2"
19 | httpx = ">=0.20.0"
20 | nonebot-plugin-htmlrender = ">=0.2.0.1"
21 |
22 |
23 | [tool.poetry.dev-dependencies]
24 |
25 | [build-system]
26 | requires = ["poetry-core>=1.0.0"]
27 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [year] [fullname]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nonebot_plugin_leetcode2
2 | 基于nonebot2的leetcode查询插件。
3 |
4 | ## 目前已实现功能
5 | - [x] **对指令`/每日一题`,`/lc`,`/leetcode`回复,发送今天的每日一题。**
6 |
7 | - [x] **可搜索leetcode题目,指令`/lc搜索 XXXXX`,`/lc查找 XXXXX`,`/leetcode搜索 XXXXX`,将以关键词“XXXXX”进行leetcode搜索,发送搜索到的第一道题。**
8 |
9 | - [x] **随机一题,指令`/lc随机`,`/lc随机一题`,`/leetcode随机`将请求leetcode随机一题,发送请求到的任意题目。**
10 |
11 | - [x] **查询用户信息`/lc查询 XXXXX`,`/lc查询用户 XXXXX`,`/leetcode查询 XXXXX`,可查询用户基本信息,XXXXX为用户ID(不能用用户名)。**
12 |
13 | - [x] **加入计划任务** 每日在指定时间向指定群和好友发送当天的每日一题
14 |
15 | ## 使用方法
16 |
17 | 1.在机器人plugins目录下进行git clone
18 |
19 | 2.使用`nb plugin install nonebot_plugin_leetcode2`
20 |
21 | 3.使用`pip install nonebot_plugin_leetcode2`,并修改插件加载。
22 |
23 | ## 注意事项
24 |
25 | 若有需要使用本插件计划任务相关功能,请在.env.\*文件中加入以下设置:
26 | ```
27 | LEETCODE_QQ_FRIENDS=[3102002900]
28 | LEETCODE_QQ_GROUPS=[805324289]
29 | LEETCODE_INFORM_TIME=[{"HOUR":20,"MINUTE":1},{"HOUR":20,"MINUTE":10},{"HOUR":0,"MINUTE":1}]
30 | ```
31 | 其中`LEETCODE_QQ_FRIENDS`是欲定期发送题目的好友QQ,`LEETCODE_QQ_GROUPS`是定期发送题目的群聊群号,`LEETCODE_INFORM_TIME`是定时的时间。这和另一个leetcode插件的配置项是相同的。
32 |
33 | 当然,不添加配置项也可正常使用其他功能。感谢@j1g5awi佬的检查与提醒。
34 |
35 | 另外,由于使用到nonebot-plugin-apscheduler插件,请安排插件导入顺序以免发生错误。
--------------------------------------------------------------------------------
/nonebot_plugin_leetcode2/template/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Leetcode
8 |
65 |
66 |
67 |
68 |
69 |
70 | 【title】
71 |
72 | 【content】
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/nonebot_plugin_leetcode2/get_problem_data.py:
--------------------------------------------------------------------------------
1 | import httpx
2 | import json
3 | from pathlib import Path
4 | from nonebot.log import logger
5 |
6 |
7 |
8 | def get_random_title() -> str:
9 | '''请求随机题目'''
10 | try:
11 | get_random_data = httpx.post("https://leetcode-cn.com/graphql", json={
12 | "query": "query problemsetRandomFilteredQuestion($categorySlug: String!, $filters: QuestionListFilterInput) { problemsetRandomFilteredQuestion(categorySlug: $categorySlug, filters: $filters)}",
13 | "variables": {
14 | "categorySlug": "",
15 | "filters": {}
16 | }
17 | })
18 | random_data = json.loads(get_random_data.text)
19 | titleSlug = random_data["data"]["problemsetRandomFilteredQuestion"]
20 | return titleSlug
21 | except Exception as e:
22 | logger.error("[LC查询] 获取随机题目标题时出错。",e)
23 | raise e
24 |
25 |
26 | def get_today_title() -> str:
27 | '''获取今日的每日一题标题'''
28 | try:
29 | get_today_data = httpx.post("https://leetcode-cn.com/graphql", json={
30 | "query":"query questionOfToday {todayRecord { date question {frontendQuestionId: questionFrontendId difficulty titleSlug } } } ",
31 | "variables":{}
32 | })
33 | today_data = json.loads(get_today_data.text)
34 | titleSlug = today_data["data"]["todayRecord"][0]["question"]["titleSlug"]
35 | return titleSlug
36 | except Exception as e:
37 | logger.error("[LC查询] 获取每日一题标题时出错。",e)
38 | raise e
39 |
40 |
41 | def get_search_title(keyword) -> str:
42 | '''调用查询接口进行查询,返回首个查询结果题目标题'''
43 | try:
44 | get_search_data = httpx.post("https://leetcode-cn.com/graphql", json={
45 | "query": "query problemsetQuestionList($categorySlug: String, $limit: Int, $skip: Int, $filters: QuestionListFilterInput) { problemsetQuestionList( categorySlug: $categorySlug limit: $limit skip: $skip filters: $filters ) { hasMore total questions { acRate difficulty freqBar frontendQuestionId isFavor paidOnly solutionNum status title titleCn titleSlug topicTags { name nameTranslated id slug } extra { hasVideoSolution topCompanyTags { imgUrl slug numSubscribed } } } }} ",
46 | "variables": {
47 | "categorySlug": "",
48 | "skip": 0,
49 | "limit": 1,
50 | "filters": {
51 | "searchKeywords": keyword
52 | }
53 | }
54 | })
55 | search_data = json.loads(get_search_data.text)
56 | question_list = search_data["data"]["problemsetQuestionList"]["questions"]
57 | if question_list:
58 | titleSlug = question_list[0]["titleSlug"]
59 | else:
60 | titleSlug = ""
61 | return titleSlug
62 | except Exception as e:
63 | logger.error("[LC查询] 获取搜索标题时出错。",e)
64 | raise e
65 |
66 |
67 | def get_sub_problem_data(titleSlug) -> list:
68 | '''获取某一已知名称的题目内容'''
69 | try:
70 | with open(Path(__file__).parent / "template" / "template.html", "r", encoding="UTF-8") as f:
71 | html_template = f.read()
72 | except Exception as e:
73 | logger.error("[LC查询] 载入HTML模板时发生错误。",e)
74 | raise e
75 | try:
76 | get_problem_data = httpx.post("https://leetcode-cn.com/graphql", json={
77 | "operationName": "questionData",
78 | "variables": {
79 | "titleSlug": titleSlug },
80 | "query": "query questionData($titleSlug: String!) { question(titleSlug: $titleSlug) { questionFrontendId title titleSlug translatedTitle translatedContent difficulty } } "
81 | })
82 | problem_data = json.loads(get_problem_data.text)
83 | problem_data = problem_data["data"]["question"]
84 | #题目信息(题号+题目译名)
85 | problem_title = problem_data.get("questionFrontendId")+"."+problem_data.get("translatedTitle")
86 | #题目难度(英语单词)
87 | problem_difficulty = "题目难度:"+problem_data.get("difficulty")
88 | #题目内容(用html输出)
89 | problem_content:str = problem_data.get("translatedContent")
90 | problem_content = html_template.replace("【content】",(problem_content.replace('\\"', '"'))).replace("【title】", problem_title)
91 | #题目链接
92 | problem_link = "本题链接:"+f"https://leetcode-cn.com/problems/{titleSlug}/"
93 | return [problem_title, problem_difficulty, problem_content, problem_link]
94 | except Exception as e:
95 | logger.error("[LC查询] 获取已知题目的内容时出错。",e)
96 | raise e
--------------------------------------------------------------------------------
/nonebot_plugin_leetcode2/get_user_data.py:
--------------------------------------------------------------------------------
1 | import httpx
2 | import json
3 | from nonebot.log import logger
4 |
5 |
6 |
7 | def get_user_public_profile(userSlug):
8 | '''获取用户公开信息'''
9 | try:
10 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
11 | "operationName": "userPublicProfile",
12 | "variables": {
13 | "userSlug": userSlug
14 | },
15 | "query": "query userPublicProfile($userSlug: String!) { userProfilePublicProfile(userSlug: $userSlug) { username haveFollowed siteRanking profile { userSlug realName aboutMe userAvatar location gender websites skillTags contestCount asciiCode medals { name year month category __typename } ranking { rating ranking currentLocalRanking currentGlobalRanking currentRating ratingProgress totalLocalUsers totalGlobalUsers __typename } skillSet { langLevels { langName langVerboseName level __typename } topics { slug name translatedName __typename } topicAreaScores { score topicArea { name slug __typename } __typename } __typename } socialAccounts { provider profileUrl __typename } __typename } educationRecordList { unverifiedOrganizationName __typename } occupationRecordList { unverifiedOrganizationName jobTitle __typename } submissionProgress { totalSubmissions waSubmissions acSubmissions reSubmissions otherSubmissions acTotal questionTotal __typename } __typename }}"
16 | })
17 | user_public_data = json.loads(get_data.text)
18 | return user_public_data
19 | except Exception as e:
20 | logger.error("[LC查询] 获取用户公开信息时出错。",e)
21 | raise e
22 |
23 |
24 |
25 | def get_user_question_progress(userSlug):
26 | '''获取用户已通过题目'''
27 | try:
28 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
29 | "operationName": "userQuestionProgress",
30 | "variables": {
31 | "userSlug": userSlug
32 | },
33 | "query": "query userQuestionProgress($userSlug: String!) { userProfileUserQuestionProgress(userSlug: $userSlug) { numAcceptedQuestions { difficulty count __typename } numFailedQuestions { difficulty count __typename } numUntouchedQuestions { difficulty count __typename } __typename }}"
34 | })
35 | user_question_progress = json.loads(get_data.text)
36 | return user_question_progress
37 | except Exception as e:
38 | logger.error("[LC查询] 获取用户已通过题目时出错。",e)
39 | raise e
40 |
41 |
42 |
43 | def get_user_solution_count(userSlug):
44 | '''获取用户已发布题解数'''
45 | try:
46 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
47 | "operationName": "columnsUserSolutionCount",
48 | "variables": {
49 | "userSlug": userSlug
50 | },
51 | "query": "query columnsUserSolutionCount($userSlug: String!) {\n columnsUserSolutionCount(userSlug: $userSlug)\n}\n"
52 | })
53 | user_solution_count = json.loads(get_data.text)
54 | return user_solution_count
55 | except Exception as e:
56 | logger.error("[LC查询] 获取用户已发布题解数时出错。",e)
57 | raise e
58 |
59 |
60 |
61 | def get_user_profile_articles(userSlug):
62 | '''获取用户最新题解题目'''
63 | try:
64 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
65 | "operationName": "profileArticles",
66 | "variables": {
67 | "userSlug": userSlug,
68 | "skip": 0,
69 | "first": 15
70 | },
71 | "query": "query profileArticles($userSlug: String!, $skip: Int, $first: Int) {\n solutionArticles(userSlug: $userSlug, skip: $skip, first: $first) {\n edges {\n node {\n title\n slug\n question {\n title\n titleSlug\n translatedTitle\n questionFrontendId\n __typename\n }\n upvoteCount\n topic {\n commentCount\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n"
72 | })
73 | user_profile_articles = json.loads(get_data.text)
74 | return user_profile_articles
75 | except Exception as e:
76 | logger.error("[LC查询] 获取用户最新题解时出错。",e)
77 | raise e
78 |
79 |
80 |
81 | def get_user_community_achievement(userSlug):
82 | '''获取用户声望信息'''
83 | try:
84 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
85 | "operationName": "profileCommunityAchievement",
86 | "variables": {
87 | "userSlug": userSlug,
88 | "size": 3
89 | },
90 | "query": "query profileCommunityAchievement($size: Int!, $userSlug: String!) {\n profileCommunityAchievement(size: $size, userSlug: $userSlug) {\n date\n voteCount\n viewCount\n favoriteCount\n __typename\n }\n}\n"
91 | })
92 | user_community_achievement = json.loads(get_data.text)
93 | return user_community_achievement
94 | except Exception as e:
95 | logger.error("[LC查询] 获取用户声望信息时出错。",e)
96 | raise e
97 |
98 |
99 |
100 | def get_user_question_submitstats(userSlug):
101 | '''获取用户题目提交统计'''
102 | try:
103 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
104 | "operationName": "userQuestionSubmitStats",
105 | "variables": {
106 | "userSlug": userSlug
107 | },
108 | "query": "query userQuestionSubmitStats($userSlug: String!) {\n userProfileUserQuestionSubmitStats(userSlug: $userSlug) {\n acSubmissionNum {\n difficulty\n count\n __typename\n }\n totalSubmissionNum {\n difficulty\n count\n __typename\n }\n __typename\n }\n}\n"
109 | })
110 | user_question_submitstat = json.loads(get_data.text)
111 | return user_question_submitstat
112 | except Exception as e:
113 | logger.error("[LC查询] 获取用户题目提交统计时出错。",e)
114 | raise e
115 |
116 |
117 |
118 | def get_user_medals(userSlug):
119 | '''获取用户勋章'''
120 | try:
121 | get_data = httpx.post("https://leetcode-cn.com/graphql", json={
122 | "operationName": "userMedals",
123 | "variables": {
124 | "userSlug": userSlug
125 | },
126 | "query": "query userMedals($userSlug: String!) {\n userProfileUserMedals(userSlug: $userSlug) {\n ...medalNodeFragment\n __typename\n }\n userProfileUserLevelMedal(userSlug: $userSlug) {\n current {\n ...medalNodeFragment\n __typename\n }\n next {\n ...medalNodeFragment\n __typename\n }\n __typename\n }\n userProfileUserNextMedal(userSlug: $userSlug) {\n ...medalNodeFragment\n __typename\n }\n}\n\nfragment medalNodeFragment on MedalNodeV2 {\n name\n obtainDate\n category\n config {\n icon\n iconGif\n iconGifBackground\n __typename\n }\n progress\n id\n year\n month\n __typename\n}\n"
127 | })
128 | user_medals = json.loads(get_data.text)
129 | return user_medals
130 | except Exception as e:
131 | logger.error("[LC查询] 获取用户勋章信息时出错。",e)
132 | raise e
--------------------------------------------------------------------------------
/nonebot_plugin_leetcode2/__init__.py:
--------------------------------------------------------------------------------
1 | from nonebot import on_command, require, get_bot, get_driver
2 | from nonebot.log import logger
3 | from nonebot.typing import T_State
4 | from nonebot.adapters.onebot.v11 import Bot, Event, MessageSegment
5 |
6 | from nonebot_plugin_htmlrender import html_to_pic
7 |
8 | from .get_problem_data import *
9 | from .get_user_data import *
10 |
11 |
12 |
13 | request_today = on_command("lc每日",aliases={"lc","leetcode"},priority = 10,block = True)
14 |
15 | request_search = on_command("lc查找",aliases={"lc搜索","leetcode搜索"},priority = 10,block = True)
16 |
17 | request_random = on_command("lc随机",aliases={"lc随机一题","leetcode随机"},priority = 10,block = True)
18 |
19 | request_user = on_command("lc查询",aliases={"lc查询用户","leetcode查询"},priority = 10,block = True)
20 |
21 |
22 | try:
23 | scheduler = require("nonebot_plugin_apscheduler").scheduler
24 | except Exception as e:
25 | logger.error("[LC查询] require定时插件时出错,请检查插件加载顺序。")
26 |
27 |
28 |
29 |
30 | #查询每日一题
31 | @request_today.handle()
32 | async def send_today_problem(bot: Bot,event:Event):
33 | try:
34 | today_title = get_today_title()
35 | logger.info(f"[LC查询] 获取今日题目成功,题目为{today_title}.")
36 | today_data = get_sub_problem_data(today_title)
37 | logger.info("[LC查询] 获取题目内容成功。")
38 | logger.debug(f"[LC查询] 题目{today_data[0]}的难度为{today_data[1]}")
39 | except Exception as e:
40 | logger.error("[LC查询] 无法连接至leetcode,请检查网络和网络代理状态。")
41 | await request_today.finish("连接到leetcode失败...呜呜呜...\n请稍后再试!!")
42 |
43 | pic = await html_to_pic(today_data[2], viewport={"width": 840, "height": 400})
44 | await request_today.send("获取今日每日一题成功~加油哦ww\n"+"\n".join(today_data[:2])+MessageSegment.image(pic)+f"\n{today_data[3]}")
45 |
46 |
47 |
48 |
49 |
50 |
51 | #搜索题目
52 | @request_search.handle()
53 | async def parse(bot: Bot, event: Event, state: T_State):
54 | temp = str(event.get_message()).split()
55 | try:
56 | state["keyword"] = temp[1]
57 | except Exception:
58 | pass
59 |
60 |
61 | @request_search.got("keyword",prompt="请输出要在leetcode查找的内容哦~\n可为题号、题目、题干内容哒")
62 | async def send_today_problem(bot: Bot,event:Event, state: T_State):
63 | try:
64 | search_title = get_search_title(state["keyword"])
65 | if search_title:
66 | logger.info(f"[LC查询] 成功搜索到关键字题目,只取第一条,题目为{search_title}.")
67 | else:
68 | logger.info("[LC查询] 搜索成功,但并无相关题目。")
69 | request_search.finish("未搜索到相关题目!!\n要不...换个关键字再搜索一下吧~可为题号、题目、题干内容哒")
70 |
71 | data = get_sub_problem_data(search_title)
72 | logger.info("[LC查询] 获取题目内容成功。")
73 | logger.debug(f"[LC查询] 题目{data[0]}的难度为{data[1]}")
74 | except Exception as e:
75 | logger.error("[LC查询] 无法连接至leetcode,请检查网络和网络代理状态。")
76 | await request_search.finish("连接到leetcode失败...呜呜呜...\n请稍后再试!!")
77 |
78 | pic = await html_to_pic(data[2], viewport={"width": 840, "height": 400})
79 | await request_search.send("搜索成功~只发送了最相关题目哦ww\n"+"\n".join(data[:2])+MessageSegment.image(pic)+f"\n{data[3]}")
80 |
81 |
82 |
83 |
84 |
85 |
86 | #随机一题
87 | @request_random.handle()
88 | async def send_random_problem(bot: Bot,event:Event):
89 | try:
90 | random_title = get_random_title()
91 | logger.info(f"[LC查询] 获取随机一题题目成功,题目为{random_title}.")
92 | random_data = get_sub_problem_data(random_title)
93 | logger.info("[LC查询] 获取题目内容成功。")
94 | logger.debug(f"[LC查询] 题目{random_data[0]}的难度为{random_data[1]}")
95 | except Exception as e:
96 | logger.error("[LC查询] 无法连接至leetcode,请检查网络和网络代理状态。")
97 | await request_random.finish("连接到leetcode失败...呜呜呜...\n请稍后再试!!")
98 |
99 | pic = await html_to_pic(random_data[2], viewport={"width": 840, "height": 400})
100 | await request_random.send("成功获取随机一题~加油哦ww\n"+"\n".join(random_data[:2])+MessageSegment.image(pic)+f"\n{random_data[3]}")
101 |
102 |
103 |
104 |
105 |
106 |
107 | #查询用户信息
108 | @request_user.handle()
109 | async def parse(bot: Bot, event: Event, state: T_State):
110 | temp = str(event.get_message()).split()
111 | if temp[1]:
112 | state["userSlug"] = temp[1]
113 |
114 |
115 | @request_user.got("userSlug",prompt="请输出要在leetcode查询的用户哦~\n请写入用户ID,而非用户昵称哦~")
116 | async def send_user_data(bot: Bot,event:Event, state: T_State):
117 | try:
118 | #详细的返回json信息请查阅json/文件夹内的文本,或者参见get_user_data.py
119 | user_public_profile = get_user_public_profile(state["userSlug"])
120 | user_question_progress = get_user_question_progress(state["userSlug"])
121 | user_solution_count = get_user_solution_count(state["userSlug"])
122 | user_profile_articles = get_user_profile_articles(state["userSlug"])
123 | user_community_achievement = get_user_community_achievement(state["userSlug"])
124 | user_question_submitstats = get_user_question_submitstats(state["userSlug"])
125 | user_medals = get_user_medals(state["userSlug"])
126 | except Exception as e:
127 | logger.error("[LC查询] 无法连接至leetcode,请检查网络和网络代理状态。")
128 | await request_user.finish("连接到leetcode失败...呜呜呜...\n请稍后再试!!")
129 | try:
130 | userSlug = state["userSlug"]
131 | realName = user_public_profile["data"]["userProfilePublicProfile"]["profile"]["realName"]
132 | userAvatar = httpx.get(user_public_profile["data"]["userProfilePublicProfile"]["profile"]["userAvatar"])
133 | totalSubmissions = user_public_profile["data"]["userProfilePublicProfile"]["submissionProgress"]["totalSubmissions"]
134 | waSubmissions = user_public_profile["data"]["userProfilePublicProfile"]["submissionProgress"]["waSubmissions"]
135 | acSubmissions = user_public_profile["data"]["userProfilePublicProfile"]["submissionProgress"]["acSubmissions"]
136 | reSubmissions = user_public_profile["data"]["userProfilePublicProfile"]["submissionProgress"]["reSubmissions"]
137 | otherSubmissions = user_public_profile["data"]["userProfilePublicProfile"]["submissionProgress"]["otherSubmissions"]
138 | acTotal = user_public_profile["data"]["userProfilePublicProfile"]["submissionProgress"]["acTotal"]
139 | logger.debug("[LC查询] user_public_profile数据解析完成")
140 |
141 | if user_community_achievement["data"]["profileCommunityAchievement"]:
142 | voteCount = user_community_achievement["data"]["profileCommunityAchievement"][0]["voteCount"]
143 | viewCount = user_community_achievement["data"]["profileCommunityAchievement"][0]["viewCount"]
144 | favoriteCount = user_community_achievement["data"]["profileCommunityAchievement"][0]["favoriteCount"]
145 | else:
146 | voteCount,viewCount,favoriteCount = 0,0,0
147 | logger.debug("[LC查询] user_community_achievement数据解析完成")
148 |
149 | numAcceptedQuestions_easy = user_question_progress["data"]["userProfileUserQuestionProgress"]["numAcceptedQuestions"][0]["count"]
150 | numAcceptedQuestions_medium = user_question_progress["data"]["userProfileUserQuestionProgress"]["numAcceptedQuestions"][1]["count"]
151 | numAcceptedQuestions_difficulty = user_question_progress["data"]["userProfileUserQuestionProgress"]["numAcceptedQuestions"][2]["count"]
152 | numFailedQuestions_easy = user_question_progress["data"]["userProfileUserQuestionProgress"]["numFailedQuestions"][0]["count"]
153 | numFailedQuestions_medium = user_question_progress["data"]["userProfileUserQuestionProgress"]["numFailedQuestions"][1]["count"]
154 | numFailedQuestions_difficulty = user_question_progress["data"]["userProfileUserQuestionProgress"]["numFailedQuestions"][2]["count"]
155 | numUntouchedQuestions_easy = user_question_progress["data"]["userProfileUserQuestionProgress"]["numUntouchedQuestions"][0]["count"]
156 | numUntouchedQuestions_medium = user_question_progress["data"]["userProfileUserQuestionProgress"]["numUntouchedQuestions"][1]["count"]
157 | numUntouchedQuestions_difficulty = user_question_progress["data"]["userProfileUserQuestionProgress"]["numUntouchedQuestions"][2]["count"]
158 | logger.debug("[LC查询] user_question_progress数据解析完成")
159 |
160 | columnsUserSolutionCount = user_solution_count["data"]["columnsUserSolutionCount"]
161 | logger.debug("[LC查询] user_solution_count数据解析完成")
162 |
163 | acSubmissionNum_easy = user_question_submitstats["data"]["userProfileUserQuestionSubmitStats"]["acSubmissionNum"][0]["count"]
164 | acSubmissionNum_medium = user_question_submitstats["data"]["userProfileUserQuestionSubmitStats"]["acSubmissionNum"][1]["count"]
165 | acSubmissionNum_hard = user_question_submitstats["data"]["userProfileUserQuestionSubmitStats"]["acSubmissionNum"][2]["count"]
166 | logger.debug("[LC查询] user_question_submitstats数据解析完成")
167 |
168 | if user_medals["data"]["userProfileUserMedals"]:
169 | latest_madal_name = user_medals["data"]["userProfileUserMedals"][0]["name"]
170 | latest_madal_date = user_medals["data"]["userProfileUserMedals"][0]["obtainDate"]
171 | latest_madal = f"【最近勋章】 勋章名:{latest_madal_name} |获得时间:{latest_madal_date}\n"
172 | else:
173 | latest_madal = ""
174 | logger.debug("[LC查询] user_medals数据解析完成")
175 |
176 | if user_profile_articles["data"]["solutionArticles"]["edges"]:
177 | latest_article_title = f'【最近题解】:{user_profile_articles["data"]["solutionArticles"]["edges"][0]["node"]["title"]}\n'
178 | else:
179 | latest_article_title = ""
180 | logger.debug("[LC查询] user_profile_articles数据解析完成")
181 |
182 |
183 | except Exception as e:
184 | await request_user.finish("解析用户信息出错×\n用户ID错误或不存在,请输入用户ID而非用户昵称哦~")
185 |
186 | await request_user.send(\
187 | "用户查询数据成功~\n"+\
188 | MessageSegment.image(userAvatar.read())+\
189 | f"用户名:{realName}({userSlug})\n"+\
190 | "========\n"+\
191 | f"【已解决问题】 EASY:{numAcceptedQuestions_easy} |MEDIUM:{numAcceptedQuestions_medium} |DIFFICULTY:{numAcceptedQuestions_difficulty}\n"+\
192 | f"【未答出问题】 EASY:{numFailedQuestions_easy} |MEDIUM:{numFailedQuestions_medium} |DIFFICULTY:{numFailedQuestions_difficulty}\n"+\
193 | f"【未接触问题】 EASY:{numUntouchedQuestions_easy} |MEDIUM:{numUntouchedQuestions_medium} |DIFFICULTY:{numUntouchedQuestions_difficulty}\n"+\
194 | f"【历史提交】 提交总数:{totalSubmissions} |错误提交数:{waSubmissions} |正确提交数:{acSubmissions} |重新提交数:{reSubmissions} |其他提交数:{otherSubmissions} |AC总数:{acTotal}\n"+\
195 | f"【提交通过数】 EASY:{acSubmissionNum_easy} |MEDIUM:{acSubmissionNum_medium} |DIFFICULTY:{acSubmissionNum_hard}\n"+\
196 | "========\n"
197 | f"【成就贡献】 阅读总数:{viewCount} |获得点赞:{voteCount} |获得收藏:{favoriteCount} |发布题解:{columnsUserSolutionCount}\n"+\
198 | latest_madal+latest_article_title+\
199 | f"用户主页:https://leetcode-cn.com/u/{userSlug}/")
200 |
201 |
202 |
203 |
204 |
205 | #定时发送
206 |
207 | time_list = get_driver().config.leetcode_inform_time if hasattr(get_driver().config, "leetcode_inform_time") else list()
208 |
209 | async def send_leetcode_everyday():
210 | qq_list = get_bot().config.leetcode_qq_friends if hasattr(get_driver().config, "leetcode_qq_friends") else list()
211 | group_list = get_bot().config.leetcode_qq_groups if hasattr(get_driver().config, "leetcode_qq_groups") else list()
212 | try:
213 | today_title = get_today_title()
214 | logger.info(f"[LC查询] 获取今日题目成功,题目为{today_title}.")
215 | today_data = get_sub_problem_data(today_title)
216 | logger.info("[LC查询] 获取题目内容成功。")
217 | logger.debug(f"[LC查询] 题目{today_data[0]}的难度为{today_data[1]}")
218 | except Exception as e:
219 | logger.error("[LC查询] 无法连接至leetcode,请检查网络和网络代理状态。")
220 | pass
221 | pic = await html_to_pic(today_data[2], viewport={"width": 840, "height": 400})
222 | try:
223 | for qq in qq_list:
224 | await get_bot().call_api("send_private_msg",user_id = qq ,message = "获取今日每日一题成功~加油哦ww\n"+"\n".join(today_data[:2])+MessageSegment.image(pic)+f"\n{today_data[3]}")
225 | for group in group_list:
226 | await get_bot().call_api("send_group_msg",group_id = group ,message = "获取今日每日一题成功~加油哦ww\n"+"\n".join(today_data[:2])+MessageSegment.image(pic)+f"\n{today_data[3]}")
227 | except TypeError:
228 | logger.error("[LC查询] 插件定时发送相关设置有误,请检查.env.*文件。")
229 |
230 |
231 |
232 |
233 |
234 | try:
235 | for index, time in enumerate(time_list):
236 | scheduler.add_job(send_leetcode_everyday, "cron", hour=time["HOUR"], minute=time["MINUTE"], id=f"leetcode_{str(index)}")
237 | logger.info(f"[LC查询] 新建计划任务成功!! id:leetcode_{index},时间为:{time}.")
238 | except TypeError:
239 | logger.error("[LC查询] 插件定时发送相关设置有误,请检查.env.*文件。")
--------------------------------------------------------------------------------