def submit_code(self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> onlinejudge.type.Submission: """ :raises NotLoggedInError: """ # NOTE: An implementation with the official API exists at 492d8d7. This is reverted at 2b7e6f5 because the API ignores cookies and says "提出するにはログインが必要です" at least at that time. session = session or utils.get_default_session() # get url = self.get_url() + '/submit' resp = utils.request('GET', url, session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.HTML_PARSER) form = soup.find('form', id='submit_form') if not form: logger.error('form not found') raise NotLoggedInError # post form = utils.FormSender(form, url=resp.url) form.set('lang', language_id) form.set_file('file', filename or 'code', code) form.unset('custom_test') resp = form.request(session=session) resp.raise_for_status() # result if 'submissions' in resp.url: # example: https://yukicoder.me/submissions/314087 logger.info('success: result: %s', resp.url) return utils.DummySubmission(resp.url, problem=self) else: logger.error('failure') soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.HTML_PARSER) for div in soup.findAll('div', attrs={'role': 'alert'}): logger.warning('yukicoder says: "%s"', div.string) raise SubmissionError
def submit_code(self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> onlinejudge.type.Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ session = session or utils.get_default_session() if not self.get_service().is_logged_in(session=session): raise NotLoggedInError # get resp = utils.request('GET', self.get_url(), session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) csrftoken = soup.find('meta', attrs={'name': 'csrf-token'}).attrs['content'] # post url = 'https://www.hackerrank.com/rest/contests/{}/challenges/{}/submissions'.format(self.contest_slug, self.challenge_slug) payload = {'code': code, 'language': str(language_id), 'contest_slug': self.contest_slug} logger.debug('payload: %s', payload) resp = utils.request('POST', url, session=session, json=payload, headers={'X-CSRF-Token': csrftoken}) # parse it = json.loads(resp.content.decode()) logger.debug('json: %s', it) if not it['status']: logger.error('Submit Code: failed') raise SubmissionError model_id = it['model']['id'] url = self.get_url().rstrip('/') + '/submissions/code/{}'.format(model_id) logger.info('success: result: %s', url) return utils.DummySubmission(url, problem=self)
def submit_code(self, code: bytes, language_id: LanguageId, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ assert language_id in [ language.id for language in self.get_available_languages(session=session) ] session = session or utils.new_default_session() # get url = 'http://{}.contest.atcoder.jp/submit'.format( self.contest_id) # TODO: use beta.atcoder.jp resp = _request('GET', url, session=session) msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): raise SubmissionError # check whether logged in path = utils.normpath(urllib.parse.urlparse(resp.url).path) if path.startswith('/login'): log.error('not logged in') raise NotLoggedInError # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', action=re.compile(r'^/submit\?task_id=')) if not form: log.error('form not found') raise SubmissionError log.debug('form: %s', str(form)) # post task_id = self._get_task_id(session=session) form = utils.FormSender(form, url=resp.url) form.set('task_id', str(task_id)) form.set('source_code', code) form.set('language_id_{}'.format(task_id), str(language_id)) resp = form.request(session=session) resp.raise_for_status() # result msgs = AtCoderService._get_messages_from_cookie(resp.cookies) AtCoderService._report_messages(msgs) if '/submissions/me' in resp.url: # example: https://practice.contest.atcoder.jp/submissions/me#32174 # CAUTION: this URL is not a URL of the submission log.success('success: result: %s', resp.url) # NOTE: ignore the returned legacy URL and use beta.atcoder.jp's one url = 'https://beta.atcoder.jp/contests/{}/submissions/me'.format( self.contest_id) return utils.DummySubmission(url, problem=self) else: log.failure('failure') log.debug('redirected to %s', resp.url) raise SubmissionError('it may be a rate limit')
def submit_code(self, code: bytes, language_id: LanguageId, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ assert language_id in [ language.id for language in self.get_available_languages(session=session) ] session = session or utils.new_default_session() # get url = 'https://atcoder.jp/contests/{}/submit'.format(self.contest_id) resp = _request('GET', url, session=session) # check whether logged in if 'login' in resp.url: raise NotLoggedInError # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', action='/contests/{}/submit'.format(self.contest_id)) if not form: raise SubmissionError('something wrong') log.debug('form: %s', str(form)) # post form = utils.FormSender(form, url=resp.url) form.set('data.TaskScreenName', self.problem_id) form.set('data.LanguageId', str(language_id)) form.set('sourceCode', code) resp = form.request(session=session) _list_alert(resp, print_=True) # result if '/submissions/me' in resp.url: # example: https://practice.contest.atcoder.jp/submissions/me#32174 # CAUTION: this URL is not a URL of the submission log.success('success: result: %s', resp.url) return utils.DummySubmission(resp.url, problem=self) else: raise SubmissionError('it may be a rate limit')
def submit_code( self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None ) -> onlinejudge.type.Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ session = session or utils.get_default_session() # get resp = utils.request('GET', self.get_url(), session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', class_='submitForm') if form is None: log.error('not logged in') raise NotLoggedInError log.debug('form: %s', str(form)) # make data form = utils.FormSender(form, url=resp.url) form.set('programTypeId', language_id) form.set_file('sourceFile', filename or 'code', code) resp = form.request(session=session) resp.raise_for_status() # result if resp.url.endswith('/my'): # example: https://codeforces.com/contest/598/my log.success('success: result: %s', resp.url) return utils.DummySubmission(resp.url, problem=self) else: log.failure('failure') # parse error messages soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) msgs = [] # type: List[str] for span in soup.findAll('span', class_='error'): msgs += [span.string] log.warning('Codeforces says: "%s"', span.string) raise SubmissionError( 'it may be the "You have submitted exactly the same code before" error: ' + str(msgs))
def submit_code( self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None ) -> onlinejudge.type.Submission: """ :raises NotLoggedInError: """ session = session or utils.get_default_session() # get url = self.get_url() + '/submit' resp = utils.request('GET', url, session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', id='submit_form') if not form: log.error('form not found') raise NotLoggedInError # post form = utils.FormSender(form, url=resp.url) form.set('lang', language_id) form.set_file('file', filename or 'code', code) form.unset('custom_test') resp = form.request(session=session) resp.raise_for_status() # result if 'submissions' in resp.url: # example: https://yukicoder.me/submissions/314087 log.success('success: result: %s', resp.url) return utils.DummySubmission(resp.url, problem=self) else: log.failure('failure') soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) for div in soup.findAll('div', attrs={'role': 'alert'}): log.warning('yukicoder says: "%s"', div.string) raise SubmissionError
def submit_code(self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> Submission: """ :raises NotImplementedError: :raises SubmissionError: """ session = session or utils.get_default_session() # get resp = utils.request('GET', self.get_url(), session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form') if form is None: log.error('not logged in') raise LoginError log.debug('form: %s', str(form)) if form.find('select' ) and form.find('select').attrs['name'] != 'languageId': log.error("Wrong submission URL") raise SubmissionError # make data form = utils.FormSender(form, url=resp.url) form.set('languageId', language_id) form.set_file('source', 'code', code) resp = form.request(session=session) resp.raise_for_status() # result if '/s/' in resp.url: # example: https://toph.co/s/201410 log.success('success: result: %s', resp.url) return utils.DummySubmission(resp.url, problem=self) else: log.failure('failure') log.debug('redirected to %s', resp.url) raise SubmissionError
def submit_code( self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None ) -> onlinejudge.type.Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ session = session or utils.get_default_session() # get resp = utils.request('GET', self.get_url(), session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', class_='submitForm') if form is None: logger.error('not logged in') raise NotLoggedInError logger.debug('form: %s', str(form)) # make data form = utils.FormSender(form, url=resp.url) form.set('programTypeId', language_id) form.set_file('sourceFile', filename or 'code', code) # post preserved_user_agent = session.headers.get('User-Agent') logger.debug( 'User-Agent is temporarily disabled. The old User-Agent is %s', repr(preserved_user_agent)) try: if preserved_user_agent is not None: del session.headers['User-Agent'] resp = form.request(session=session, raise_for_status=False) finally: if preserved_user_agent is not None: session.headers['User-Agent'] = preserved_user_agent try: resp.raise_for_status() except requests.exceptions.HTTPError as e: logger.exception(e) if resp.status_code == 403: logger.warning('You may use wrong User-Agent: %s', repr(session.headers.get('User-Agent'))) raise SubmissionError( 'You may use wrong User-Agent: {}: {}'.format( repr(session.headers.get('User-Agent')), e)) raise e # result if resp.url.endswith('/my'): # example: https://codeforces.com/contest/598/my logger.info('success: result: %s', resp.url) return utils.DummySubmission(resp.url, problem=self) else: logger.error('failure') # parse error messages soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) msgs = [] # type: List[str] for span in soup.findAll('span', class_='error'): msgs += [span.string] logger.warning('Codeforces says: "%s"', span.string) raise SubmissionError( 'it may be the "You have submitted exactly the same code before" error: ' + str(msgs))
def submit_code(self, code: bytes, language_id: LanguageId, filename: Optional[str] = None, session: Optional[requests.Session] = None, kind: str = 'example') -> onlinejudge.type.Submission: """ :param kind: must be one of `example` (default) or `full` :raises NotLoggedInError: :raises SubmissionError: """ assert kind in ['example', 'full'] session = session or utils.new_default_session() # TODO: implement self.is_logged_in() # if not self.is_logged_in(session=session): # raise NotLoggedInError # module=MatchDetails url = 'https://community.topcoder.com/tc?module=MatchDetails&rd=%d' % self.rd resp = utils.request('GET', url, session=session) soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) path = soup.find('a', text='Register/Submit').attrs['href'] assert path.startswith('/') and 'module=ViewReg' in path # module=ViewActiveContests url = 'https://community.topcoder.com' + path resp = utils.request('GET', url, session=session) soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) path = [tag.attrs['href'] for tag in soup.find_all('a', text='Submit') if ('rd=%d' % self.rd) in tag.attrs['href']] if len(path) == 0: log.error('link to submit not found: Are you logged in? Are you registered? Is the contest running?') raise SubmissionError('something wrong') assert len(path) == 1 path = path[0] assert path.startswith('/') and 'module=Submit' in path query = dict(urllib.parse.parse_qsl(urllib.parse.urlparse(path).query)) self.cd = query['cd'] self.compid = query['compid'] # module=Submit submit_url = 'https://community.topcoder.com' + path resp = utils.request('GET', submit_url, session=session) soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) # post url = 'https://community.topcoder.com/longcontest/' data = { 'module': 'Submit', 'rd': self.rd, 'cd': self.cd, 'compid': self.compid, 'Action': 'submit', 'exOn': { 'example': 'true', 'full': 'false' }[kind], 'lid': str(language_id), 'code': code, } resp = utils.request('POST', url, session=session, data=data) # check if module=SubmitSuccess if 'module=SubmitSuccess' in resp.content.decode(resp.encoding): url = 'http://community.topcoder.com/longcontest/?module=SubmitSuccess&rd={}&cd={}&compid={}'.format(self.rd, self.cd, self.compid) log.success('success: result: %s', url) return utils.DummySubmission(url, problem=self) else: # module=Submit to get error messages resp = utils.request('GET', submit_url, session=session) soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) messages = soup.find('textarea', {'name': 'messages'}).text log.failure('%s', messages) raise SubmissionError('it may be a rate limit: ' + messages)
def submit_code( self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None ) -> onlinejudge.type.Submission: """ :raises NotLoggedInError: :raises SubmissionError: """ session = session or utils.get_default_session() # get url = 'https://kcs.miz-miz.biz/contest/{}/submit/{}'.format( self.contest_id, self.problem_id) resp = utils.request('GET', url, session=session) # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.HTML_PARSER) form = soup.find('form', id='submission_data') if form is None: raise NotLoggedInError logger.debug('form: %s', str(form)) # post form = utils.FormSender(form, url=resp.url) form.set('language', language_id) form.set('code', code) try: resp = form.request(session=session) except requests.exceptions.HTTPError as e: raise SubmissionError from e # result if '/submissions' in resp.url: # parse the individual submission page submission_url = resp.url try: url = 'https://kcs.miz-miz.biz/contest/{}/submissions?json=True'.format( self.contest_id) resp = utils.request('GET', url, session=session) submissions = json.loads(resp.content.decode(resp.encoding)) submission_id = max([ submission['submission_id'] for submission in submissions ]) submission_url = 'https://kcs.miz-miz.biz/contest/{}/code/{}'.format( self.contest_id, submission_id) except: logger.exception( 'failed to find the individual submission page. use the list page of all submissions instead.' ) # return the url of the submission page logger.info('success: result: %s', submission_url) return utils.DummySubmission(submission_url, problem=self) else: logger.error('failure') raise SubmissionError