#!/usr/bin/env python
import json
import os
import re
import time
from pprint import pprint
from requests.api import head
import codefast as cf
from codefast.argparser import ArgParser
from termcolor import colored
class LeetCode():
def __init__(self, header_file='local/leetcode_header.dat'):
self.s = cf.net.client
H = self._get_config(header_file)
self.s.headers.update(H)
self.title = ''
self.domain = re.findall(r'https://(.*).com/' ,H.get('referer', '') +H.get('Referer', ''))[0]
def _get_config(self, head_file):
return dict(x.split(': ')[:2] for x in cf.io.iter(head_file))
def init_code_env(self, title='two-sum'):
self.title = title
j = {
'operationName': "getQuestionDetail",
'query':
"query getQuestionDetail($titleSlug: String!) {\n isCurrentUserAuthenticated\n userStatus {\n isPremium\n __typename\n }\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n questionTitle\n translatedTitle\n questionTitleSlug\n content\n translatedContent\n difficulty\n stats\n allowDiscuss\n contributors {\n username\n profileUrl\n __typename\n }\n similarQuestions\n mysqlSchemas\n randomQuestionUrl\n sessionId\n categoryTitle\n submitUrl\n interpretUrl\n codeDefinition\n sampleTestCase\n enableTestMode\n metaData\n langToValidPlayground\n enableRunCode\n enableSubmit\n judgerAvailable\n infoVerified\n envInfo\n urlManager\n article\n questionDetailUrl\n libraryUrl\n topicTags {\n name\n slug\n translatedName\n __typename\n }\n __typename\n }\n subscribeUrl\n loginUrl\n}\n",
'variables': {
'titleSlug': title
}
}
r = self.s.post(f'https://{self.domain}.com/graphql/', json=j)
j = r.json()
details = j['data']['question']
difficulty, id, title, env = details['difficulty'], details[
'questionFrontendId'], details['questionTitleSlug'], details[
'codeDefinition']
# print(id, title, content, env)
env = json.loads(env)
def _code_file_name(extension: str):
return f"{id}.{title}.{extension}"
for nj in env:
_code = nj.get('defaultCode', '')
if nj['value'] == 'cpp':
continue
fname = _code_file_name('cpp')
os.system(f"cat conf.d/head.cpp > {fname}")
cf.io.write(_code, _code_file_name("cpp"), mode='a')
os.system(f"cat conf.d/tail.cpp >> {fname}")
elif nj['value'] == 'rust':
cf.io.write(_code, _code_file_name('rs'))
elif nj['value'] == 'c':
continue
cf.io.write(_code, _code_file_name('c'))
elif nj['value'] == 'python3':
continue
fname = _code_file_name('py')
os.system(f"cat conf.d/head.py > {fname}")
text = f'# https://leetcode.com/problems/{self.title}/description/\n# {difficulty}\n{_code}\n'
cf.io.write(text, _code_file_name('py'), mode='a')
elif nj['value'] == 'mysql':
creat_sql_codes = ';\n'.join(details['mysqlSchemas'] + [''])
tables = re.findall(r'Not Exists (.*?) \(', creat_sql_codes)
drop_tables_codes = 'drop tables ' + ', '.join(tables) + '; \n'
open('c.sh', 'w').write(drop_tables_codes + creat_sql_codes)
print(creat_sql_codes)
fname = f"{id}.{title}.sql"
os.system(f'touch {fname}')
# os.system(f'echo {creat_sql_codes} > c.sh')
def _read_code_file(self, fname='test.py'):
# Read codes from file, and ignore all debug lines,
# e.g., those with print commands .
text = cf.io.iter(fname)
res = ""
for line in text:
if line.startswith(('int main', 'struct Solution')):
return res
if not re.search('print\(|say|include', line):
res += line + "\n"
return res
def _get_id_from_sql(self, code_file):
'''Get Question ID from graphql
'''
title = '.'.join(code_file.split('.')[1:-1])
data = {
"operationName":
"getQuestionDetail",
"variables": {
"titleSlug": title
},
"query":
"query getQuestionDetail($titleSlug: String!) {\n isCurrentUserAuthenticated\n userStatus {\n isPremium\n __typename\n }\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n questionTitle\n translatedTitle\n questionTitleSlug\n content\n translatedContent\n difficulty\n stats\n allowDiscuss\n contributors {\n username\n profileUrl\n __typename\n }\n similarQuestions\n mysqlSchemas\n randomQuestionUrl\n sessionId\n categoryTitle\n submitUrl\n interpretUrl\n codeDefinition\n sampleTestCase\n enableTestMode\n metaData\n langToValidPlayground\n enableRunCode\n enableSubmit\n judgerAvailable\n infoVerified\n envInfo\n urlManager\n article\n questionDetailUrl\n libraryUrl\n topicTags {\n name\n slug\n translatedName\n __typename\n }\n __typename\n }\n subscribeUrl\n loginUrl\n}\n"
}
url = f'https://{self.domain}.com/graphql'
res = cf.net.post(url, json=data, verify=False)
return res.json()['data']['question']['questionId']
def submit_answer(self, code_file):
code = self._read_code_file(code_file)
bid = str(self._get_id_from_sql(code_file))
# Set submitted language. Either python3, cpp or rust.
langs = {
'py': 'python3',
'cpp': 'cpp',
'rs': 'rust',
'sql': 'mysql',
'java': 'java',
'c': 'c'
}
code_language = langs[code_file.split('.').pop()]
idata = {
"question_id": bid,
"data_input": "",
"lang": code_language,
"typed_code": code,
"test_mode": False,
"judge_type": "large"
}
cf.info('Submitting file: ', code_file)
cf.info('Backend id:', str(bid))
res = self.s.post(
f'https://{self.domain}.com/problems/customers-who-never-order/submit/',
json=idata,
verify=False)
msg = str(res) + res.text
cf.info(msg)
cf.info('Submission result copied to clipboard.')
os.system(
f"echo https://{self.domain}.com/submissions/detail/{res.json()['submission_id']}/ | pbcopy"
)
self._get_result(res.json()['submission_id'])
def _get_result(self, submission_id):
j = {
'operationName': "globalData",
'query':
"query globalData {\n feature {\n questionTranslation\n subscription\n signUp\n discuss\n mockInterview\n contest\n store\n chinaProblemDiscuss\n socialProviders\n studentFooter\n enableChannels\n dangerZone\n enableSharedWorker\n enableRecaptchaV3\n enableDebugger\n enableDebuggerPremium\n enableAutocomplete\n enableAutocompletePremium\n enableAllQuestionsRaw\n autocompleteLanguages\n enableIndiaPricing\n enableReferralDiscount\n maxTimeTravelTicketCount\n enableStoreShippingForm\n __typename\n }\n userStatus {\n isSignedIn\n isAdmin\n isStaff\n isSuperuser\n isMockUser\n isTranslator\n isPremium\n isVerified\n checkedInToday\n username\n realName\n avatar\n optedIn\n requestRegion\n region\n activeSessionId\n permissions\n notificationStatus {\n lastModified\n numUnread\n __typename\n }\n completedFeatureGuides\n __typename\n }\n siteRegion\n chinaHost\n websocketUrl\n recaptchaKey\n recaptchaKeyV2\n sitewideAnnouncement\n userCountryCode\n}\n",
'variables': {}
}
self.s.headers['referer'] = 'referer: https://leetcode.com/submissions/detail/{}/'.format(submission_id)
# j['variables']['id'] = submission_id
time.sleep(5)
j = self.s.post(f'https://{self.domain}.com/graphql/', json=j).json()
print(j)
return
details = j['data']['submissionDetail']
cf.info('Memory usage ' + details['memory'])
cf.info('Time usage ' + details['runtime'])
# self.calculate_runtime_rank(submission_id)
tp, tt = details['passedTestCaseCnt'], details["totalTestCaseCnt"]
cf.info('Test cased passed:' + f" {tp} / {tt}")
status = details['statusDisplay']
sign = colored(status, 'green') if status == 'Accepted' else colored(
status, 'red')
cf.info('Status: ' + sign)
def calculate_runtime_rank(self, submission_id):
headers = {'user-agent': 'Chrome'}
self.s.headers.update(headers)
j = self.s.get(
f'https://{self.domain}.com/submissions/api/runtime_distribution/{submission_id}/'
).text.json()
print(j)
if __name__ == "__main__":
ap = ArgParser()
ap.input(
'-d',
'--download',
description='Download question description and initiate code env.')
ap.input('-s', '--submit', description='Submit an solution.')
ap.parse()
lc = LeetCode()
if ap.download:
url = ap.download.value + '/description'
title = re.findall(r'problems/(.*?)(/description)',
url)[0][0].strip('/')
print(title)
lc.init_code_env(title)
elif ap.submit:
lc.submit_answer(ap.submit.value)
else:
ap.help()