lcr 0.0.7

Happy Leetcoding with Rust
Documentation
#!/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()