Skip to content

Commit 96b8a46

Browse files
committed
Implement command to list all user questions
1 parent bd75c29 commit 96b8a46

File tree

2 files changed

+97
-3
lines changed

2 files changed

+97
-3
lines changed

index.js

+94-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const {
66
addUserQuestion,
77
deleteUserQuestion,
88
getNextQuestion,
9+
getAllUserQuestions,
910
updateRecall
1011
} = require('./src/services/userQuestionsService')
1112
const { getQuestion } = require('./src/services/questionsService')
@@ -29,11 +30,15 @@ This is a bot that can intelligently schedule your next LeetCode problems to pra
2930
the forgetting curve. It uses a simple yet powerful model of forgetting (similar to Duolingo) to let you practice \
3031
problems with least recall probabilities.
3132
33+
Add or update a problem simply by sending its LeetCode question id to the bot.
34+
3235
<a href="https://github.com/SiyanH/leetrepeat-bot">Code</a> is open source on GitHub.
3336
3437
<b>Available actions</b>
3538
36-
/start shows welcome message`
39+
/start shows welcome message
40+
/next fetches your next problem
41+
/all lists all your problems`
3742

3843
const questionURL = (titleSlug) => `https://leetcode.com/problems/${titleSlug}`
3944

@@ -55,6 +60,40 @@ bot.start(ctx =>
5560

5661
bot.help(ctx => ctx.replyWithHTML(help))
5762

63+
bot.command('all', async ctx => {
64+
try {
65+
const questions = await getAllUserQuestions(ctx.from.id)
66+
67+
// Split questions to show on multiple pages if number of questions is over limit
68+
if (questions.length) {
69+
let html = ''
70+
const limit = 10 // number of questions shown on each page
71+
ctx.session.userQuestionsHTML = []
72+
73+
for (let i = 0; i < questions.length; i++) {
74+
if (i > 0 && i % limit === 0) {
75+
ctx.session.userQuestionsHTML.push(html)
76+
html = ''
77+
}
78+
const url = questionURL(questions[i].question[0].titleSlug)
79+
html += `<a href="${url}">${questions[i].question[0].id}. ${questions[i].question[0].title}</a>\n`
80+
}
81+
ctx.session.userQuestionsHTML.push(html)
82+
ctx.session.userQuestionsPage = 0
83+
84+
ctx.replyWithHTML(ctx.session.userQuestionsHTML[0], {
85+
disable_web_page_preview: true,
86+
reply_markup: ctx.session.userQuestionsHTML[1]
87+
? Markup.inlineKeyboard([Markup.button.callback('>>', 'next_page')]).reply_markup : []
88+
})
89+
} else {
90+
ctx.reply(`You haven't got any problem in your bucket. Try adding one?`)
91+
}
92+
} catch (e) {
93+
console.error('Bot failed to process command /all\n' + e)
94+
}
95+
})
96+
5897
bot.command('next', async ctx => {
5998
try {
6099
const userId = ctx.from.id
@@ -101,6 +140,60 @@ You can <b>update</b> it with the recent status of your solution or <b>delete</b
101140
}
102141
})
103142

143+
bot.action('next_page', async ctx => {
144+
try {
145+
await ctx.answerCbQuery()
146+
const html = ctx.session.userQuestionsHTML[++ctx.session.userQuestionsPage]
147+
let reply_markup
148+
149+
if (ctx.session.userQuestionsHTML[ctx.session.userQuestionsPage + 1]) {
150+
reply_markup = Markup.inlineKeyboard([
151+
Markup.button.callback('<<', 'previous_page'),
152+
Markup.button.callback('>>', 'next_page')
153+
]).reply_markup
154+
} else {
155+
reply_markup = Markup.inlineKeyboard([
156+
Markup.button.callback('<<', 'previous_page'),
157+
]).reply_markup
158+
}
159+
160+
ctx.editMessageText(html, {
161+
parse_mode: 'HTML',
162+
disable_web_page_preview: true,
163+
reply_markup
164+
})
165+
} catch (e) {
166+
console.error(`Bot failed to process callback 'next_page'\n` + e)
167+
}
168+
})
169+
170+
bot.action('previous_page', async ctx => {
171+
try {
172+
await ctx.answerCbQuery()
173+
const html = ctx.session.userQuestionsHTML[--ctx.session.userQuestionsPage]
174+
let reply_markup
175+
176+
if (ctx.session.userQuestionsHTML[ctx.session.userQuestionsPage - 1]) {
177+
reply_markup = Markup.inlineKeyboard([
178+
Markup.button.callback('<<', 'previous_page'),
179+
Markup.button.callback('>>', 'next_page')
180+
]).reply_markup
181+
} else {
182+
reply_markup = Markup.inlineKeyboard([
183+
Markup.button.callback('>>', 'next_page')
184+
]).reply_markup
185+
}
186+
187+
ctx.editMessageText(html, {
188+
parse_mode: 'HTML',
189+
disable_web_page_preview: true,
190+
reply_markup
191+
})
192+
} catch (e) {
193+
console.error(`Bot failed to process callback 'previous_page'\n` + e)
194+
}
195+
})
196+
104197
bot.action('update', async ctx => {
105198
try {
106199
await ctx.answerCbQuery()

src/services/userQuestionsService.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ async function getNextQuestion (userId) {
8484
}
8585

8686
/**
87-
* Get all the user questions.
87+
* Get all the user questions in ascending order of question id.
8888
* @param userId
89-
* @return {Promise<[object]>} an array of user questions with question details [{ _id, question: {...} }]
89+
* @return {Promise<[object]>} an array of user questions with question details [{ _id, question: [{...}] }]
9090
*/
9191
async function getAllUserQuestions (userId) {
9292
try {
@@ -104,6 +104,7 @@ async function getAllUserQuestions (userId) {
104104
as: 'question'
105105
}
106106
}])
107+
.sort({ questionId: 1 })
107108
.project({ question: 1 })
108109
.toArray()
109110
} catch (e) {

0 commit comments

Comments
 (0)