Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
 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')
Exemplo n.º 4
0
    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')
Exemplo n.º 5
0
    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))
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
    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))
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
    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