def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: # this one's a little different, all form stepping is in javascript # persist same form between handlers, don't submit until end self.set_registration_type(user) form = self.browser.get_form() handlers = [ self.eligibility, self.voter_information, self.address, self.previous_info, self.review_affirm, self.email_receipt ] for handler in handlers: handler(user, form) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: forms = [ self.language, self.init_voter_registration, self.eligibility, self.personal_information, self.change_of_address, self.update_address, self.confirm_address, self.register_to_vote, self.verify_voter_registration, self.vote_by_mail ] for handler in forms: handler(user) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: forms = [ self.identification, ] for handler in forms: handler(user) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: forms = [ self.step1, self.step2, self.step3, self.step4, self.step5 ] for handler in forms: step_form = self.browser.get_form() if step_form: handler(step_form, user) errors = self.parse_errors(step_form) if errors: raise ValidationError(message='field_errors', payload=errors) if not step_form: raise ValidationError(message='no_form_found', payload=handler.__name__) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: self.validate(user) # format is: [kwargs to select / identify form, method to call with form] # frustratingly, MA uses the same methods and IDs for each form... forms = [[{ 'action': "./MinRequirements.aspx?RMVId=True" }, self.minimum_requirements], [{ 'action': "./FormAndReview.aspx?RMVId=True" }, self.rmv_identification], [{ 'action': "./FormAndReview.aspx?RMVId=True" }, self.complete_form], [{ 'action': "./FormAndReview.aspx?RMVId=True" }, self.review]] for form_kwargs, handler in forms: step_form = self.browser.get_form(**form_kwargs) if step_form: handler(user, step_form) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) if not step_form: raise ValidationError(message='no_form_found', payload=handler.__name__) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: return {'status': 'failure'} except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def step3(self, form, user): # Vote by Mail vote_by_mail_choice = bool_to_string(user.get('vote_by_mail', False), capitalize=True) # I want to get my ballot by mail before each election. form['IsPermanentVBM'].value = vote_by_mail_choice # I want to get my state voter information guide by mail before each statewide election. form['IsVIG'].value = vote_by_mail_choice # I want to get my sample ballot by mail before each election. form['IsSampleBallot'].value = vote_by_mail_choice # Consent to Use Signature if user.get('consent_use_signature'): form['ConsentToUseSignature'].value = "True" else: raise ValidationError(message='consent_use_signature must be True', payload=user['consent_use_signature']) # Affirmation user_is_eligible = user['us_citizen'] and user['will_be_18'] and ( not user['disenfranchised']) # also add "information is true and correct"? form['Affirmation'].value = bool_to_string(user_is_eligible) form['Affirmation'].checked = 'checked' # not capitalized the same as other fields form['CanBePollWorker'].value = 'false' form['CanProvidePollingPlace'].value = 'false' self.submit_form_field(form, 'GoToNext')
def submit(self, user, error_callback_url): self.set_user_agent(user) self.error_callback_url = error_callback_url try: self.drivers_license(user) self.citizenship(user) self.age_verification(user) self.application_type(user) self.illinois_identification(user) self.illinois_name(user) self.illinois_address(user) self.illinois_personal_info(user) self.illinois_email(user) self.illinois_election_authority(user) self.illinois_mailing_address(user) self.illinois_different_name(user) self.illinois_different_address(user) self.illinois_assisting(user) self.illinois_summary(user) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url # KY doesn't have intermediate forms, they just submit as JSON all at once # assemble the data dict iteratively, to match style of other states form_data = {} try: steps = [ self.requirements, self.check_existing, self.personal_information, self.party_affiliation, self.address, self.signature ] for handler in steps: handler(user, form_data) r = self.browser.session.post( 'https://vrsws.sos.ky.gov/EVRwcf/EVRwcf.Service1.svc/UpdateVoter', json=form_data, headers={ 'X-Requested-With': 'XMLHttpRequest', 'Referer': 'https://vrsws.sos.ky.gov/ovrweb/' }) success_page = r.content if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def full_registration(self, user): # if given choice to register online, choose pdf form if self.browser.get_form(id='state_ovr'): finish_form = self.browser.get_form(id='finish') self.browser.submit_form(finish_form) full_form = self.browser.get_form(id='full_registration') if full_form: # BUG, user.get(field, '') results in silent 400 errors, wtf? # full_form['title'].value = user.get('title', '') # print 'set title', full_form['title'].value # full_form['suffix'].value = user.get('suffix', '') # print 'set suffix', full_form['suffix'].value full_form['state_id_number'].value = user['state_id_number'] party_translated = get_party_from_list(user.get('political_party'), options_dict(full_form['political_party']).keys()) if not party_translated: party_translated = 'No party' full_form['political_party'].value = options_dict(full_form['political_party'])[party_translated] # why does the form require bool as string? full_form['us_citizen'].value = str(bool_to_int(user['us_citizen'])) self.browser.submit_form(full_form) else: errors_string = ','.join(self.parse_errors()) raise ValidationError(message='unable to get_form full_registration.', payload=errors_string)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: # format is: [kwargs to select / identify form, method to call with form] forms = [ [{}, self.welcome], [{}, self.minimum_requirements], [{}, self.personal_information], [{}, self.consent_use_signature], [{ 'id': 'formId' }, self.residence_address ], # there are two forms on this page, but one is blank [{}, self.general_information], [{}, self.review_information], [{}, self.confirmation_email], ] for form_kwargs, handler in forms: step_form = self.browser.get_form(**form_kwargs) if step_form: handler(user, step_form) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) if not step_form: raise ValidationError(message='no_form_found', payload=handler.__name__) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def validate(self, user): self.check_required_fields(user) if self.errors: self.errors.append({ 'validate_state': user['state'] }) # append state to error dict, so we can debug in logs raise ValidationError(message='missing_fields', payload=self.errors)
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: self.validate(user) # format is: [kwargs to select / identify form, method to call with form] forms = [ [{ 'id': 'verifyNewVoterForm' }, self.verify_identification], [ {}, self.new_or_existing_voter ], # this splits between verify_eligibility, edit_voter_information [{ 'id': 'reviewVoterForm' }, self.review], [{ 'id': 'affirmationVoterForm' }, self.affirmation] ] for form_kwargs, handler in forms: step_form = self.browser.get_form(**form_kwargs) handler(user, step_form) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) if not step_form: raise ValidationError(message='no_form_found', payload=handler.__name__) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: raise ValidationError(message='no_success_string') except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def step1(self, form, user): if user['us_citizen'] and (user['state'].upper() == 'CA'): form['ClassificationType'].value = '1' # default check 'A U.S. citizen residing in California.' else: raise ValidationError(message='must be US citizen residing in California to register', payload={ 'us_citizen': user['us_citizen'], 'state': user['state'] }) self.submit_form_field(form, 'GoToNext')
def lookup_existing_record(self, form): if not form['ssn']: raise ValidationError( message= 'We need your Social Security number to look up your existing voter registration' ) if not form['dob']: raise ValidationError( message= 'We need your date of birth to look up your existing voter registration' ) form['ssn_no_sep'] = form['ssn'].replace('-', '') r = self.browser.session.get( 'https://vrsws.sos.ky.gov/EVRwcf/EVRwcf.Service1.svc/getVoterData/%(ssn_no_sep)s/%(dob)s' % form, headers={'Referer': 'https://vrsws.sos.ky.gov/ovrweb/'}) del form['ssn_no_sep'] return r.json()
def get_address_from_freeform(address): client = Client(auth_id=SMARTY_STREETS_AUTH_ID, auth_token=SMARTY_STREETS_AUTH_TOKEN) response = client.street_address(str(address)) if not response or not response.get('analysis', False) or \ response['analysis'].get('active', 'N') != 'Y': raise ValidationError("could not validate freeform address", payload={"address": address}) return response
def requirements(self, user, form): # check answers to requirements, but don't actually submit to state if not user['us_citizen']: raise ValidationError( message= 'You must be a US citizen to register to vote in Kentucky') if not user['legal_resident']: raise ValidationError( message= 'You must be a current resident of Kentucky to register to vote' ) if not user['will_be_18']: raise ValidationError( message= 'You must be at least 18 years of age on or before the next general election.' ) if user['disenfranchised']: raise ValidationError( message= 'You must not be a convicted felon, or if your have been convicted of a felony, your civil rights must be restored by executive pardon.' ) if user['incompetent']: raise ValidationError( message= 'You must not have not been judged "mentally incompetent" in a court of law.' ) if user['claim_elsewhere']: raise ValidationError( message= 'You must not claim the right to vote anywhere outside Kentucky' ) # individual registration, not part of high school or college registration drive form['regsrc'] = 'in'
def general_information(self, user, form): # these fields are all optional, fill in only if defined if user.get('gender'): form['gender'].options = [ 'Male', 'Female' ] # they have two buttons with the same name but different ids gender_str = parse_gender( user['gender']) # coerces free text to M/F if gender_str is 'F': form['gender'].value = 'Female' elif gender_str is 'M': form['gender'].value = 'Male' else: raise ValidationError(message='parse_gender error', payload=user['gender']) # poll_worker if user.get('ssn_last_4'): form['ssnId'] = user['ssn_last_4'] # also accepts full SSN, but no dashes if user.get('email'): form['emailId'] = user['email'] if user.get('phone'): form['telephone'] = user['phone'] # format? # ethnicity requires a dropdown, and is optional # skip it # previous address appears here if user.get('has_previous_address'): prev_address_components = get_address_components( user['previous_address'], user['previous_city'], user['previous_state'], user['previous_zip']) form['preStreetNo'].value = prev_address_components[ 'primary_number'] form['preStreetName'].value = get_street_name_from_components( prev_address_components).upper() if 'secondary_number' in prev_address_components: form['preAptNo'].value = prev_address_components[ 'secondary_number'] form['prePostalCity'].value = prev_address_components['city_name'] form[ 'ctl00$MainContent$TxtPrevRegZip'].value = prev_address_components[ 'zipcode'] form['preState'].value = prev_address_components[ 'state_abbreviation'] form.action = 'summary.do' self.browser.submit_form(form, submit=form['next']) return form
def submit(self, user, error_callback_url=None): self.set_user_agent(user) self.error_callback_url = error_callback_url try: # format is: [kwargs to select / identify form, method to call with form] forms = [ [{}, self.voting_eligibility], [{}, self.voting_identity], [{}, self.protected_voter], [{}, self.overseas_classification], [{}, self.absentee_ballot], [{}, self.residence_address], [{}, self.contact_information], [{}, self.affirmation] ] for form_kwargs, handler in forms: step_form = self.browser.get_form(**form_kwargs) if step_form: handler(user, step_form) errors = self.parse_errors() if errors: raise ValidationError(message='field_errors', payload=errors) if not step_form: raise ValidationError(message='no_form_found', payload=handler.__name__) success_page = clean_browser_response(self.browser) if self.success_string in success_page: return {'status': 'success'} else: return {'status': 'failure'} except ValidationError, e: raise OVRError(self, message=e.message, payload=e.payload, error_callback_url=self.error_callback_url)
def edit_voter_information(self, user, form): party_options = options_dict(form['editVoterForm:partyAffiliationId']) # do fuzzy match to political party options party = get_party_from_list(user['political_party'], party_options.keys()) # it is required. if we haven't found a match, defer to 'Unaffiliated' if not party: party = 'Unaffiliated' form['editVoterForm:partyAffiliationId'].value = party_options[party] if user['military_or_overseas']: form['editVoterForm:areUOCAVAId'].value = 'Y' form['editVoterForm:uocavaTypeId'].value = 'a' if user[ 'military_or_overseas'] == 'military' else 'c' else: form['editVoterForm:areUOCAVAId'].value = 'N' form['editVoterForm:uocavaBallotMethodId'].value = 'Mail' if user[ 'vote_by_mail'] else 'Email' # or 'Fax' # email, phone and gender are prefilled form['editVoterForm:emailId'].value = user['email'] form[ 'editVoterForm:receiveEmailCommunicationId'].checked = 'checked' if user[ 'email'] else '' if 'phone' in user: # strip country prefix form['editVoterForm:phoneId'].value = user['phone'].replace( '+1', '') gender_str = parse_gender(user['gender']) if gender_str is 'F': form['editVoterForm:genderSelectId'].value = '0' elif gender_str is 'M': form['editVoterForm:genderSelectId'].value = '1' else: raise ValidationError(message='parse_gender error', payload=user['gender']) form['editVoterForm:resAddress'].value = user['address'] form['editVoterForm:resCity'].value = user['city'] form['editVoterForm:resCounty'].value = options_dict( form['editVoterForm:resCounty'])[user['county']] form['editVoterForm:resZip'].value = user['zip'] self.browser.submit_form(form, submit=form['editVoterForm:j_idt114'])
def illinois_identification(self, user): self.browser.open('https://ova.elections.il.gov/Step4.aspx') illinois_identification_form = self.browser.get_form() if user.get('state_id_number'): if user['state_id_number'][0].isalpha(): illinois_identification_form[ 'ctl00$MainContent$tbILDLIDNumber'] = user[ 'state_id_number'][0:4] illinois_identification_form[ 'ctl00$MainContent$tbILDLIDNumber2'] = user[ 'state_id_number'][4:8] illinois_identification_form[ 'ctl00$MainContent$tbILDLIDNumber3'] = user[ 'state_id_number'][8:12] else: raise ValidationError( message= 'A valid Illinois ID number must start with a letter') else: raise ValidationError( message= 'A valid Illinois ID number is required to register to vote online' ) (dob_year, dob_month, dob_day) = split_date(user['date_of_birth']) illinois_identification_form[ 'ctl00$MainContent$tbDOB'].value = '-'.join( [dob_month, dob_day, dob_year]) (id_year, id_month, id_day) = split_date(user['state_id_issue_date']) illinois_identification_form[ 'ctl00$MainContent$tbIDIssuedDate'].value = '-'.join( [id_month, id_day, id_year]) self.browser.submit_form( illinois_identification_form, submit=illinois_identification_form['ctl00$MainContent$btnNext'])
def set_registration_type(self, user): token = self.browser.find( "input", {"name": "__RequestVerificationToken"})['value'] request_data = { 'HaveDL': True if 'state_id_number' in user else False, 'Source': '' } r = self.browser.session.post( 'https://olvr.sec.state.vt.us/Registration/SavetheRequest', request_data, headers={ '__RequestVerificationToken': token, 'X-Requested-With': 'XMLHttpRequest' }) if (r.status_code >= 400): raise ValidationError(message='unable to get token') self.browser.open( 'https://olvr.sec.state.vt.us/Registration/RegistrationDetails', headers={'__RequestVerificationToken': token})
def submit_form_field(self, form, name): submit_button = form[name] submit_value = submit_button.value # weird workaround required to add a hidden copy of the same value # required so that the state sends us a 302 redirect, instead of a 404 form.add_field(Input("<input type='hidden' name='%s' value='%s' />" % (name, submit_value))) self.browser.submit_form(form, submit=submit_button) response = self.browser.state.response if response.status_code == 302: self.browser.open('https://covr.sos.ca.gov'+response.headers['Location']) else: raise ValidationError(message='unable to submit', payload={ 'url': self.browser.state.url, 'form': { 'action': form.action, 'data': form.serialize().data, 'status_code': response.status_code } })
def get_address_components(address, city, state, zip): client = Client(auth_id=SMARTY_STREETS_AUTH_ID, auth_token=SMARTY_STREETS_AUTH_TOKEN) # reassemble components into string # smarty streets specifically wants strings (not unicode) so... full_address = "%(address)s, %(city)s, %(state)s, %(zip)s" % \ {'address': str(address), 'city': str(city), 'state': str(state), 'zip': str(zip)} response = client.street_address(str(full_address)) if not response or not response.get('analysis', False) or \ response['analysis'].get('active', 'N') != 'Y': raise ValidationError("could not validate address", payload={ "address": address, "city": city, "state": state, "zip": zip }) # merge county into components dict d = response['components'] d['county_name'] = response['metadata']['county_name'] return d
def complete_form(self, user, form): address_components = get_address_components(user['address'], user['city'], user['state'], user['zip']) form['ctl00$MainContent$txtStNum'].value = address_components[ 'primary_number'] street_name = get_street_name_from_components(address_components) form['ctl00$MainContent$txStNameSuffix'].value = street_name[:25] if user.get('address_unit' ) and not user.get('address_unit').lower() == "none": form['ctl00$MainContent$txtUnitApt'].value = user.get( 'address_unit') if 'street_suffix' in address_components: street_suffix_options = options_dict( form['ctl00$MainContent$ddlStreetSuffix']) try: form[ 'ctl00$MainContent$ddlStreetSuffix'].value = street_suffix_options[ address_components['street_suffix'].upper()] except KeyError: form[ 'ctl00$MainContent$ddlStreetSuffix'].value = street_suffix_options[ 'No suffix'] city_normalized = MA_ARCHAIC_COMMUNITIES.get(user['city'], user['city']) try: form['ctl00$MainContent$ddlCityTown'].value = options_dict( form['ctl00$MainContent$ddlCityTown'])[city_normalized] except KeyError: raise ValidationError( message='unable to find city in MA CityTown list', payload=user['city']) form['ctl00$MainContent$txtZip'].value = user['zip'] user_party = user['political_party'].strip() parties = options_dict(form['ctl00$MainContent$ddlPartyList']) designations = options_dict( form['ctl00$MainContent$ddlPoliticalDesig']) party = get_party_from_list(user_party, parties.keys()) designation = get_party_from_list(user_party, designations.keys()) user_party = user_party.lower() if user_party and user_party != 'independent' and user_party != 'none': if party: form['ctl00$MainContent$PartyEnrolled'].value = 'rdoBtnParty' # crucial - un-disable the party list del self.browser.select( 'select[name="ctl00$MainContent$ddlPartyList"]' )[0]['disabled'] form['ctl00$MainContent$ddlPartyList'].value = parties[party] elif designation: form[ 'ctl00$MainContent$PartyEnrolled'].value = 'rdoBtnPolDesig' # crucial - un-disable the designation list del self.browser.select( 'select[name="ctl00$MainContent$ddlPoliticalDesig"]' )[0]['disabled'] form[ 'ctl00$MainContent$ddlPoliticalDesig'].value = designations[ designation] else: # unable to match designation, unenrolled self.add_error( "We were unable to match that political designation", field='political_party') form['ctl00$MainContent$PartyEnrolled'].value = 'rdoBtnNoParty' else: # No Party (Unenrolled, commonly referred to as ''Independent'') form['ctl00$MainContent$PartyEnrolled'].value = 'rdoBtnNoParty' # phone number, optional if user.get('phone'): phone = user.get('phone').replace('+1', '') form['ctl00$MainContent$txtAreaCode'].value = phone[0:3] form['ctl00$MainContent$txtPhone3'].value = phone[3:6] form['ctl00$MainContent$txtPhone4'].value = phone[6:10] # separate mailing address if user.get('has_separate_mailing_address'): form['ctl00$MainContent$ChkDiffMailAddr'].checked = 'checked' form['ctl00$MainContent$ChkDiffMailAddr'].value = 'on' # remove the disabled attr on the relevant fields del self.browser.select( 'input[name="ctl00$MainContent$txtDiffStNamePO"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$txtDiffUnitApt"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$txtDiffCityTownCounty"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$txtDiffZip"]')[0]['disabled'] del self.browser.select( 'select[name="ctl00$MainContent$ddlDiffStateTerr"]' )[0]['disabled'] # parse mailing address components mailing_address = get_address_from_freeform( user['separate_mailing_address']) mailing_components = mailing_address['components'] # update fields with mailing address data form[ 'ctl00$MainContent$txtDiffStNamePO'].value = get_street_address_from_components( mailing_components) if mailing_components.get('secondary_number'): form[ 'ctl00$MainContent$txtDiffUnitApt'].value = get_address_unit_from_components( mailing_components) form[ 'ctl00$MainContent$txtDiffCityTownCounty'].value = mailing_components[ 'city_name'] form['ctl00$MainContent$txtDiffZip'].value = mailing_components[ 'zipcode'] form[ 'ctl00$MainContent$ddlDiffStateTerr'].value = mailing_components[ 'state_abbreviation'] # former name if user.get('has_previous_name'): prev_first, prev_middle, prev_last = split_name( user.get('previous_name')) del self.browser.select( 'input[name="ctl00$MainContent$txtFirstNameFormer"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$txtLastNameFormer"]' )[0]['disabled'] form['ctl00$MainContent$txtFirstNameFormer'].value = prev_first form['ctl00$MainContent$txtLastNameFormer'].value = prev_last # address where you were last registered to vote if user.get('has_previous_address'): form['ctl00$MainContent$ChkPrevRegAddr'].checked = 'checked' form['ctl00$MainContent$ChkPrevRegAddr'].value = 'on' # remove the disabled attr on the relevant fields del self.browser.select( 'input[name="ctl00$MainContent$TxtPrevRegStAddr"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$TxtPrevRegUnitApt"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$TxtPrevRegCityTownCounty"]' )[0]['disabled'] del self.browser.select( 'input[name="ctl00$MainContent$TxtPrevRegZip"]')[0]['disabled'] del self.browser.select( 'select[name="ctl00$MainContent$ddlPrevRegStateTerr"]' )[0]['disabled'] # update fields with previous address data form['ctl00$MainContent$TxtPrevRegStAddr'].value = user.get( 'previous_address', '') form['ctl00$MainContent$TxtPrevRegUnitApt'].value = user.get( 'previous_address_unit', '') form[ 'ctl00$MainContent$TxtPrevRegCityTownCounty'].value = user.get( 'previous_city', '') form['ctl00$MainContent$TxtPrevRegZip'].value = user.get( 'previous_zip', '') state_options = options_dict( form['ctl00$MainContent$ddlPrevRegStateTerr']) try: prev_state = state_options[state_abbr_to_name( user.get('previous_state'))] form[ 'ctl00$MainContent$ddlPrevRegStateTerr'].value = prev_state except KeyError: pass self.browser.submit_form(form)
def step2(self, form, user): # Eligibility form['IsUSCitizen'].value = bool_to_string(user['us_citizen']) if user['will_be_18']: form['RegistrationChoice'].value = '1' # I will be 18 or older by the next election. else: # other options: # form['RegistrationChoice'].value = '2' # I am a 16 or 17 years old and I would like to pre-register to vote. # don't handle this yet, needs update in votebot-api raise ValidationError(message='not eligible', payload={ 'will_be_18': user['will_be_18'], 'date_of_birth': user['date_of_birth'] }) prefix_options = options_dict(form['Prefix']) if 'name_prefix' in user: form['Prefix'].value = prefix_options.get(user['name_prefix']) form['FirstName'].value = user['first_name'] form['MiddleName'].value = user.get('middle_name') form['LastName'].value = user['last_name'] suffix_options = options_dict(form['Suffix']) if 'name_suffix' in user: form['Suffix'].value = suffix_options.get(user['name_suffix']) form['EmailAddress'].value = user.get('email', '') form['ConfirmEmail'].value = user.get('email', '') if user.get('phone'): phone = user.get('phone').replace('+1', '').replace('-', '') form['PhoneNumber'].value = phone # change of name if user.get('has_previous_name'): form['IsPreviouslyRegistered'].checked = 'checked' (prev_first, prev_middle, prev_last) = split_name(user.get('previous_name', '')) form['Previous.FirstName'] = prev_first form['Previous.MiddleName'] = prev_middle form['Previous.LastName'] = prev_last # change of address if user.get('has_previous_adress'): form['IsPreviouslyRegistered'].checked = 'checked' form['Previous.StreetAddress'] = user.get('previous_address', '') form['Previous.ApartmentLotNumber'] = user.get( 'previous_address_unit', '') form['Previous.City'] = user.get('previous_city', '') form['Previous.Zip'] = user.get('previous_zip', '') form['Previous.StateId'] = user.get('previous_state', '') # separate mailing address if user.get('has_separate_mailing_addresss'): form['IsDifferentMailingAddress'].checked = 'checked' mailing_components = get_address_from_freeform( user.get('separate_mailing_address')) form['Mailing.StreetAddress'] = get_street_address_from_components( mailing_components) form[ 'Mailing.ApartmentLotNumber'] = get_address_unit_from_components( mailing_components) form['Mailing.City'] = mailing_components('city_name') form['Mailing.State'] = mailing_components('state_abbreviation') form['Mailing.Zip'] = mailing_components('zipcode') (year, month, day) = split_date(user['date_of_birth'], padding=False) form['MonthOfBirth'].value = month form['DayOfBirth'].value = day form['YearOfBirth'].value = year # ID and last 4 of SSN (CA requires both!) if 'state_id_number' in user: form['CaliforniaID'].value = user.get('state_id_number') else: form['HasNoCaliforniaID'].value = bool_to_string(True) # we actually require this, so shouldn't get here, but just in case if user.get('ssn_last4') == "NONE": form['HasNoSSN'].value = bool_to_string(True) else: form['SSN4'].value = user.get('ssn_last4') # Home and Mailing Address form['Home.StreetAddress'].value = user['address'] form['Home.ApartmentLotNumber'].value = user.get('address_unit') form['Home.City'].value = user['city'] form['Home.Zip'].value = user['zip'] county_options = options_dict(form['Home.CountyId']) try: form['Home.CountyId'].value = county_options.get( user['county'].strip().upper()) except KeyError: raise ValidationError(message='no county match', payload=user['county']) # Ethnicity (optional) if 'ethnicity' in user: ethnicity_options = options_dict(form['EthnicityId']) form['EthnicityId'].value = ethnicity_options.get( user['ethnicity'].upper(), ethnicity_options['OTHER']) # Political Party Preference user["political_party"] = user["political_party"].strip().upper() # they have two inputs with the same name but separated by other elements # so robobrowser's _group_flat_tags creates two entries, which their server won't validate form.fields.pop('PoliticalPreferenceType') # recreate with just one PoliticalPreferenceType = Input( "<input type='radio' name='PoliticalPreferenceType'/>") PoliticalPreferenceType.options = ['1', '2'] form.add_field(PoliticalPreferenceType) if user['political_party'].lower( ) == 'independent' or user['political_party'].lower() == "none": PoliticalPreferenceType.value = '2' PoliticalPreferenceType.checked = 'checked' # also delete the politcal party select form.fields.pop('PoliticalPartyId') else: # mess with the DOM to un-disable Political Party del self.browser.select( 'select[name="PoliticalPartyId"]')[0]['disabled'] PoliticalPreferenceType.value = '1' PoliticalPreferenceType.checked = 'checked' party_options = options_dict(form['PoliticalPartyId']) # do fuzzy match to political party options party_choice = get_party_from_list(user['political_party'], party_options.keys()) if party_choice in party_options.keys(): form['PoliticalPartyId'].value = party_options[party_choice] else: form['PoliticalPartyId'].value = party_options.get('Other') form['OtherPoliticalParty'].value = user['political_party'] self.submit_form_field(form, 'GoToNext')
def register_to_vote(self, user): frm = self.browser.get_form() user["political_party"] = user["political_party"].strip() if user['political_party'].lower( ) == 'independent' or user['political_party'].lower() == "none": frm['partyPreference'].value = "No Party Preference" else: party_options = options_dict(frm['partyPreference']) # do fuzzy match to political party options party_choice = get_party_from_list(user['political_party'], party_options.keys()) if party_choice in party_options.keys(): frm['partyPreference'].value = party_options[party_choice] else: frm['otherPartyPreference'].value = user['political_party'] frm['email'].value = user['email'] if user.get('has_previous_address'): frm['regOther'].checked = 'checked' prev_address_components = get_address_components( user['previous_address'], user['previous_city'], user['previous_state'], user['previous_zip']) # County or state where previously registered try: if prev_address_components['state_abbreviation'] == "AZ": COUNTY_IDS = { "Apache": "01", "Cochise": "02", "Coconino": "03", "Gila": "04", "Graham": "05", "Greenlee": "06", "Maricopa": "07", "Mohave": "08", "Navajo": "09", "Pima": "10", "Pinal": "11", "Santa Cruz": "12", "Yavapai": "13", "Yuma": "14", "La Paz": "15" } frm['regCounty'].value = COUNTY_IDS[ prev_address_components['county_name']] else: frm['regCounty'].value = user['previous_state'] except KeyError: raise ValidationError( message='unable to match previous state/county', payload=user['previous_zip']) if user.get('has_previous_name'): frm['nameChange'].checked = 'checked' (prev_first, prev_middle, prev_last) = split_name(user.get('previous_name')) frm['formerFirstName'] = prev_first frm['formerMiddleName'] = prev_middle frm['formerLastname'] = prev_last self.browser.submit_form(frm, submit=frm['_eventId_register'], headers=self.get_default_submit_headers())