Skip to content

Commit fd63633

Browse files
author
Guriy Samarin
committed
automated check for today's task
1 parent 6653b19 commit fd63633

File tree

4 files changed

+204
-6
lines changed

4 files changed

+204
-6
lines changed

src/LeetcodeDailyChallengeReminder/Functions.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,20 @@ public async Task<string> Test(ILambdaContext context)
110110

111111
DailyChallengeInfo? daily = await LeetcodeDailyChallenge.LeetcodeDailyChallenge.LeetcodeDailyChallenge.GetLeetcodeDailyChallenge(s_client, jsonSerializerOptions, context.Logger);
112112
if (daily is null) return "Fail to get daily challenge";
113-
context.Logger.LogInformation("Daily challenge received {daily.Data}");
113+
context.Logger.LogInformation($"Daily challenge received {daily.Data}");
114+
115+
UserProfileResponse? userProfileResponse = await LeetcodeDailyChallenge.LeetcodeDailyChallenge.LeetcodeDailyChallenge.GetUserLeetcodeStatus("Sa1Gur", jsonSerializerOptions, context.Logger);
116+
if (userProfileResponse is {})
117+
{
118+
context.Logger.LogInformation($"UserProfileResponse {userProfileResponse}");
119+
if (userProfileResponse.RecentSubmissionList.Any(submission => submission.TitleSlug.Equals(daily.Data.Challenge.Question.Slug, StringComparison.Ordinal)))
120+
return "Solved for today!";
121+
}
122+
else
123+
{
124+
context.Logger.LogInformation("Fail to receive UserProfileResponse");
125+
}
126+
114127

115128
string creds = await _secretsManagerCache.GetSecretString("LeetcodeDailyChallengeBot");
116129
context.Logger.LogInformation("Creds received");

src/LeetcodeDailyChallengeReminder/LeetcodeDailyChallengeReminder.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.4" />
1818
<PackageReference Include="Amazon.Lambda.Annotations" Version="1.6.2" />
1919
<PackageReference Include="AWSSDK.SecretsManager.Caching" Version="1.0.6" />
20+
<PackageReference Include="GraphQL.Client" Version="6.1.0" />
21+
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="6.1.0" />
2022
</ItemGroup>
2123
<!--
2224
The FrameworkReference is used to reduce the deployment bundle size by not having to include

src/LeetcodeDailyChallengeReminder/Service/LeetcodeDailyChallenge.cs

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
using System.Text.Json;
2+
using System.Text.Json.Serialization;
23
using Amazon.Lambda.Core;
4+
using GraphQL;
5+
using GraphQL.Client.Http;
6+
using GraphQL.Client.Serializer.SystemTextJson;
37

48
namespace LeetcodeDailyChallenge.LeetcodeDailyChallenge;
59

@@ -47,4 +51,171 @@ await response.Content.ReadAsStringAsync(),
4751
return null;
4852
}
4953
}
50-
}
54+
55+
public static async Task<UserProfileResponse?> GetUserLeetcodeStatus(
56+
string username,
57+
JsonSerializerOptions options,
58+
ILambdaLogger logger)
59+
{
60+
string leetCodeGraphQLUrl = "https://leetcode.com/graphql";
61+
var query = @"
62+
query getUserProfile($username: String!) {
63+
allQuestionsCount {
64+
difficulty
65+
count
66+
}
67+
matchedUser(username: $username) {
68+
username
69+
socialAccounts
70+
githubUrl
71+
contributions {
72+
points
73+
questionCount
74+
testcaseCount
75+
}
76+
profile {
77+
realName
78+
websites
79+
countryName
80+
skillTags
81+
company
82+
school
83+
starRating
84+
aboutMe
85+
userAvatar
86+
reputation
87+
ranking
88+
}
89+
submissionCalendar
90+
submitStats: submitStatsGlobal {
91+
acSubmissionNum {
92+
difficulty
93+
count
94+
submissions
95+
}
96+
}
97+
}
98+
recentSubmissionList(username: $username, limit: 20) {
99+
title
100+
titleSlug
101+
timestamp
102+
statusDisplay
103+
lang
104+
}
105+
}";
106+
107+
using var graphQLClient = new GraphQLHttpClient(leetCodeGraphQLUrl, new SystemTextJsonSerializer());
108+
109+
GraphQLRequest request = new()
110+
{
111+
Query = query,
112+
Variables = new { username }
113+
};
114+
115+
var response = await graphQLClient.SendQueryAsync<UserProfileResponse>(request);
116+
117+
if (response.Errors != null && response.Errors.Length > 0)
118+
{
119+
logger.LogError($"Errors:{string.Join("\n", response.Errors.Select(x => x.ToString()))}");
120+
return null;
121+
}
122+
123+
return response.Data;
124+
}
125+
}
126+
127+
public class UserProfileResponse
128+
{
129+
public List<QuestionCount> AllQuestionsCount { get; set; }
130+
public MatchedUser MatchedUser { get; set; }
131+
public List<RecentSubmission> RecentSubmissionList { get; set; }
132+
}
133+
134+
public class QuestionCount
135+
{
136+
public string Difficulty { get; set; }
137+
public int Count { get; set; }
138+
}
139+
140+
public class MatchedUser
141+
{
142+
public string Username { get; set; }
143+
public List<string> SocialAccounts { get; set; }
144+
public string GithubUrl { get; set; }
145+
public Contributions Contributions { get; set; }
146+
public Profile Profile { get; set; }
147+
public string SubmissionCalendar { get; set; }
148+
public SubmitStats SubmitStats { get; set; }
149+
}
150+
151+
public class Contributions
152+
{
153+
public int Points { get; set; }
154+
public int QuestionCount { get; set; }
155+
public int TestcaseCount { get; set; }
156+
}
157+
158+
public class Profile
159+
{
160+
public string RealName { get; set; }
161+
public List<string> Websites { get; set; }
162+
public string CountryName { get; set; }
163+
public List<string> SkillTags { get; set; }
164+
public string Company { get; set; }
165+
public string School { get; set; }
166+
public double StarRating { get; set; }
167+
public string AboutMe { get; set; }
168+
public string UserAvatar { get; set; }
169+
public int Reputation { get; set; }
170+
public int Ranking { get; set; }
171+
}
172+
173+
public class SubmitStats
174+
{
175+
public List<AcSubmissionNum> AcSubmissionNum { get; set; }
176+
}
177+
178+
public class AcSubmissionNum
179+
{
180+
public string Difficulty { get; set; }
181+
public int Count { get; set; }
182+
public int Submissions { get; set; }
183+
}
184+
185+
public class RecentSubmission
186+
{
187+
public string Title { get; set; }
188+
public string TitleSlug { get; set; }
189+
[JsonConverter(typeof(UnixTimestampToDateTimeConverter))]
190+
public DateTime Timestamp { get; set; }
191+
public string StatusDisplay { get; set; }
192+
public string Lang { get; set; }
193+
}
194+
195+
public class UnixTimestampToDateTimeConverter : JsonConverter<DateTime>
196+
{
197+
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
198+
{
199+
if (reader.TokenType == JsonTokenType.String)
200+
{
201+
string stringValue = reader.GetString();
202+
if (long.TryParse(stringValue, out long unixTimestamp))
203+
{
204+
return DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).DateTime;
205+
}
206+
}
207+
else if (reader.TokenType == JsonTokenType.Number)
208+
{
209+
long unixTimestamp = reader.GetInt64();
210+
return DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).DateTime;
211+
}
212+
213+
throw new JsonException("Unable to convert timestamp to DateTime");
214+
}
215+
216+
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
217+
{
218+
long unixTimestamp = ((DateTimeOffset)value).ToUnixTimeSeconds();
219+
writer.WriteNumberValue(unixTimestamp);
220+
}
221+
}

src/LeetcodeDailyChallengeReminder/serverless.template

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
{
22
"AWSTemplateFormatVersion": "2010-09-09",
33
"Transform": "AWS::Serverless-2016-10-31",
4-
"Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v1.3.0.0).",
4+
"Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v1.6.2.0).",
55
"Resources": {
66
"LambdaAnnotationsFunctionsDefaultGenerated": {
77
"Type": "AWS::Serverless::Function",
88
"Metadata": {
99
"Tool": "Amazon.Lambda.Annotations",
1010
"SyncedEvents": [
1111
"RootGet"
12-
]
12+
],
13+
"SyncedEventProperties": {
14+
"RootGet": [
15+
"Path",
16+
"Method"
17+
]
18+
}
1319
},
1420
"Properties": {
1521
"Runtime": "dotnet8",
@@ -38,7 +44,13 @@
3844
"Tool": "Amazon.Lambda.Annotations",
3945
"SyncedEvents": [
4046
"RootGet"
41-
]
47+
],
48+
"SyncedEventProperties": {
49+
"RootGet": [
50+
"Path",
51+
"Method"
52+
]
53+
}
4254
},
4355
"Properties": {
4456
"Runtime": "dotnet8",
@@ -70,4 +82,4 @@
7082
}
7183
}
7284
}
73-
}
85+
}

0 commit comments

Comments
 (0)