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

feat(companies): Leet companies - view company list to filter problems by #92

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ image_support = false,
- `daily` opens the question of today

- `list` opens a problem list picker
-
- `companies` opens a list of companies to filter questions by

- `open` opens the current question in a default browser

Expand Down
10 changes: 10 additions & 0 deletions lua/leetcode-plugins/cn/queries.lua
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,13 @@ queries.session_progress = [[
}
}
]]

queries.streak = [[
query questionCompanyTags {
companyTags {
name
slug
questionCount
}
}
]]
20 changes: 14 additions & 6 deletions lua/leetcode-ui/group/page/problems.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local cmd = require("leetcode.command")
local config = require("leetcode.config")

local Title = require("leetcode-ui.lines.title")
local Button = require("leetcode-ui.lines.button.menu")
Expand Down Expand Up @@ -33,14 +34,21 @@ local daily = Button("Daily", {
on_press = cmd.qot,
})

local companies = Button("Companies", {
icon = "",
sc = "c",
on_press = cmd.companies,
})

local back = BackButton("menu")

page:insert(Buttons({
list,
random,
daily,
back,
}))
button_list = { list, random, daily }
if config.auth.is_premium then
table.insert(button_list, companies)
end
table.insert(button_list, back)

page:insert(Buttons(button_list))

page:insert(footer)

Expand Down
81 changes: 81 additions & 0 deletions lua/leetcode/api/companies.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
local utils = require("leetcode.api.utils")
local config = require("leetcode.config")
local log = require("leetcode.logger")
local queries = require("leetcode.api.queries")
local urls = require("leetcode.api.urls")
local Spinner = require("leetcode.logger.spinner")

---@class lc.CompaniesApi
local Companies = {}

---@param cb? fun(res: lc.cache.Company[]|nil, err: lc.err)
---@param noti? boolean
--
---@return lc.cache.Company[] lc.err
function Companies.all(cb, noti)
local query = queries.companies

local spinner
if noti then
spinner = Spinner:init("updating cache...", "points")
end
if cb then
utils.query(query, _, {
endpoint = urls.companies,
callback = function(res, err)
if err then
if spinner then
spinner:stop(err.msg, false)
end
return cb(nil, err)
end
local data = res.data
local companies = data["companyTags"]
if spinner then
spinner:stop("cache updated")
end
cb(companies)
end,
})
else
local res, err = utils.query(query)
if err then
if spinner then
spinner:stop(err.msg, false)
end
return nil, err
else
local data = res.data
local companies = data["companyTags"]
if spinner then
spinner:stop("cache updated")
end
return companies
end
end
end

function Companies.problems(company, cb)
local url = urls.company_problems:format(company)

if cb then
utils.get(url, {
callback = function(res, err)
if err then
return cb(nil, err)
end
local questions = res["questions"]
cb(questions)
end
})
else
local res, err = utils.get(url)
if err then
return nil, err
end
local questions = res.data["questions"]
return questions
end
end

return Companies
10 changes: 10 additions & 0 deletions lua/leetcode/api/queries.lua
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,14 @@ queries.session_progress = [[
}
]]

queries.companies = [[
query questionCompanyTags {
companyTags {
name
slug
questionCount
}
}
]]

return queries
6 changes: 6 additions & 0 deletions lua/leetcode/api/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,12 @@
---@field questions_count table<lc.Stats.QuestionCount>
---@field submit_stats lc.Stats.SubmissionStat

--------------------------------------------
--- Companies
--------------------------------------------
---@class lc.Companies.Res
---@field companyTags {name: string, slug: string, questionCount: number}[]

--------------------------------------------
--- Skills
--------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions lua/leetcode/api/urls.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ urls.base = "/graphql/"
urls.solved = "/graphql/"
urls.calendar = "/graphql/"
urls.languages = "/graphql/"
urls.companies = "/graphql/"
urls.skills = "/graphql/"
urls.auth = "/graphql/"

urls.problems = "/api/problems/%s/"
urls.company_problems = "/problems/tag-data/company-tags/%s/"
urls.interpret = "/problems/%s/interpret_solution/"
urls.submit = "/problems/%s/submit/"
urls.run = "/problems/%s/interpret_solution/"
Expand Down
23 changes: 23 additions & 0 deletions lua/leetcode/api/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,27 @@ function utils.translate_titles(problems, titles)
end, problems)
end

--@return lc.cache.Question[]
function utils.normalize_company_problems(problems)
return vim.tbl_map(function(p)
return {
status = p.status,
id = tonumber(p.questionId),
frontend_id = tonumber(p.questionFrontendId),
title = p.title,
title_cn = "",
title_slug = p.titleSlug,
link = ("https://leetcode.%s/problems/%s/"):format(
config.domain,
p.titleSlug
),
paid_only = p.isPaidOnly,
ac_rate = tonumber(p.acRate:sub(1, -2)),
difficulty = p.difficulty,
starred = false,
topic_tags = {},
}
end, problems)
end

return utils
123 changes: 123 additions & 0 deletions lua/leetcode/cache/companylist.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
local path = require("plenary.path")
local companies_api = require("leetcode.api.companies")

local log = require("leetcode.logger")
local config = require("leetcode.config")
local interval = config.user.cache.update_interval

---@type Path
local file = config.storage.cache:joinpath(("companylist%s"):format(config.is_cn and "_cn" or ""))

---@type { at: integer, payload: lc.cache.payload }
local hist = nil

---@class lc.cache.Company
---@field name string
---@field slug string
---@field questionCount number


---@class lc.cache.Copmanylist
local Companylist = {}

---@return lc.cache.Company[]
function Companylist.get()
return Companylist.read().data
end

---@return lc.cache.payload
function Companylist.read()
if not file:exists() then
return Companylist.populate()
end

local time = os.time()
if hist and (time - hist.at) <= math.min(60, interval) then
return hist.payload
end

local contents = file:read()
if not contents or type(contents) ~= "string" then
return Companylist.populate()
end

local cached = Companylist.parse(contents)

if not cached or (cached.version ~= config.version or cached.username ~= config.auth.name) then
return Companylist.populate()
end

hist = { at = time, payload = cached }
if (time - cached.updated_at) > interval then
Companylist.update()
end

return cached
end

---@return lc.cache.payload
function Companylist.populate()
local res, err = companies_api.all(nil, true)

if not res or err then
local msg = (err or {}).msg or "failed to fetch company list"
error(msg)
end

Companylist.write({ data = res })
return hist.payload
end

function Companylist.update()
companies_api.all(function(res, err)
if not err then
Companylist.write({ data = res })
end
end, true)
end

---@return lc.cache.Company
function Companylist.get_by_title_slug(title_slug)
local companies = Companylist.get()

local company = vim.tbl_filter(function(e)
return e.title_slug == slug
end, companies)[1]

assert(company("Company `%s` not found. Try updating cache?"):format(title_slug))
return company
end

---@param payload? lc.cache.payload
function Companylist.write(payload)
payload = vim.tbl_deep_extend("force", {
version = config.version,
updated_at = os.time(),
username = config.auth.name,
}, payload)

if not payload.data then
payload.data = Companylist.get()
end

file:write(vim.json.encode(payload), "w")
hist = { at = os.time(), payload = payload }
end

---@alias lc.cache.payload { version: string, data: lc.cache.Company[], updated_at: integer, username: string }

---@param str string
---
---@return lc.cache.payload
function Companylist.parse(str)
return vim.json.decode(str)
end

function Companylist.delete()
if not file:exists() then
return false
end
return pcall(path.rm, file)
end

return Companylist
5 changes: 5 additions & 0 deletions lua/leetcode/cache/init.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
local config = require("leetcode.config")
local Problemlist = require("leetcode.cache.problemlist")
local Companylist = require("leetcode.cache.companylist")

---@class lc.Cache
local cache = {}

function cache.update()
Problemlist.update()
if config.auth.is_premium then
Companylist.update()
end
end

return cache
17 changes: 17 additions & 0 deletions lua/leetcode/command/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ function cmd.problems(options)
require("leetcode.pickers.question").pick(p, options)
end

---@param options table<string, string[]>
function cmd.companies(options)
require("leetcode.utils").auth_guard()
if not config.auth.is_premium then
err.msg = "Selecting problems by company is only for premium."
err.lvl = vim.log.levels.WARN
return nil, err
end

local c = require("leetcode.cache.companylist").get()
require("leetcode.pickers.company").pick(c, options)
end

---@param cb? function
function cmd.cookie_prompt(cb)
local cookie = require("leetcode.cache.cookie")
Expand Down Expand Up @@ -635,6 +648,10 @@ cmd.commands = {
cmd.problems,
_args = arguments.list,
},
companies = {
cmd.companies,
_args = arguments.list,
},
random = {
cmd.random_question,
_args = arguments.random,
Expand Down
Loading