#!/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()