├── __init__.py ├── emailer ├── __init__.py ├── aws_emailer │ ├── __init__.py │ └── email_with_attachment.py ├── gcp_emailer │ ├── __init__.py │ └── gcp_email.py └── README.md ├── just_for_fun ├── qr_code │ ├── images │ │ ├── .gitkeep │ │ ├── genesys.png │ │ ├── vanessa.jpeg │ │ ├── pycon_ireland.png │ │ ├── devfestireland.png │ │ ├── pycon_ireland_22.png │ │ └── Genesys_square_logo.png │ ├── qr_codes │ │ ├── .gitkeep │ │ ├── rounded.png │ │ ├── standard.png │ │ ├── with_image.png │ │ ├── with_mask.png │ │ ├── ronan_rounded.png │ │ ├── ronan_standard.png │ │ ├── ronan_with_image.png │ │ ├── ronan_with_mask.png │ │ ├── vanessa_rounded.png │ │ ├── vanessa_standard.png │ │ ├── vanessa_with_image.png │ │ ├── vanessa_with_mask.png │ │ ├── adf_builder_rounded.png │ │ ├── adf_builder_standard.png │ │ ├── adf_builder_with_mask.png │ │ ├── jira_rest_api_rounded.png │ │ ├── jirascripting_rounded.png │ │ ├── adf_builder_with_image.png │ │ ├── devfestireland_rounded.png │ │ ├── devfestireland_standard.png │ │ ├── jira_rest_api_standard.png │ │ ├── jira_rest_api_with_mask.png │ │ ├── jirascripting_standard.png │ │ ├── jirascripting_with_mask.png │ │ ├── devfestireland_with_image.png │ │ ├── devfestireland_with_mask.png │ │ ├── jira_rest_api_with_image.png │ │ └── jirascripting_with_image.png │ ├── .DS_Store │ └── qr_code_production.py ├── file_access │ ├── output │ │ ├── example.csv │ │ └── MOCK_DATA_WITH_PROJECT.csv │ ├── .DS_Store │ ├── input │ │ ├── example.xlsx │ │ ├── example.csv │ │ └── MOCK_DATA.csv │ ├── write_csv.py │ ├── csv_read.py │ ├── excel_read.py │ └── adding_to_the_mock_data.py ├── .DS_Store ├── HTML │ ├── json2html2pdf.pdf │ ├── json2html.html │ └── json_to_html.py └── README.md ├── part_1_story_creation ├── reports │ └── .gitkeep ├── README.md ├── part_1_same_story_for_every_project.py ├── part_2_same_story_for_every_project_assigned_to_a_user.py ├── part_3_same_story_for_every_project_assigned_to_project_lead.py └── part_4_same_story_for_every_project_assigned_with_report.py ├── part_2_epic_creation ├── reports │ └── .gitkeep ├── README.md ├── part_1_create_an_epic.py ├── part_2_create_many_linked_epics.py └── part_3_create_many_linked_epics_with_record.py ├── src ├── __init__.py └── jirascripting │ ├── __init__.py │ ├── auth_and_headers.py │ ├── create_jira_epic.py │ ├── get_assignable_users.py │ ├── create_jira_issue.py │ ├── create_jira_issue_with_parent.py │ ├── create_fancy_jira_issue.py │ └── helpers.py ├── part_3_creating_from_csv ├── input │ ├── .gitkeep │ ├── MOCK_DATA.csv │ └── MOCK_DATA_WITH_PROJECT.csv ├── README.md ├── part_1_create_from_csv.py ├── part_2_create_fancy_from_csv.py ├── part_3_create_in_projects_defined_in_csv.py └── _description_document.py ├── part_0_my_jira_cloud_instance ├── output │ └── .gitkeep ├── README.md └── get_to_know_your_jira_instance.py ├── part_4_creating_assigning_and_emailing ├── input │ ├── .gitkeep │ ├── devfestireland_with_image.png │ ├── MOCK_DATA_WITH_PROJECT_3_lines.csv │ ├── MOCK_DATA_WITH_PROJECT_6_lines.csv │ └── MOCK_DATA_WITH_PROJECT.csv ├── reports │ └── .gitkeep ├── README.md ├── _follow_up_email_body.py ├── part_5_completeness_percentage_sunburst.py ├── _email_body.py ├── _comment_document.py ├── part_3_follow_up_with_a_comment.py ├── part_4_follow_up_with_an_email.py ├── part_1_create_assign_email.py ├── _description_document.py └── part_2_create_assign_email_prepaired_for_follow_up.py ├── .DS_Store ├── .env_template ├── CONTRIBUTING.md ├── requirements.txt ├── pyproject.toml ├── SECURITY.md ├── LICENSE ├── .github └── workflows │ └── codeql.yml ├── .gitignore ├── README.md └── CODE_OF_CONDUCT.md /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emailer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emailer/aws_emailer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emailer/gcp_emailer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /part_1_story_creation/reports/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /part_2_epic_creation/reports/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | # this is a comment -------------------------------------------------------------------------------- /part_3_creating_from_csv/input/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /part_0_my_jira_cloud_instance/output/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/jirascripting/__init__.py: -------------------------------------------------------------------------------- 1 | # this is a comment -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/input/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/reports/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /just_for_fun/file_access/output/example.csv: -------------------------------------------------------------------------------- 1 | I,love,Python,Hangouts 2 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/.DS_Store -------------------------------------------------------------------------------- /just_for_fun/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/.DS_Store -------------------------------------------------------------------------------- /.env_template: -------------------------------------------------------------------------------- 1 | # copy this file and save it as .env then fill in the values 2 | JIRA_EMAIL= 3 | API_KEY= 4 | BASE_URL= 5 | -------------------------------------------------------------------------------- /just_for_fun/qr_code/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/.DS_Store -------------------------------------------------------------------------------- /just_for_fun/HTML/json2html2pdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/HTML/json2html2pdf.pdf -------------------------------------------------------------------------------- /just_for_fun/file_access/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/file_access/.DS_Store -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/genesys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/genesys.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/vanessa.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/vanessa.jpeg -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/standard.png -------------------------------------------------------------------------------- /just_for_fun/file_access/input/example.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/file_access/input/example.xlsx -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/pycon_ireland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/pycon_ireland.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/with_image.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/devfestireland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/devfestireland.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/ronan_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/pycon_ireland_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/pycon_ireland_22.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/ronan_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_standard.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/ronan_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_with_image.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/ronan_with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/vanessa_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/vanessa_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_standard.png -------------------------------------------------------------------------------- /just_for_fun/file_access/input/example.csv: -------------------------------------------------------------------------------- 1 | Name,Age,City,Job 2 | David,21,Dublin,Dev 3 | Mary,28,Galway,DevOps 4 | John,30,London,Security 5 | Ann,45,Leeds,Marketing -------------------------------------------------------------------------------- /just_for_fun/qr_code/images/Genesys_square_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/Genesys_square_logo.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/vanessa_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_with_image.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/vanessa_with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/adf_builder_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/adf_builder_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_standard.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/adf_builder_with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jira_rest_api_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jirascripting_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/adf_builder_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_with_image.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/devfestireland_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_rounded.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/devfestireland_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_standard.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jira_rest_api_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_standard.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jira_rest_api_with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jirascripting_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_standard.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jirascripting_with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/devfestireland_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_with_image.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/devfestireland_with_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_with_mask.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jira_rest_api_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_with_image.png -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_codes/jirascripting_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_with_image.png -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/input/devfestireland_with_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/part_4_creating_assigning_and_emailing/input/devfestireland_with_image.png -------------------------------------------------------------------------------- /just_for_fun/file_access/write_csv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | data = ["I", "love", "Python", "Hangouts"] 4 | 5 | with open('output/example.csv', 'w') as file: 6 | writer = csv.writer(file) 7 | writer.writerow(data) 8 | -------------------------------------------------------------------------------- /just_for_fun/file_access/csv_read.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | with open("input/example.csv") as infile: 4 | reader = csv.reader(infile, delimiter=",") 5 | 6 | next(reader, None) 7 | 8 | for row in reader: 9 | print(row) 10 | print(row[0]) 11 | print(row[1]) 12 | -------------------------------------------------------------------------------- /part_2_epic_creation/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - Epic Creation 2 | 3 | This section deals with the creation of Epics and how we start to logically collect issues. 4 | 5 | ### What is in this section? ### 6 | 7 | * Create an epic 8 | * Create many epics linked under and Uber Epic or Initiative 9 | * Continue keeping a report of actions taken -------------------------------------------------------------------------------- /just_for_fun/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - Just for Fun 2 | 3 | Not directly used by this repository but were used in presenting this repository 4 | 5 | ### What is in this section? ### 6 | 7 | * File Access - how to access different file types you may wish to import issues from 8 | * QR Code - create fancy QR codes from URL's 9 | * HTML - representing a JSON file as HTML -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions welcome via pull request. 2 | Add a directory following the naming convention including a descriptive title. 3 | If adding to the helpers.py file, please also add a docstring and a calling section in th if __name__ == "main": section. 4 | 5 | While not manditory to contribute, if you've found this repo useful and you have added to it, I would encourage you to do so. 6 | -------------------------------------------------------------------------------- /just_for_fun/file_access/excel_read.py: -------------------------------------------------------------------------------- 1 | import os 2 | from openpyxl import load_workbook 3 | 4 | wb = load_workbook(filename=f"input/example.xlsx") 5 | sheet_names = wb.sheetnames 6 | ws = wb[sheet_names[0]] 7 | 8 | for row_num, row_val in enumerate(ws.iter_rows(min_row=2, max_row=ws.max_row), start=2): 9 | Name = row_val[0].value 10 | Age = row_val[1].value 11 | City = row_val[2].value 12 | -------------------------------------------------------------------------------- /part_1_story_creation/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - Story Creation 2 | 3 | This section deals with the most atomic action in Jira Cloud, creating an issue. 4 | 5 | ### What is in this section? ### 6 | 7 | * Creating an issue 8 | * Getting all projects using the method found in the helpers file 9 | * Using the assignable users JSON output 10 | * Introducing the concept of keeping a report of actions taken -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pillow>=9.3.0 2 | qrcode==7.3.1 3 | 4 | defusedxml~=0.6.0 5 | future~=0.17.1 6 | ipython>=7.34.0 7 | pip>=21.3.1 8 | toml~=0.10.1 9 | Brotli~=1.0.9 10 | cryptography~=3.2 11 | py==1.11.0 12 | setuptools>=65.5.1 13 | docutils~=0.15.2 14 | requests~=2.31.0 15 | python-dotenv~=0.19.0 16 | retrying~=1.3.3 17 | botocore~=1.15.49 18 | boto3~=1.12.49 19 | sendgrid~=6.9.7 20 | openpyxl~=3.0.9 21 | json2html~=1.3.0 22 | pytz~=2019.3 23 | pandas~=1.3.2 24 | plotly~=5.3.1 -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name="jirascripting" 3 | version='0.0.5' 4 | description='Methods for interacting with Jira Cloud' 5 | authors = [ 6 | { name="David Renton", email="davidleerenton@gmail.com" }, 7 | ] 8 | dependencies=["requests~=2.31.0", "python-dotenv~=0.19.0"] 9 | classifiers=[ 10 | "Development Status :: 3 - Alpha", 11 | 'License :: OSI Approved :: MIT License', 12 | "Programming Language :: Python :: 3", 13 | 'Operating System :: OS Independent', 14 | ] 15 | 16 | -------------------------------------------------------------------------------- /emailer/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - Emailer 2 | 3 | Two directories for two cloud emailing offerings. AWS is implemented, GCP is a skeleton only 4 | 5 | ### What is in this section? ### 6 | 7 | * AWS emailer - this requires an active AWS account with the email address you wish to send emails from registered in SES. 8 | * The correct aws_access_key_id and aws_secret_access_key must be created and used to gain access. 9 | * Further instructions can be found here - https://docs.aws.amazon.com/ses/latest/dg/setting-up.html 10 | * GCP implementation is incomplete -------------------------------------------------------------------------------- /part_2_epic_creation/part_1_create_an_epic.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from src import create_epic 4 | 5 | 6 | def main(): 7 | res = create_epic( 8 | summary="This is a summary", 9 | project="D2", 10 | description="This is a description for an epic", 11 | epic_name="Some Epic Name", 12 | priority="High", 13 | assignee_id='-1') 14 | json_res = json.loads(res.text) 15 | story_key = json_res['key'] 16 | print(f"New Epic created - Key: {story_key} ") 17 | 18 | 19 | if __name__ == "__main__": 20 | main() 21 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_3_lines.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message,project 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3 -------------------------------------------------------------------------------- /part_3_creating_from_csv/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - Creating from a CSV 2 | 3 | This section delivers on the promise of creating many Jira issues from a CSV. 4 | CSV's may be hand made and handed over as a work package, be the output of reportng system or given from an external party e.g. an auditor. 5 | 6 | ### What is in this section? ### 7 | 8 | * Create issues from the provided CSV in a single project 9 | * Create issues in specified projects from a provided CSV 10 | * Using the description document generated from https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ and using variable substitution -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - Creating Assigning & Emailing 2 | 3 | This section pulls everything together from the earlier sections and shows the practical usecase for maintaining the reporting JSON file outlined in previous sections. 4 | 5 | ### What is in this section? ### 6 | 7 | * Creating and assigning issues and emailing the assignee directly 8 | * Report keeping in the form of a JSON file 9 | * Adding comments on open issues 10 | * Tagging users in comments 11 | * Sending email followups to the assignees of open issues 12 | * Producing an interactive diagram of all issues and their states -------------------------------------------------------------------------------- /part_0_my_jira_cloud_instance/README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting - My Jira Cloud Instance 2 | 3 | While many Jira cloud instances start off equivalent, over time with user input the extendable nature of Jira Cloud will mean your admin will, at the request of teams using the service, have added many alternatives to the starting set provided out of the box. User beware - these differences may be between projects within the instance also. 4 | 5 | ### What is in this section? ### 6 | 7 | * Get to know your Jira instance - has a basic set of extendable types including issue types, priorities and issue links. 8 | * It is recommended the user add to this as discoveries are made to use as a reference. -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /just_for_fun/file_access/adding_to_the_mock_data.py: -------------------------------------------------------------------------------- 1 | import csv 2 | from random import randrange 3 | 4 | with open("input/MOCK_DATA.csv") as infile: 5 | reader = csv.reader(infile, delimiter=",") 6 | with open('input/MOCK_DATA.csv', 'r') as csv_input: 7 | with open('output/MOCK_DATA_WITH_PROJECT.csv', 'w') as csv_output: 8 | writer = csv.writer(csv_output, lineterminator='\n') 9 | reader = csv.reader(csv_input) 10 | 11 | new_contents = [] 12 | row = next(reader) 13 | row.append('project') 14 | new_contents.append(row) 15 | 16 | for row in reader: 17 | projects = ['D1', 'D2', 'D3'] 18 | row.append(projects[randrange(3)]) 19 | new_contents.append(row) 20 | 21 | writer.writerows(new_contents) 22 | -------------------------------------------------------------------------------- /part_1_story_creation/part_1_same_story_for_every_project.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from src import create_issue 4 | from src import get_all_projects 5 | 6 | 7 | def main(): 8 | all_projects = get_all_projects() 9 | for project in all_projects: 10 | project_key = project.get('key', None) 11 | created_issue = create_issue( 12 | summary=f"I am a test in project {project_key}" 13 | , project=project_key 14 | , description="This is a test, please delete me." 15 | , issue_type="Story" 16 | , priority='High' 17 | ) 18 | 19 | json_res = json.loads(created_issue.text) 20 | story_key = json_res.get('key', None) 21 | print(f"Newly created Story - Key: {story_key} ") 22 | 23 | 24 | if __name__ == "__main__": 25 | main() 26 | -------------------------------------------------------------------------------- /src/jirascripting/auth_and_headers.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from dotenv import load_dotenv 3 | import os 4 | 5 | load_dotenv() 6 | 7 | 8 | def jira_auth_and_headers(): 9 | """Uses .ENV file variables to authenticate to the Jira API 10 | 11 | Returns: 12 | auth: (HTTPBasicAuth object) for the Jira Cloud instance 13 | headers: (json object) contains required headers for all requests 14 | url: (String) the base URL for the instance 15 | 16 | """ 17 | auth = requests.auth.HTTPBasicAuth(os.environ.get("JIRA_EMAIL"), os.environ.get("API_KEY")) 18 | 19 | headers = { 20 | "Accept": "application/json", 21 | "Content-Type": "application/json", 22 | "X-ExperimentalApi": "opt-in" 23 | } 24 | 25 | url = os.environ.get("BASE_URL") 26 | 27 | return auth, headers, url 28 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/_follow_up_email_body.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def email_body(story_key, status, reminders): 4 | body_html = f""" 5 | 6 | 7 | 8 |

Hey;

9 |
10 |

You have a Jira ticket still in {status}


11 |

❤️❤️I know you are all super busy, but this needs to be done! ❤️❤️

12 |

You should have gotten previous reminders

13 |
14 |             
15 |             {reminders}
16 |             
17 |         
18 |

Here is the Jira story we created for you to report progress - https://YOUR_PROJECT.atlassian.net/browse/{story_key}

19 | Here is the Jira story we created for you to report progress. 20 | 21 | """ 22 | return body_html -------------------------------------------------------------------------------- /just_for_fun/HTML/json2html.html: -------------------------------------------------------------------------------- 1 | Json 2 HTML
glossary
titleexample glossary
GlossDiv
titleS
GlossList
GlossEntry
IDSGML
SortAsSGML
GlossTermStandard Generalized Markup Language
AcronymSGML
AbbrevISO 8879:1986
GlossDef
paraA meta-markup language, used to create markup languages such as DocBook.
GlossSeeAlso
  • GML
  • XML
GlossSeemarkup
-------------------------------------------------------------------------------- /part_0_my_jira_cloud_instance/get_to_know_your_jira_instance.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from src import get_issue_types, get_priority_types, get_all_epic_link_types 4 | 5 | 6 | def main(): 7 | my_instance = {} 8 | issue_types = get_issue_types() 9 | my_instance['issue_types'] = [] 10 | for issue_type in issue_types: 11 | my_instance['issue_types'].append(issue_type.get('name', None)) 12 | 13 | priorities = get_priority_types() 14 | my_instance['priorities'] = [] 15 | for priority_ in priorities: 16 | my_instance['priorities'].append(priority_.get('name', None)) 17 | 18 | issue_links = get_all_epic_link_types() 19 | my_instance['issue_links'] = [] 20 | for issue_link in issue_links: 21 | my_instance['issue_links'].append(issue_link.get('name', None)) 22 | 23 | return my_instance 24 | 25 | 26 | if __name__ == "__main__": 27 | my_instance_details = main() 28 | with open(f'output/my_instance_details.json', 'w') as outfile: 29 | json.dump(my_instance_details, outfile) -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_6_lines.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message,project 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3 5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3 6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3 7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 David Renton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /part_1_story_creation/part_2_same_story_for_every_project_assigned_to_a_user.py: -------------------------------------------------------------------------------- 1 | from src import get_all_assignable_users_email 2 | import json 3 | 4 | from src import create_issue 5 | from src import get_all_projects 6 | 7 | 8 | def main(): 9 | all_projects = get_all_projects() 10 | assignable_users = get_all_assignable_users_email('D1') 11 | # replace user_email with one you have in your jira instance 12 | user_email = 'davidleerenton@gmail.com' 13 | user_id = assignable_users.get(user_email, None) 14 | 15 | for project in all_projects: 16 | project_key = project.get('key', None) 17 | created_issue = create_issue( 18 | summary=f"I am a test in project {project_key}" 19 | , project=project_key 20 | , description="This is a test, please delete me." 21 | , issue_type="Story" 22 | , assignee_id=user_id 23 | , priority='High' 24 | ) 25 | 26 | json_res = json.loads(created_issue.text) 27 | story_key = json_res.get('key', None) 28 | print(f"Newly created Story - Key: {story_key} Assigned to: {user_id} ({user_email})") 29 | 30 | 31 | if __name__ == "__main__": 32 | main() -------------------------------------------------------------------------------- /part_1_story_creation/part_3_same_story_for_every_project_assigned_to_project_lead.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from src import create_issue 4 | from src import get_all_projects, get_single_project 5 | 6 | 7 | def main(): 8 | all_projects = get_all_projects() 9 | 10 | for project in all_projects: 11 | project_key = project.get('key', None) 12 | project = get_single_project(project_key) 13 | project_lead_id = project.get('lead', {}).get('accountId', "-1") 14 | project_lead_display_name = project.get('lead', {}).get('displayName', "No Name Attached") 15 | created_issue = create_issue( 16 | summary=f"I am a test in project {project_key}" 17 | , project=project_key 18 | , description="This is a test, please delete me." 19 | , issue_type="Story" 20 | , assignee_id=project_lead_id 21 | , priority='High' 22 | ) 23 | 24 | json_res = json.loads(created_issue.text) 25 | story_key = json_res.get('key', None) 26 | print(f"Newly created Story - Key: {story_key} Assigned to: {project_lead_id} ({project_lead_display_name})") 27 | 28 | 29 | if __name__ == "__main__": 30 | main() -------------------------------------------------------------------------------- /part_2_epic_creation/part_2_create_many_linked_epics.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from src import create_epic 4 | from src import create_epic_link 5 | 6 | 7 | def main(): 8 | epic_names = ["Epic one", "Epic two", "Epic three", "Dave", "Other Dave", "Big Dave", 9 | "Tommy Dave", "Jana Dave", "Rich Dave", "Patrick Paterson"] 10 | 11 | uber_epic_creation = create_epic( 12 | summary="This is a summary", 13 | project="D2", 14 | description="This is a description for an uber epic", 15 | epic_name="One Epic to rule them all", 16 | priority="High", 17 | assignee_id='-1') 18 | json_res = json.loads(uber_epic_creation.text) 19 | uber_epic_key = json_res['key'] 20 | 21 | for epic_name in epic_names: 22 | epic_creation = create_epic( 23 | summary="This is a summary", 24 | project="D3", 25 | description="This is a description for an uber epic", 26 | epic_name=epic_name, 27 | priority="High", 28 | assignee_id='-1') 29 | json_res = json.loads(epic_creation.text) 30 | epic_key = json_res['key'] 31 | 32 | link_response = create_epic_link(epic_key, uber_epic_key, 'Relates') 33 | print(link_response) 34 | 35 | 36 | if __name__ == "__main__": 37 | main() -------------------------------------------------------------------------------- /part_3_creating_from_csv/part_1_create_from_csv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import json 3 | 4 | from src import create_issue 5 | 6 | 7 | def main(file_): 8 | with open(file_) as infile: 9 | reader = csv.reader(infile, delimiter=",") 10 | # Skip the header 11 | next(reader, None) 12 | # For each row 13 | for row in reader: 14 | res = create_issue( 15 | summary=f"From CSV - {row[1]} {row[2]}" 16 | , project="D2" 17 | , description=f""" 18 | This could be used to assign people : {row[3]} 19 | Gender : {row[4]} 20 | ip : {row[5]} 21 | Message : {row[6]}""" 22 | , issue_type="Story" 23 | , epic_link="D2-2" 24 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b" 25 | , priority='High' 26 | ) 27 | if res.status_code == 400: 28 | json_res = json.loads(res.text) 29 | print(json_res['errors']) 30 | else: 31 | json_res = json.loads(res.text) 32 | story_id = json_res['id'] 33 | story_key = json_res['key'] 34 | print(f"ID: {story_id}, Key: {story_key} ") 35 | 36 | 37 | if __name__ == "__main__": 38 | input_file = "input/MOCK_DATA.csv" 39 | main(input_file) -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/part_5_completeness_percentage_sunburst.py: -------------------------------------------------------------------------------- 1 | import json 2 | import pandas as pd 3 | import plotly.express as px 4 | 5 | filename = 'go_to_devfest' 6 | with open(f'reports/{filename}.json', 'r') as f: 7 | report = json.load(f) 8 | 9 | stories = report['stories'] 10 | 11 | df2 = pd.DataFrame.from_dict(stories, orient='index') 12 | # This adds the key in as a column 13 | df2['index'] = df2.index 14 | stories_df = df2.groupby(by=['assignee', 'status_category', 'index']).count()[["hash"]].rename(columns={"hash": "count"}) 15 | # This fills each row as the group by gives a hierarchical view 16 | stories_df = stories_df.reset_index() 17 | stories_df.head() 18 | # If you want to see what the dataframe looks like uncomment the print below 19 | # print(stories_df) 20 | fig = px.sunburst(stories_df, 21 | path=['assignee', 'status_category', 'index'], 22 | values='count', 23 | maxdepth=3, 24 | color='status_category', 25 | color_discrete_map={'(?)': 'black', "new": 'red', "indeterminate": 'pink', "done": 'green'} 26 | ) 27 | # Open a browser with the interactive graph 28 | fig.show() 29 | 30 | with open(f'reports/{filename}.html', 'a') as f: 31 | f.write(fig.to_html(full_html=False, include_plotlyjs='cdn')) -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/_email_body.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def email_body(first_name, last_name, gender, ip_address, message, project, story_key): 4 | body_html = f""" 5 | 6 | 7 | 8 |

Hey {first_name} {last_name};

9 |
10 |

We have created a ticket for your attention in the Jira project {project} as a part of the super important 11 | project


❤️❤️I know you are all super busy, but we need your help! ❤️❤️

12 |

{message} needs to be actioned.

13 |

This is turning out well.

14 |
15 |             
16 |             This is some code snippet 
17 |             
18 |         
19 |

Add a list if it is needed?

20 | 25 |

Here is a link to the project confluence page - if there is a chance of questions, start a Confluence page for updates

26 |

Here is the Jira story we created for you to report progress - https://YOUR_PROJECT.atlassian.net/browse/{story_key}

27 | Here is the Jira story we created for you to report progress. 28 | 29 | """ 30 | return body_html -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/_comment_document.py: -------------------------------------------------------------------------------- 1 | # This file is imported by the part_3_create_in_projects_defined_in_csv.py and part_2_create_fancy_from_csv.py files 2 | # The json object assigned to fancy_description is generated from - https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ 3 | 4 | def comment_doc(id_, reminder, status): 5 | fancy_description = { 6 | "version": 1, 7 | "type": "doc", 8 | "content": [ 9 | { 10 | "type": "paragraph", 11 | "content": [ 12 | { 13 | "type": "text", 14 | "text": "Hey " 15 | }, 16 | { 17 | "type": "mention", 18 | "attrs": { 19 | "id": f"{id_}" 20 | } 21 | }, 22 | { 23 | "type": "text", 24 | "text": " have you booked your ticket to DevFest yet?" 25 | } 26 | ] 27 | }, 28 | { 29 | "type": "paragraph", 30 | "content": [ 31 | { 32 | "type": "text", 33 | "text": f"This ticket was created {reminder}" 34 | } 35 | ] 36 | }, 37 | { 38 | "type": "paragraph", 39 | "content": [ 40 | { 41 | "type": "text", 42 | "text": f"It’s still in status {status}" 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | return fancy_description 49 | -------------------------------------------------------------------------------- /just_for_fun/HTML/json_to_html.py: -------------------------------------------------------------------------------- 1 | from json2html import * 2 | import pdfkit 3 | 4 | 5 | def json_to_html_page(input_): 6 | html_start = '''Json 2 HTML''' 7 | html_end = '''''' 8 | table = json2html.convert(json=input_) 9 | complete_html_page = html_start + table + html_end 10 | return complete_html_page 11 | 12 | 13 | if __name__ == "__main__": 14 | json_input = { 15 | "glossary": { 16 | "title": "example glossary", 17 | "GlossDiv": { 18 | "title": "S", 19 | "GlossList": { 20 | "GlossEntry": { 21 | "ID": "SGML", 22 | "SortAs": "SGML", 23 | "GlossTerm": "Standard Generalized Markup Language", 24 | "Acronym": "SGML", 25 | "Abbrev": "ISO 8879:1986", 26 | "GlossDef": { 27 | "para": "A meta-markup language, used to create markup languages such as DocBook.", 28 | "GlossSeeAlso": ["GML", "XML"] 29 | }, 30 | "GlossSee": "markup" 31 | } 32 | } 33 | } 34 | } 35 | } 36 | html_page = json_to_html_page(json_input) 37 | file = open('json2html.html', 'w') 38 | file.write(html_page) 39 | file.close() 40 | pdfkit.from_file('json2html.html', 'json2html2pdf.pdf') 41 | -------------------------------------------------------------------------------- /emailer/gcp_emailer/gcp_email.py: -------------------------------------------------------------------------------- 1 | import os 2 | from sendgrid import SendGridAPIClient 3 | from sendgrid.helpers.mail import Mail, Email 4 | from python_http_client.exceptions import HTTPError 5 | 6 | 7 | def send_mail(sender: str, recipients: list, title: str, html: str = None) -> dict: 8 | """ 9 | Send email to recipients. Sends one mail to all recipients. 10 | To set this up on the GCP console follow this tutorial 11 | https://cloud.google.com/compute/docs/tutorials/sending-mail/using-sendgrid . 12 | """ 13 | # If using this module handle the API key with respect 14 | sg = SendGridAPIClient(os.environ['EMAIL_API_KEY']) 15 | 16 | html_content = html 17 | 18 | message = Mail( 19 | to_emails=recipients, 20 | from_email=Email(sender), 21 | subject=title, 22 | html_content=html_content 23 | ) 24 | 25 | try: 26 | response = sg.send(message) 27 | return_message = f"email.status_code={response.status_code}" 28 | #expected 202 Accepted 29 | 30 | except HTTPError as e: 31 | return_message = e.message 32 | 33 | return return_message 34 | 35 | 36 | if __name__ == '__main__': 37 | # replace sender_ with the email address you registered in AWS SES 38 | sender_ = 'david.renton@genesys.com' 39 | recipients_ = ['davidleerenton@gmail.com'] 40 | title_ = 'DevFest' 41 | text_ = 'DevFest is awesome' 42 | body_ = """

A header 1


Some text.""" 43 | 44 | response_ = send_mail(sender_, recipients_, title_, text_, body_) 45 | print(response_) -------------------------------------------------------------------------------- /part_1_story_creation/part_4_same_story_for_every_project_assigned_with_report.py: -------------------------------------------------------------------------------- 1 | from src import get_all_assignable_users_email 2 | import json 3 | 4 | from src import create_issue 5 | from just_for_fun.HTML.json_to_html import json_to_html_page 6 | from src import get_all_projects 7 | 8 | 9 | def main(): 10 | all_projects = get_all_projects() 11 | assignable_users = get_all_assignable_users_email('D1') 12 | campaign_report_ = {} 13 | project_keys = [] 14 | 15 | for project in all_projects: 16 | project_keys.append(project.get('key', None)) 17 | 18 | for project_key in project_keys: 19 | if project_key is not None: 20 | created_issue = create_issue( 21 | summary=f"I am a test in project {project_key}" 22 | , project=project_key 23 | , description="This is a test, please delete me." 24 | , issue_type="Story" 25 | # replace the email below with one from your jira project 26 | , assignee_id=assignable_users.get('davidleerenton@gmail.com', None) 27 | , priority='High' 28 | ) 29 | 30 | json_res = json.loads(created_issue.text) 31 | story_key = json_res.get('key', None) 32 | campaign_report_[f'{project_key}'] = {} 33 | campaign_report_[f'{project_key}']['created_story'] = story_key 34 | return campaign_report_ 35 | 36 | 37 | if __name__ == "__main__": 38 | campaign_report = main() 39 | campaign_name = "my_super_report" 40 | with open(f'reports/{campaign_name}_report.json', 'w') as outfile: 41 | json.dump(campaign_report, outfile) 42 | 43 | html_page = json_to_html_page(campaign_report) 44 | file = open(f'reports/{campaign_name}_report.html', 'w') 45 | file.write(html_page) 46 | file.close() 47 | 48 | 49 | -------------------------------------------------------------------------------- /part_2_epic_creation/part_3_create_many_linked_epics_with_record.py: -------------------------------------------------------------------------------- 1 | import atexit 2 | import json 3 | 4 | from src import create_epic 5 | from src import create_epic_link 6 | from just_for_fun.HTML.json_to_html import json_to_html_page 7 | 8 | campaign_report = {} 9 | 10 | 11 | def main(): 12 | epic_names = ["Epic one", "Epic two", "Epic three"] 13 | 14 | uber_epic_creation = create_epic( 15 | summary="This is a summary", 16 | project="D2", 17 | description="This is a description for an uber epic", 18 | epic_name="One Epic to rule them all", 19 | priority="High", 20 | assignee_id='-1') 21 | json_res = json.loads(uber_epic_creation.text) 22 | uber_epic_key = json_res['key'] 23 | campaign_report['uber_epic'] = {f'{uber_epic_key}': {}} 24 | campaign_report[f'epics'] = {} 25 | 26 | for epic_name in epic_names: 27 | epic_creation = create_epic( 28 | summary="This is a summary", 29 | project="D3", 30 | description="This is a description for an uber epic", 31 | epic_name=epic_name, 32 | priority="High", 33 | assignee_id='-1') 34 | json_res = json.loads(epic_creation.text) 35 | epic_key = json_res['key'] 36 | campaign_report['epics'][f'{epic_key}'] = {} 37 | 38 | link_response = create_epic_link(epic_key, uber_epic_key, 'Relates') 39 | print(link_response) 40 | 41 | 42 | @atexit.register 43 | def final_function(): 44 | campaign_name = "my_super_at_exit" 45 | with open(f'reports/{campaign_name}_report.json', 'w') as outfile: 46 | json.dump(campaign_report, outfile) 47 | 48 | html_page = json_to_html_page(campaign_report) 49 | file = open(f'reports/{campaign_name}_report.html', 'w') 50 | file.write(html_page) 51 | file.close() 52 | 53 | 54 | if __name__ == "__main__": 55 | main() 56 | -------------------------------------------------------------------------------- /part_3_creating_from_csv/part_2_create_fancy_from_csv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import json 3 | 4 | from src import get_all_assignable_users_email 5 | from src import create_fancy_issue 6 | from part_3_creating_from_csv._description_document import description_doc 7 | 8 | assignable_users = get_all_assignable_users_email('D1') 9 | 10 | 11 | def main(file_): 12 | with open(file_) as infile: 13 | reader = csv.reader(infile, delimiter=",") 14 | # Skip the header 15 | next(reader, None) 16 | # For each row 17 | for row in reader: 18 | # get user id from email, this could be provided in th csv file 19 | # replace the below email with one from your jira instance 20 | assignable_user_email = 'davidleerenton@gmail.com' 21 | assignable_user_id = assignable_users.get(assignable_user_email, None) 22 | 23 | first_name = row[1] 24 | last_name = row[2] 25 | email = row[3] 26 | gender = row[4] 27 | ip_address = row[5] 28 | message = row[6] 29 | # Create the description document 30 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message) 31 | res = create_fancy_issue( 32 | summary=f"From CSV - {first_name} {last_name}" 33 | , project="D2" 34 | , description_doc=description_document 35 | , issue_type="Story" 36 | , epic_link="D2-2" 37 | , assignee_id=assignable_user_id 38 | , priority='High' 39 | ) 40 | if res.status_code == 400: 41 | json_res = json.loads(res.text) 42 | print(json_res['errors']) 43 | else: 44 | json_res = json.loads(res.text) 45 | story_id = json_res['id'] 46 | story_key = json_res['key'] 47 | print(f"ID: {story_id}, Key: {story_key} ") 48 | 49 | 50 | if __name__ == "__main__": 51 | input_file = "input/MOCK_DATA.csv" 52 | main(input_file) 53 | -------------------------------------------------------------------------------- /part_3_creating_from_csv/part_3_create_in_projects_defined_in_csv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import json 3 | 4 | from src import get_all_assignable_users_email 5 | from src import create_fancy_issue 6 | from part_3_creating_from_csv._description_document import description_doc 7 | 8 | assignable_users = get_all_assignable_users_email('D1') 9 | 10 | 11 | def main(file_): 12 | with open(file_) as infile: 13 | reader = csv.reader(infile, delimiter=",") 14 | # Skip the header 15 | next(reader, None) 16 | # For each row 17 | for row in reader: 18 | # get user id from email, this could be provided in th csv file 19 | # replace the below email with one from your jira instance 20 | assignable_user_email = 'davidleerenton@gmail.com' 21 | assignable_user_id = assignable_users.get(assignable_user_email, None) 22 | 23 | first_name = row[1] 24 | last_name = row[2] 25 | email = row[3] 26 | gender = row[4] 27 | ip_address = row[5] 28 | message = row[6] 29 | project = row[7] 30 | # Create the description document 31 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message) 32 | res = create_fancy_issue( 33 | summary=f"From CSV - {first_name} {last_name}" 34 | , project=project 35 | , description_doc=description_document 36 | , issue_type="Story" 37 | , epic_link="D2-2" 38 | , assignee_id=assignable_user_id 39 | , priority='High' 40 | ) 41 | if res.status_code == 400: 42 | json_res = json.loads(res.text) 43 | print(json_res['errors']) 44 | else: 45 | json_res = json.loads(res.text) 46 | story_id = json_res['id'] 47 | story_key = json_res['key'] 48 | print(f"ID: {story_id}, Key: {story_key} ") 49 | 50 | 51 | if __name__ == "__main__": 52 | input_file = "input/MOCK_DATA_WITH_PROJECT.csv" 53 | main(input_file) 54 | -------------------------------------------------------------------------------- /just_for_fun/qr_code/qr_code_production.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import qrcode 4 | from qrcode.image.styledpil import StyledPilImage 5 | from qrcode.image.styles.moduledrawers import RoundedModuleDrawer 6 | from qrcode.image.styles.colormasks import RadialGradiantColorMask 7 | 8 | 9 | def make_qr_code(url): 10 | qr = qrcode.QRCode(version=1, box_size=5, border=5) 11 | qr.add_data(url) 12 | qr.make() 13 | 14 | img = qr.make_image(fill_color='black', back_color='white') 15 | return img 16 | 17 | 18 | def make_qr_with_image_code(url, image): 19 | qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H) 20 | qr.add_data(url) 21 | img = qr.make_image(image_factory=StyledPilImage, embeded_image_path=image) 22 | return img 23 | 24 | 25 | def make_qr_with_colour_mask_code(url): 26 | qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H) 27 | qr.add_data(url) 28 | img = qr.make_image(image_factory=StyledPilImage, color_mask=RadialGradiantColorMask()) 29 | return img 30 | 31 | 32 | def make_rounded_qr_code(url): 33 | qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H) 34 | qr.add_data(url) 35 | img = qr.make_image(image_factory=StyledPilImage, module_drawer=RoundedModuleDrawer()) 36 | return img 37 | 38 | 39 | if __name__ == "__main__": 40 | website_link = 'https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/' 41 | my_path = "qr_codes" 42 | image_path = "images/Genesys_square_logo.png" 43 | name_ = "genesys_request" 44 | 45 | file_name = f"{name_}_standard.png" 46 | saved_path = os.path.join(my_path, file_name) 47 | qr_code = make_qr_code(website_link) 48 | qr_code.save(saved_path) 49 | 50 | file_name = f"{name_}_with_image.png" 51 | saved_path = os.path.join(my_path, file_name) 52 | qr_code = make_qr_with_image_code(website_link, image_path) 53 | qr_code.save(saved_path) 54 | 55 | file_name = f"{name_}_with_mask.png" 56 | saved_path = os.path.join(my_path, file_name) 57 | qr_code = make_qr_with_colour_mask_code(website_link) 58 | qr_code.save(saved_path) 59 | 60 | file_name = f"{name_}_rounded.png" 61 | saved_path = os.path.join(my_path, file_name) 62 | qr_code = make_rounded_qr_code(website_link) 63 | qr_code.save(saved_path) 64 | 65 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/part_3_follow_up_with_a_comment.py: -------------------------------------------------------------------------------- 1 | import json 2 | from datetime import datetime 3 | 4 | from src import get_issue_status, get_issue_status_category, add_fancy_comment_to_story, get_issue_assignee 5 | from part_4_creating_assigning_and_emailing._comment_document import comment_doc 6 | 7 | 8 | def main(initiative_name_): 9 | date_ = datetime.now() 10 | f_name = f"reports/{initiative_name_}.json" 11 | with open(f'{f_name}', 'r+') as initiative_: 12 | init_ = json.load(initiative_) 13 | 14 | for story in init_["stories"]: 15 | if init_["stories"][f"{story}"]["status_category"] != "done": 16 | story_status_category = get_issue_status_category(story) 17 | if story_status_category == "done": 18 | init_["stories"][f"{story}"]["status_category"] = story_status_category 19 | continue 20 | else: 21 | story_status = get_issue_status(story) 22 | this_assignee = get_issue_assignee(story) 23 | if this_assignee["assignee_id"] != init_["stories"][f"{story}"]["assignee_id"]: 24 | init_["stories"][f"{story}"]["assignee_id"] = this_assignee["assignee_id"] 25 | init_["stories"][f"{story}"]["assignee"] = this_assignee["assignee_email"] 26 | comment_document = comment_doc(init_["stories"][f"{story}"]["assignee_id"], 27 | init_["stories"][f"{story}"]["reminder"], 28 | story_status) 29 | try: 30 | comment = add_fancy_comment_to_story(story, comment_document) 31 | init_['stories'][f'{story}']['reminder'].append( 32 | f"Reminder comment was added on {date_}") 33 | except: 34 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 35 | json.dump(init_, outfile) 36 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 37 | json.dump(init_, outfile) 38 | 39 | 40 | if __name__ == "__main__": 41 | initiative_name = "go_to_devfest" 42 | main(initiative_name) 43 | 44 | with open(f'reports/{initiative_name}.json', 'r+') as initiative: 45 | init = json.load(initiative) 46 | print(json.dumps(init, indent=4)) 47 | -------------------------------------------------------------------------------- /src/jirascripting/create_jira_epic.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | from src import jira_auth_and_headers 4 | 5 | 6 | def create_epic(summary, project, description, epic_name, priority, assignee_id="-1"): 7 | """Creates an epic 8 | 9 | Parameters: 10 | summary (string): The issue summary 11 | project (string): What Jira project should this be in SECCOMPPM is 21697 12 | description (string): The issue description 13 | epic_name (string): The name of this epic 14 | priority (string): Text Highest, High, Medium, Low, Lowest 15 | assignee_id (string): The ID of the assignable user. 16 | 17 | Returns: 18 | response object: this will have the response code and in the text will have the details of the created epic 19 | 20 | """ 21 | auth, headers, base_url = jira_auth_and_headers() 22 | # create issue 23 | url = f"{base_url}/rest/api/3/issue" 24 | 25 | # create content 26 | content_list = [] 27 | paragraph_content = [] 28 | content_obj = {} 29 | content = {'text': description, 'type': "text"} 30 | content_obj['type'] = "paragraph" 31 | paragraph_content.append(content) 32 | content_obj['content'] = paragraph_content 33 | 34 | # create issue 35 | issue = {'fields': {}} 36 | issue['fields']['summary'] = summary 37 | issue['fields']['issuetype'] = {'name': 'Epic'} 38 | issue['fields']['project'] = {'key': project} 39 | content_list.append(content_obj) 40 | issue['fields']['description'] = {'type': "doc", 'version': 1, 'content': content_list} 41 | issue['fields']['priority'] = {'name': priority} 42 | issue['fields']['assignee'] = {'id': assignee_id} 43 | issue['fields']['customfield_10011'] = f"{epic_name}" 44 | 45 | payload = json.dumps(issue) 46 | 47 | response = requests.request( 48 | "POST", 49 | url, 50 | data=payload, 51 | headers=headers, 52 | auth=auth 53 | ) 54 | return response 55 | 56 | 57 | if __name__ == "__main__": 58 | res = create_epic( 59 | summary="This is a summary", 60 | project="D2", 61 | description="This is a description for an epic", 62 | epic_name="Some Epic Name", 63 | priority="High") 64 | json_res = json.loads(res.text) 65 | story_id = json_res['id'] 66 | story_key = json_res['key'] 67 | print(f"ID: {story_id}, Key: {story_key} ") 68 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/part_4_follow_up_with_an_email.py: -------------------------------------------------------------------------------- 1 | import json 2 | from datetime import datetime 3 | 4 | from src import get_issue_status, get_issue_status_category, get_issue_assignee 5 | from part_4_creating_assigning_and_emailing._follow_up_email_body import email_body 6 | from emailer.aws_emailer.email_with_attachment import send_mail 7 | 8 | 9 | def main(initiative_name_): 10 | date_ = datetime.now() 11 | f_name = f"reports/{initiative_name_}.json" 12 | with open(f'{f_name}', 'r+') as initiative_: 13 | init_ = json.load(initiative_) 14 | 15 | for story in init_["stories"]: 16 | if init_["stories"][f"{story}"]["status_category"] != "done": 17 | story_status_category = get_issue_status_category(story) 18 | if story_status_category == "done": 19 | init_["stories"][f"{story}"]["status_category"] = story_status_category 20 | continue 21 | else: 22 | story_status = get_issue_status(story) 23 | this_assignee = get_issue_assignee(story) 24 | if this_assignee["assignee_id"] != init_["stories"][f"{story}"]["assignee_id"]: 25 | init_["stories"][f"{story}"]["assignee_id"] = this_assignee["assignee_id"] 26 | init_["stories"][f"{story}"]["assignee"] = this_assignee["assignee_email"] 27 | 28 | sender_ = 'david.renton@genesys.com' 29 | recipients_ = [f'{init_["stories"][f"{story}"]["assignee"]}'] 30 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com'] 31 | title_ = 'DevFest Ireland' 32 | text_ = 'REMINDER - DevFest is awesome' 33 | body_ = email_body(story, story_status, init_["stories"][f"{story}"]["reminder"]) 34 | attachments_ = ['input/devfestireland_with_image.png'] 35 | try: 36 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_) 37 | print(response_) 38 | init_['stories'][f'{story}']['reminder'].append( 39 | f"Reminder email with subject {title_} was sent to {recipients_} on {date_}") 40 | except: 41 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 42 | json.dump(init_, outfile) 43 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 44 | json.dump(init_, outfile) 45 | 46 | 47 | if __name__ == "__main__": 48 | initiative_name = "go_to_devfest" 49 | main(initiative_name) 50 | 51 | with open(f'reports/{initiative_name}.json', 'r+') as initiative: 52 | init = json.load(initiative) 53 | print(json.dumps(init, indent=4)) 54 | -------------------------------------------------------------------------------- /src/jirascripting/get_assignable_users.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from src.jirascripting.auth_and_headers import jira_auth_and_headers 3 | import json 4 | 5 | 6 | def _get_assignable_users(key, start_from): 7 | auth, headers, base_url = jira_auth_and_headers() 8 | url = f"{base_url}/rest/api/3/user/assignable/search" 9 | 10 | query = { 11 | 'project': key, 12 | 'startAt': start_from 13 | } 14 | 15 | response = requests.request( 16 | "GET", 17 | url, 18 | headers=headers, 19 | params=query, 20 | auth=auth 21 | ) 22 | return response 23 | 24 | 25 | def get_all_assignable_users_name(project_key): 26 | """Returns a Json object with usernames mapped to logical ID 27 | Parameters: 28 | project_key (string): The key of an active project in the target Jira instance. 29 | Returns: 30 | response object: Json object with available users in the targeted Jira instance with their logical ID's. 31 | """ 32 | start_at = 0 33 | my_json = {} 34 | while start_at is not None: 35 | user_list_response = _get_assignable_users(project_key, start_at) 36 | text_contents = json.loads(user_list_response.text) 37 | for user in text_contents: 38 | my_json[f"{user.get('displayName', None)}"] = user.get('accountId', None) 39 | if len(text_contents) == 100: 40 | start_at = start_at + 100 41 | else: 42 | start_at = None 43 | 44 | return my_json 45 | 46 | 47 | def get_all_assignable_users_email(project_key): 48 | """Returns a Json object with email mapped to logical ID 49 | Parameters: 50 | project_key (string): The key of an active project in the target Jira instance. 51 | Returns: 52 | response object: Json object with available users in the targeted Jira instance with their logical ID's. 53 | """ 54 | start_at = 0 55 | my_json = {} 56 | while start_at is not None: 57 | user_list_response = _get_assignable_users(project_key, start_at) 58 | text_contents = json.loads(user_list_response.text) 59 | for user in text_contents: 60 | my_json[f"{user.get('emailAddress', None)}"] = user.get('accountId', None) 61 | if len(text_contents) == 100: 62 | start_at = start_at + 100 63 | else: 64 | start_at = None 65 | 66 | return my_json 67 | 68 | 69 | if __name__ == "__main__": 70 | jira_project_key = 'D1' 71 | returned_json_name = get_all_assignable_users_name(jira_project_key) 72 | print(json.dumps(returned_json_name, indent=4)) 73 | 74 | returned_json_email = get_all_assignable_users_email(jira_project_key) 75 | print(json.dumps(returned_json_email, indent=4)) -------------------------------------------------------------------------------- /src/jirascripting/create_jira_issue.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | from src import jira_auth_and_headers 4 | 5 | 6 | def create_issue(summary, project, description, epic_link=None, assignee_id=None, priority="High", issue_type="Story"): 7 | """Creates a story under an epic 8 | 9 | Parameters: 10 | summary (string): The issue summary. 11 | project (string): Project key eg. SECCOMPPM. 12 | description (string): The issue description. 13 | epic_link (string): The epic identifier eg: SECCOMPPM-93. 14 | assignee_id (string): The ID of the assignable user. 15 | issue_type (string): Text description of what entity you wish to create eg, Story, Bug, Task 16 | priority(string): Text Highest, High, Medium, Low, Lowest 17 | 18 | Returns: 19 | response object: This will have the response code and in the text will have the details of the created issue. 20 | 21 | """ 22 | auth, headers, base_url = jira_auth_and_headers() 23 | # create content 24 | content_list = [] 25 | paragraph_content = [] 26 | content_obj = {} 27 | content = {'text': description, 'type': "text"} 28 | content_obj['type'] = "paragraph" 29 | paragraph_content.append(content) 30 | content_obj['content'] = paragraph_content 31 | 32 | # create issue 33 | issue = {'fields': {}} 34 | issue['fields']['summary'] = summary 35 | issue['fields']['issuetype'] = {'name': issue_type} 36 | issue['fields']['project'] = {'key': project} 37 | content_list.append(content_obj) 38 | issue['fields']['description'] = {'type': "doc", 'version': 1, 'content': content_list} 39 | issue['fields']['priority'] = {'name': priority} 40 | if assignee_id is not None: 41 | issue['fields']['assignee'] = {'id': assignee_id} 42 | else: 43 | issue['fields']['assignee'] = {'id': "-1"} 44 | if epic_link is not None: 45 | issue['fields']['parent'] = {'key': epic_link} 46 | 47 | url = f"{base_url}/rest/api/3/issue" 48 | 49 | payload = json.dumps(issue) 50 | 51 | response = requests.request( 52 | "POST", 53 | url, 54 | data=payload, 55 | headers=headers, 56 | auth=auth 57 | ) 58 | return response 59 | 60 | 61 | if __name__ == "__main__": 62 | res = create_issue( 63 | summary="Delete Me" 64 | , project="D1" 65 | , description="This is a test, please delete me." 66 | , issue_type="Story" 67 | # , epic_link="D1-6" 68 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b" 69 | , priority='High' 70 | ) 71 | if res.status_code == 400: 72 | json_res = json.loads(res.text) 73 | print(json_res['errors']) 74 | else: 75 | json_res = json.loads(res.text) 76 | story_id = json_res['id'] 77 | story_key = json_res['key'] 78 | print(f"ID: {story_id}, Key: {story_key} ") -------------------------------------------------------------------------------- /src/jirascripting/create_jira_issue_with_parent.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | from src.jirascripting.auth_and_headers import jira_auth_and_headers 4 | 5 | 6 | def create_issue_parent(summary, project, description, assignee_id=None, priority="High", issue_type="Story", parent=None): 7 | """ 8 | Creates a story under an epic 9 | 10 | Parameters: 11 | parent (string): The key of the parent epic 12 | summary (string): The issue summary. 13 | project (string): Project key. 14 | description (string): The issue description. 15 | assignee_id (string): The ID of the assignable user. 16 | issue_type (string): Text description of what entity you wish to create eg, Story, Bug, Task 17 | priority(string): Text Highest, High, Medium, Low, Lowest 18 | 19 | Returns: 20 | response object: This will have the response code and in the text will have the details of the created issue. 21 | 22 | """ 23 | 24 | auth, headers, base_url = jira_auth_and_headers() 25 | # create content 26 | content_list = [] 27 | paragraph_content = [] 28 | content_obj = {} 29 | content = {'text': description, 'type': "text"} 30 | content_obj['type'] = "paragraph" 31 | paragraph_content.append(content) 32 | content_obj['content'] = paragraph_content 33 | 34 | # create issue 35 | issue = {'fields': {}} 36 | issue['fields']['summary'] = summary 37 | if parent is not None: 38 | issue['fields']['parent'] = {'key': parent} 39 | issue['fields']['issuetype'] = {'name': issue_type} 40 | issue['fields']['project'] = {'key': project} 41 | content_list.append(content_obj) 42 | issue['fields']['description'] = {'type': "doc", 'version': 1, 'content': content_list} 43 | issue['fields']['priority'] = {'name': priority} 44 | if assignee_id is not None: 45 | issue['fields']['assignee'] = {'id': assignee_id} 46 | else: 47 | issue['fields']['assignee'] = {'id': "-1"} 48 | 49 | url = f"{base_url}/rest/api/3/issue" 50 | 51 | payload = json.dumps(issue) 52 | 53 | response = requests.request( 54 | "POST", 55 | url, 56 | data=payload, 57 | headers=headers, 58 | auth=auth 59 | ) 60 | return response 61 | 62 | 63 | if __name__ == "__main__": 64 | res = create_issue_parent( 65 | summary="Parent test" 66 | , project="D1" 67 | , description="Parent test." 68 | , issue_type="Story" 69 | # , epic_link="D1-6" 70 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b" 71 | , priority='High' 72 | , parent='D1-7' 73 | ) 74 | if res.status_code == 400: 75 | json_res = json.loads(res.text) 76 | print(json_res['errors']) 77 | else: 78 | json_res = json.loads(res.text) 79 | story_id = json_res['id'] 80 | story_key = json_res['key'] 81 | print(f"ID: {story_id}, Key: {story_key} ") -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/part_1_create_assign_email.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import json 3 | 4 | from src import get_all_assignable_users_email 5 | from src import create_fancy_issue 6 | from emailer.aws_emailer.email_with_attachment import send_mail 7 | from part_4_creating_assigning_and_emailing._description_document import description_doc 8 | from part_4_creating_assigning_and_emailing._email_body import email_body 9 | 10 | assignable_users = get_all_assignable_users_email('D1') 11 | 12 | 13 | def main(file_): 14 | with open(file_) as infile: 15 | reader = csv.reader(infile, delimiter=",") 16 | # Skip the header 17 | next(reader, None) 18 | # For each row 19 | for row in reader: 20 | # get user id from email, this could be provided in th csv file 21 | # replace the below email with one from your jira instance 22 | assignable_user_email = 'davidleerenton@gmail.com' 23 | assignable_user_id = assignable_users.get(assignable_user_email, None) 24 | # these don't need to be assigned, this way just makes it more readable when debugging. 25 | first_name = row[1] 26 | last_name = row[2] 27 | email = row[3] 28 | gender = row[4] 29 | ip_address = row[5] 30 | message = row[6] 31 | project = row[7] 32 | # Create the description document 33 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message) 34 | # Build and execute the call to the Jira Cloud API 35 | res = create_fancy_issue( 36 | summary=f"From CSV - {first_name} {last_name}" 37 | , project=project 38 | , description_doc=description_document 39 | , issue_type="Story" 40 | , epic_link="D2-2" 41 | , assignee_id=assignable_user_id 42 | , priority='High' 43 | ) 44 | if res.status_code == 400: 45 | json_res = json.loads(res.text) 46 | print(json_res['errors']) 47 | else: 48 | json_res = json.loads(res.text) 49 | story_key = json_res['key'] 50 | print(f"Story created - Key: {story_key} ") 51 | 52 | # replace the sender_ email with the one registered in AWS SES 53 | sender_ = 'david.renton@genesys.com' 54 | recipients_ = [f'{assignable_user_email}'] 55 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com'] 56 | title_ = 'DevFest Ireland' 57 | text_ = 'DevFest is awesome' 58 | body_ = email_body(first_name, last_name, gender, ip_address, message, project, story_key) 59 | attachments_ = ['input/devfestireland_with_image.png'] 60 | 61 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_) 62 | print(response_) 63 | 64 | 65 | if __name__ == "__main__": 66 | input_file = "input/MOCK_DATA_WITH_PROJECT.csv" 67 | main(input_file) 68 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '40 9 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Use only 'java' to analyze code written in Java, Kotlin or both 38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 40 | 41 | steps: 42 | - name: Checkout repository 43 | uses: actions/checkout@v3 44 | 45 | # Initializes the CodeQL tools for scanning. 46 | - name: Initialize CodeQL 47 | uses: github/codeql-action/init@v2 48 | with: 49 | languages: ${{ matrix.language }} 50 | # If you wish to specify custom queries, you can do so here or in a config file. 51 | # By default, queries listed here will override any specified in a config file. 52 | # Prefix the list here with "+" to use these queries and those in the config file. 53 | 54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 55 | # queries: security-extended,security-and-quality 56 | 57 | 58 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 59 | # If this step fails, then you should remove it and run the build manually (see below) 60 | - name: Autobuild 61 | uses: github/codeql-action/autobuild@v2 62 | 63 | # ℹ️ Command-line programs to run using the OS shell. 64 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 65 | 66 | # If the Autobuild fails above, remove it and uncomment the following three lines. 67 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 68 | 69 | # - run: | 70 | # echo "Run, Build Application using script" 71 | # ./location_of_script_within_repo/buildscript.sh 72 | 73 | - name: Perform CodeQL Analysis 74 | uses: github/codeql-action/analyze@v2 75 | with: 76 | category: "/language:${{matrix.language}}" 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .idea/* 106 | .env 107 | .venv 108 | env/ 109 | venv/ 110 | ENV/ 111 | env.bak/ 112 | venv.bak/ 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | /site 123 | 124 | # mypy 125 | .mypy_cache/ 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre/ 131 | 132 | # project speciffic 133 | .env 134 | .idea 135 | .idea/* 136 | 137 | just_for_fun/images.* 138 | !just_for_fun/qr_code/images/.gitkeep 139 | 140 | just_for_fun/qr_codes.* 141 | !just_for_fun/qr_code/qr_codes/.gitkeep 142 | 143 | part_1_story_creation/reports/* 144 | !part_1_story_creation/reports/.gitkeep 145 | 146 | part_2_epic_creation/reports/* 147 | !part_2_epic_creation/reports/.gitkeep 148 | 149 | part_3_creating_from_csv/input/* 150 | !part_3_creating_from_csv/input/.gitkeep 151 | !part_3_creating_from_csv/input/MOCK_DATA.csv 152 | !part_3_creating_from_csv/input/MOCK_DATA_WITH_PROJECT.csv 153 | 154 | part_4_creating_assigning_and_emailing/input* 155 | !part_4_creating_assigning_and_emailing/input/.gitkeep 156 | !part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT.csv 157 | !part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_3_lines.csv 158 | !part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_6_lines.csv 159 | 160 | part_4_creating_assigning_and_emailing/reports/* 161 | !part_4_creating_assigning_and_emailing/reports/.gitkeep 162 | 163 | 164 | part_0_my_jira_cloud_instance/output/* 165 | !part_0_my_jira_cloud_instance/output/.gitkeep 166 | 167 | -------------------------------------------------------------------------------- /emailer/aws_emailer/email_with_attachment.py: -------------------------------------------------------------------------------- 1 | import os 2 | import boto3 3 | from email.mime.multipart import MIMEMultipart 4 | from email.mime.text import MIMEText 5 | from email.mime.application import MIMEApplication 6 | 7 | 8 | def create_multipart_message( 9 | sender: str, recipients: list, cc: list, title: str, text: str = None, html: str = None, attachments: list = None) \ 10 | -> MIMEMultipart: 11 | """ 12 | Creates a MIME multipart message object. 13 | Uses only the Python `email` standard library. 14 | Emails, both sender and recipients, can be just the email string or have the format 'The Name '. 15 | 16 | :param sender: The sender. 17 | :param recipients: List of recipients. Needs to be a list, even if only one recipient. 18 | :param title: The title of the email. 19 | :param text: The text version of the email body (optional). 20 | :param html: The html version of the email body (optional). 21 | :param attachments: List of files to attach in the email. 22 | :return: A `MIMEMultipart` to be used to send the email. 23 | """ 24 | multipart_content_subtype = 'alternative' if text and html else 'mixed' 25 | msg = MIMEMultipart(multipart_content_subtype) 26 | msg['Subject'] = title 27 | msg['From'] = sender 28 | msg['To'] = ', '.join(recipients) 29 | msg['Cc'] = ', '.join(cc) 30 | 31 | # Record the MIME types of both parts - text/plain and text/html. 32 | # According to RFC 2046, the last part of a multipart message, in this case the HTML message, is best and preferred. 33 | if text: 34 | part = MIMEText(text, 'plain') 35 | msg.attach(part) 36 | if html: 37 | part = MIMEText(html, 'html') 38 | msg.attach(part) 39 | 40 | # Add attachments 41 | for attachment in attachments or []: 42 | with open(attachment, 'rb') as f: 43 | part = MIMEApplication(f.read()) 44 | part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment)) 45 | msg.attach(part) 46 | 47 | return msg 48 | 49 | 50 | def send_mail( 51 | sender: str, recipients: list, cc: list, title: str, text: str = None, html: str = None, 52 | attachments: list = None) -> dict: 53 | """ 54 | Send email to recipients. Sends one mail to all recipients. 55 | The sender needs to be a verified email in SES. 56 | """ 57 | msg = create_multipart_message(sender, recipients, cc, title, text, html, attachments) 58 | ses_client = boto3.client('ses') # Use your settings here 59 | 60 | # If you are using this in a personal capacity and want to add credentials directly use the method below 61 | # ses_client = boto3.client('ses', 62 | # aws_access_key_id=settings.AWS_SERVER_PUBLIC_KEY, 63 | # aws_secret_access_key=settings.AWS_SERVER_SECRET_KEY, 64 | # region_name=REGION_NAME 65 | # ) 66 | final_destinations = recipients + cc 67 | return ses_client.send_raw_email( 68 | Source=sender, 69 | Destinations=final_destinations, 70 | RawMessage={'Data': msg.as_string()} 71 | ) 72 | 73 | 74 | if __name__ == '__main__': 75 | # replace sender_ with the email address you registered in AWS SES 76 | sender_ = 'david.renton@genesys.com' 77 | recipients_ = ['devfestireland@gmail.com'] 78 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com'] 79 | title_ = 'DevFest' 80 | text_ = 'DevFest is awesome' 81 | body_ = """

A header 1


Some text.""" 82 | attachments_ = ['../../just_for_fun/qr_code/qr_codes/with_image.png'] 83 | 84 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_) 85 | print(response_) 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JiraScripting 2 | 3 | This repo is being made available as is, minimal tidy-up has been done, I will continue to support and refactor as time allows (pull requests welcome). 4 | 5 | This is code I have used to create hundreds of Jira tickets in minutes saving hours/days of Jira Donkey work. 6 | 7 | Refactors, updates, additions and new ways of using this would be greatly appreciated, please consider contributing. 8 | 9 | ## What is this repository for? ## 10 | 11 | * Quick summary: 12 | * Automating Jira Epic & Story creation 13 | * Commenting on issues 14 | * Emailing assignees 15 | * Tracking actions performed for easy follow up 16 | 17 | ### Usecases ### 18 | 19 | * Audit request list (SOC2, C5, PCI DSS) 20 | * Gap analysis output (Any security gap list from any consultancy) 21 | * CVE check (Verify non-existence, not vulnerable or updated across many teams with report as evidence) 22 | * Quarterly security check output that needs to be remediated 23 | * Multi project upgrade work (e.g. all services need to upgrade encryption to TLS 1.3 or FIPS 140-3) 24 | * Output work from Datadog or Sumo Logic 25 | 26 | 27 | ## How do I get set up? ## 28 | * Normal Python 3.10 or higher setup should be followed, download Python here - https://www.python.org/downloads/. 29 | * A virtual environment should be set up `python -m venv .` 30 | * Activate the virtual environment `source venv/bin/activate` (this may be different on your system, check the created venv folder to ensure the path to the activate.py file is the same) 31 | * Install the imported packages `pip install -r requirements.txt` (this may be different on your system depending on the pip alias) 32 | * Set up a free instance of Jira Cloud `https://www.atlassian.com/software/jira/free` 33 | * This demo was set up with three Kanban, Company managed projects named 'Demo 1', 'Demo 2' and 'Demo 3' with keys 'D1', 'D2' and 'D3' for ease of following along, the user may wish to create these also. 34 | * This demo also has added two alternative emails so the user can see how the system reacts to users that are not the admin, this is not mandatory, however it is suggested the user do the same. 35 | * Create a copy of the .env_template file and name it `.env` exactly 36 | * Fill out the necessary fields in the newly created .env file (BASE_URL should look like this - https://YOURPROJECT.atlassian.net) 37 | * Your API token can be created by: 38 | 1. logging into Jira Cloud (the one you created earlier) 39 | 2. Click on your avatar in the top right 40 | 3. Click Account Settings 41 | 4. Navigate to the Security tab on the left 42 | 5. Click Create and manage API tokens 43 | * If creating stories from a CSV file, place it in the inputs folder to avoid sensitive data being committed to the repo. 44 | * If creating a report output file (Json files are outputted by some scripts), please put it in the reports folder to avoid sensitive data being committed to the repo. 45 | 46 | 47 | ## I'm set up, what's next? ## 48 | * The repository is set up in folders bringing the user from the basic operations through to the more complete solutions. Part 0 through to part 4. 49 | * Some functionality is offered in its own folder for easy transplanting into the learner's project for example assignable_users and emailer. 50 | * The just_for_fun folder is a collection of code used for pairing a presentation on this repository so is offered here as it may help someone down the line. 51 | 52 | 53 | 54 | * At present this is a collection of scripts that can be used independently or combined to accomplish more complex Jira tasks. 55 | * Some files committed to the repo are designed to accomplish specific goals and can serve as an example of how the different files can be combined. 56 | * To use the aws_emailer or GCP emailer an active account with separate credentials is needed. 57 | 58 | 59 | ### Contribution guidelines ### 60 | 61 | * Please contribute frequently and openly! 62 | 63 | ### Who do I talk to? ### 64 | 65 | * Original Creator - David Renton david.renton@genesys.com 66 | -------------------------------------------------------------------------------- /part_3_creating_from_csv/_description_document.py: -------------------------------------------------------------------------------- 1 | # This file is imported by the part_3_create_in_projects_defined_in_csv.py and part_2_create_fancy_from_csv.py files 2 | # The json object assigned to fancy_description is generated from - https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ 3 | 4 | def description_doc(first_name, last_name, email, gender, ip_address, message): 5 | fancy_description = { 6 | "version": 1, 7 | "type": "doc", 8 | "content": [ 9 | { 10 | "type": "heading", 11 | "attrs": { 12 | "level": 1 13 | }, 14 | "content": [ 15 | { 16 | "type": "text", 17 | "text": f"Hey {first_name} {last_name} " 18 | }, 19 | { 20 | "type": "emoji", 21 | "attrs": { 22 | "shortName": ":wave:", 23 | "id": "1f44b", 24 | "text": "👋" 25 | } 26 | }, 27 | { 28 | "type": "text", 29 | "text": " " 30 | } 31 | ] 32 | }, 33 | { 34 | "type": "paragraph", 35 | "content": [ 36 | { 37 | "type": "text", 38 | "text": "This story description was build " 39 | }, 40 | { 41 | "type": "text", 42 | "text": "here", 43 | "marks": [ 44 | { 45 | "type": "link", 46 | "attrs": { 47 | "href": "https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/" 48 | } 49 | } 50 | ] 51 | }, 52 | { 53 | "type": "text", 54 | "text": " !" 55 | } 56 | ] 57 | }, 58 | { 59 | "type": "paragraph", 60 | "content": [ 61 | { 62 | "type": "text", 63 | "text": "Email, " 64 | }, 65 | { 66 | "type": "text", 67 | "text": f"could have been used to assign the ticket {email}", 68 | "marks": [ 69 | { 70 | "type": "em" 71 | } 72 | ] 73 | }, 74 | { 75 | "type": "text", 76 | "text": " " 77 | }, 78 | { 79 | "type": "emoji", 80 | "attrs": { 81 | "shortName": ":man_shrugging:", 82 | "id": "1f937-200d-2642-fe0f", 83 | "text": "🤷‍♂️" 84 | } 85 | }, 86 | { 87 | "type": "text", 88 | "text": " " 89 | } 90 | ] 91 | }, 92 | { 93 | "type": "bulletList", 94 | "content": [ 95 | { 96 | "type": "listItem", 97 | "content": [ 98 | { 99 | "type": "paragraph", 100 | "content": [ 101 | { 102 | "type": "text", 103 | "text": f"Gender : {gender}" 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | { 110 | "type": "listItem", 111 | "content": [ 112 | { 113 | "type": "paragraph", 114 | "content": [ 115 | { 116 | "type": "text", 117 | "text": f"IP : {ip_address}" 118 | } 119 | ] 120 | } 121 | ] 122 | }, 123 | { 124 | "type": "listItem", 125 | "content": [ 126 | { 127 | "type": "paragraph", 128 | "content": [ 129 | { 130 | "type": "text", 131 | "text": f"Message : {message}" 132 | } 133 | ] 134 | } 135 | ] 136 | } 137 | ] 138 | }, 139 | { 140 | "type": "paragraph", 141 | "content": [ 142 | { 143 | "type": "text", 144 | "text": "This is some code:" 145 | } 146 | ] 147 | }, 148 | { 149 | "type": "codeBlock", 150 | "attrs": { 151 | "language": "python" 152 | }, 153 | "content": [ 154 | { 155 | "type": "text", 156 | "text": "res = create_issue(\n summary=f\"From CSV - {first_name} {last_name}\"\n , project=\"D2\"\n , description_doc=description_document\n , issue_type=\"Story\"\n , epic_link=\"D2-2\"\n , assignee_id=assignable_user_id\n , priority='High'\n)" 157 | } 158 | ] 159 | }, 160 | { 161 | "type": "paragraph", 162 | "content": [] 163 | } 164 | ] 165 | } 166 | 167 | return fancy_description 168 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/_description_document.py: -------------------------------------------------------------------------------- 1 | # This file is imported by the part_3_create_in_projects_defined_in_csv.py and part_2_create_fancy_from_csv.py files 2 | # The json object assigned to fancy_description is generated from - https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ 3 | 4 | def description_doc(first_name, last_name, email, gender, ip_address, message): 5 | fancy_description = { 6 | "version": 1, 7 | "type": "doc", 8 | "content": [ 9 | { 10 | "type": "heading", 11 | "attrs": { 12 | "level": 1 13 | }, 14 | "content": [ 15 | { 16 | "type": "text", 17 | "text": f"Hey {first_name} {last_name} " 18 | }, 19 | { 20 | "type": "emoji", 21 | "attrs": { 22 | "shortName": ":wave:", 23 | "id": "1f44b", 24 | "text": "👋" 25 | } 26 | }, 27 | { 28 | "type": "text", 29 | "text": " " 30 | } 31 | ] 32 | }, 33 | { 34 | "type": "paragraph", 35 | "content": [ 36 | { 37 | "type": "text", 38 | "text": "This story description was build " 39 | }, 40 | { 41 | "type": "text", 42 | "text": "here", 43 | "marks": [ 44 | { 45 | "type": "link", 46 | "attrs": { 47 | "href": "https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/" 48 | } 49 | } 50 | ] 51 | }, 52 | { 53 | "type": "text", 54 | "text": " !" 55 | } 56 | ] 57 | }, 58 | { 59 | "type": "paragraph", 60 | "content": [ 61 | { 62 | "type": "text", 63 | "text": "Email, " 64 | }, 65 | { 66 | "type": "text", 67 | "text": f"could have been used to assign the ticket {email}", 68 | "marks": [ 69 | { 70 | "type": "em" 71 | } 72 | ] 73 | }, 74 | { 75 | "type": "text", 76 | "text": " " 77 | }, 78 | { 79 | "type": "emoji", 80 | "attrs": { 81 | "shortName": ":man_shrugging:", 82 | "id": "1f937-200d-2642-fe0f", 83 | "text": "🤷‍♂️" 84 | } 85 | }, 86 | { 87 | "type": "text", 88 | "text": " " 89 | } 90 | ] 91 | }, 92 | { 93 | "type": "bulletList", 94 | "content": [ 95 | { 96 | "type": "listItem", 97 | "content": [ 98 | { 99 | "type": "paragraph", 100 | "content": [ 101 | { 102 | "type": "text", 103 | "text": f"Gender : {gender}" 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | { 110 | "type": "listItem", 111 | "content": [ 112 | { 113 | "type": "paragraph", 114 | "content": [ 115 | { 116 | "type": "text", 117 | "text": f"IP : {ip_address}" 118 | } 119 | ] 120 | } 121 | ] 122 | }, 123 | { 124 | "type": "listItem", 125 | "content": [ 126 | { 127 | "type": "paragraph", 128 | "content": [ 129 | { 130 | "type": "text", 131 | "text": f"Message : {message}" 132 | } 133 | ] 134 | } 135 | ] 136 | } 137 | ] 138 | }, 139 | { 140 | "type": "paragraph", 141 | "content": [ 142 | { 143 | "type": "text", 144 | "text": "This is some code:" 145 | } 146 | ] 147 | }, 148 | { 149 | "type": "codeBlock", 150 | "attrs": { 151 | "language": "python" 152 | }, 153 | "content": [ 154 | { 155 | "type": "text", 156 | "text": "res = create_issue(\n summary=f\"From CSV - {first_name} {last_name}\"\n , project=\"D2\"\n , description_doc=description_document\n , issue_type=\"Story\"\n , epic_link=\"D2-2\"\n , assignee_id=assignable_user_id\n , priority='High'\n)" 157 | } 158 | ] 159 | }, 160 | { 161 | "type": "paragraph", 162 | "content": [] 163 | } 164 | ] 165 | } 166 | 167 | return fancy_description 168 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/part_2_create_assign_email_prepaired_for_follow_up.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import hashlib 3 | import json 4 | import os 5 | from datetime import datetime 6 | 7 | from src import get_all_assignable_users_email 8 | from src import create_fancy_issue 9 | from emailer.aws_emailer.email_with_attachment import send_mail 10 | from part_4_creating_assigning_and_emailing._description_document import description_doc 11 | from part_4_creating_assigning_and_emailing._email_body import email_body 12 | 13 | assignable_users = get_all_assignable_users_email('D1') 14 | 15 | 16 | def main(file_, epic_, initiative_name_): 17 | init_ = {} 18 | f_name = f"reports/{initiative_name_}.json" 19 | if os.path.exists(f_name): 20 | with open(f'reports/{initiative_name_}.json', 'r+') as initiative_: 21 | init_ = json.load(initiative_) 22 | else: 23 | init_['created'] = [] 24 | init_['stories'] = {} 25 | with open(file_) as infile: 26 | reader = csv.reader(infile, delimiter=",") 27 | # Skip the header 28 | next(reader, None) 29 | # For each row 30 | for row in reader: 31 | row_tuple = tuple(row) 32 | hash_ = hashlib.md5() 33 | for entry in row_tuple: 34 | hash_.update(entry.encode()) 35 | row_hash = hash_.hexdigest() 36 | # Are we doing work or not? 37 | if row_hash not in init_['created']: 38 | # get user id from email, this could be provided in th csv file 39 | date_ = datetime.now() 40 | assignable_user_email = 'davidleerenton@gmail.com' 41 | assignable_user_id = assignable_users.get(assignable_user_email, None) 42 | # these don't need to be assigned, this way just makes it more readable when debugging. 43 | first_name = row[1] 44 | last_name = row[2] 45 | email = row[3] 46 | gender = row[4] 47 | ip_address = row[5] 48 | message = row[6] 49 | project = row[7] 50 | # Create the description document 51 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message) 52 | # Build and execute the call to the Jira Cloud API 53 | try: 54 | res = create_fancy_issue( 55 | summary=f"From CSV - {first_name} {last_name}" 56 | , project=project 57 | , description_doc=description_document 58 | , issue_type="Story" 59 | , epic_link=epic_ 60 | , assignee_id=assignable_user_id 61 | , priority='High' 62 | ) 63 | json_res = json.loads(res.text) 64 | story_key = json_res['key'] 65 | init_['stories'][f'{story_key}'] = { 66 | "date_opened": f"{date_}", 67 | "assignee": f"{assignable_user_email}", 68 | "assignee_id": f"{assignable_user_id}", 69 | "hash": f"{row_hash}", 70 | "status_category": "new", 71 | "reminder": [] 72 | } 73 | init_['created'].append(row_hash) 74 | except Exception as e: 75 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 76 | json.dump(init_, outfile) 77 | print(f"Exception: {e} \nFor: {row}") 78 | 79 | sender_ = 'david.renton@genesys.com' 80 | recipients_ = [f'{assignable_user_email}'] 81 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com'] 82 | title_ = 'DevFest Ireland' 83 | text_ = 'DevFest is awesome' 84 | body_ = email_body(first_name, last_name, gender, ip_address, message, project, story_key) 85 | attachments_ = ['input/devfestireland_with_image.png'] 86 | try: 87 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_) 88 | print(response_) 89 | init_['stories'][f'{story_key}']['reminder'].append(f"Email with subject {title_} was sent to {recipients_} on {date_}") 90 | except: 91 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 92 | json.dump(init_, outfile) 93 | with open(f'reports/{initiative_name_}.json', 'w') as outfile: 94 | json.dump(init_, outfile) 95 | 96 | 97 | if __name__ == "__main__": 98 | initiative_name = "go_to_devfest" 99 | input_file = "input/MOCK_DATA_WITH_PROJECT.csv" 100 | epic = "D2-2" 101 | main(input_file, epic, initiative_name) 102 | 103 | with open(f'reports/{initiative_name}.json', 'r+') as initiative: 104 | init = json.load(initiative) 105 | print(json.dumps(init, indent=4)) 106 | 107 | # # Some stories got added 108 | # ready_to_add_some_more = input("Ready to add more stories?") 109 | # initiative_name = "go_to_devfest" 110 | # input_file = "input/MOCK_DATA_WITH_PROJECT_6_lines.csv" 111 | # main(input_file, epic, initiative_name) 112 | # 113 | # ready_to_see_the_result_2 = input("press any key") 114 | # with open(f'reports/{initiative_name}.json', 'r+') as initiative: 115 | # init = json.load(initiative) 116 | # print(json.dumps(init, indent=4)) 117 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | david.renton@genesys.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /src/jirascripting/create_fancy_jira_issue.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from src.jirascripting.auth_and_headers import jira_auth_and_headers 4 | 5 | 6 | def create_fancy_issue(summary, project, description_doc, parent=None, assignee_id=None, priority="High", issue_type="Story"): 7 | """Creates an ADF(markdown) story under an epic, use the pyadf library to build out the description document 8 | https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ 9 | 10 | Parameters: 11 | :param summary: (string) The issue summary. 12 | :param project: (string) Project key eg. D1-1. 13 | :param description_doc: (string) Use the Document Builder here https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/. 14 | :param parent: (string): The key of the parent epic 15 | :param assignee_id: (string) The ID of the assignable user (use get_assignable_users to get this). 16 | :param issue_type: (string) Text name of the issue type you wish to create eg, Story, Bug, Task 17 | :param priority: (string) Text - Highest, High, Medium, Low, Lowest 18 | 19 | Returns: 20 | response object: This will have the response code and in the text will have the details of the created issue. 21 | 22 | """ 23 | auth, headers, base_url = jira_auth_and_headers() 24 | 25 | # create issue 26 | issue = {'fields': {}} 27 | if parent is not None: 28 | issue['fields']['parent'] = {'key': parent} 29 | issue['fields']['summary'] = summary 30 | issue['fields']['issuetype'] = {'name': issue_type} 31 | issue['fields']['project'] = {'key': project} 32 | issue['fields']['description'] = description_doc 33 | issue['fields']['priority'] = {'name': priority} 34 | if assignee_id is not None: 35 | issue['fields']['assignee'] = {'id': assignee_id} 36 | else: 37 | issue['fields']['assignee'] = {'id': "-1"} 38 | 39 | url = f"{base_url}/rest/api/3/issue" 40 | payload = json.dumps(issue) 41 | response = requests.request( 42 | "POST", 43 | url, 44 | data=payload, 45 | headers=headers, 46 | auth=auth 47 | ) 48 | return response 49 | 50 | 51 | if __name__ == "__main__": 52 | formatted_description = { 53 | "version": 1, 54 | "type": "doc", 55 | "content": [ 56 | { 57 | "type": "paragraph", 58 | "content": [ 59 | { 60 | "type": "text", 61 | "text": "Generated from the " 62 | }, 63 | { 64 | "type": "text", 65 | "text": "Document Builder", 66 | "marks": [ 67 | { 68 | "type": "link", 69 | "attrs": { 70 | "href": "https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/" 71 | } 72 | } 73 | ] 74 | } 75 | ] 76 | }, 77 | { 78 | "type": "paragraph", 79 | "content": [ 80 | { 81 | "type": "text", 82 | "text": "I am bold", 83 | "marks": [ 84 | { 85 | "type": "strong" 86 | } 87 | ] 88 | } 89 | ] 90 | }, 91 | { 92 | "type": "paragraph", 93 | "content": [ 94 | { 95 | "type": "text", 96 | "text": "I am itallic", 97 | "marks": [ 98 | { 99 | "type": "em" 100 | } 101 | ] 102 | } 103 | ] 104 | }, 105 | { 106 | "type": "paragraph", 107 | "content": [ 108 | { 109 | "type": "text", 110 | "text": "List" 111 | } 112 | ] 113 | }, 114 | { 115 | "type": "bulletList", 116 | "content": [ 117 | { 118 | "type": "listItem", 119 | "content": [ 120 | { 121 | "type": "paragraph", 122 | "content": [ 123 | { 124 | "type": "text", 125 | "text": "one" 126 | } 127 | ] 128 | } 129 | ] 130 | }, 131 | { 132 | "type": "listItem", 133 | "content": [ 134 | { 135 | "type": "paragraph", 136 | "content": [ 137 | { 138 | "type": "text", 139 | "text": "two" 140 | } 141 | ] 142 | } 143 | ] 144 | }, 145 | { 146 | "type": "listItem", 147 | "content": [ 148 | { 149 | "type": "paragraph", 150 | "content": [ 151 | { 152 | "type": "text", 153 | "text": "three" 154 | } 155 | ] 156 | } 157 | ] 158 | } 159 | ] 160 | }, 161 | { 162 | "type": "paragraph", 163 | "content": [] 164 | }, 165 | { 166 | "type": "codeBlock", 167 | "attrs": { 168 | "language": "python" 169 | }, 170 | "content": [ 171 | { 172 | "type": "text", 173 | "text": "def some_python_method():\n me = some_variable\n return me" 174 | } 175 | ] 176 | } 177 | ] 178 | } 179 | res = create_fancy_issue( 180 | summary="MarkDown Test" 181 | , project="D1" 182 | , description_doc=formatted_description 183 | , issue_type="Story" 184 | # , epic_link="SECCOMPPM-6" 185 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b" 186 | , priority='High' 187 | ) 188 | if res.status_code == 400: 189 | json_res = json.loads(res.text) 190 | print(json_res['errors']) 191 | else: 192 | json_res = json.loads(res.text) 193 | story_id = json_res['id'] 194 | story_key = json_res['key'] 195 | print(f"ID: {story_id}, Key: {story_key} ") 196 | -------------------------------------------------------------------------------- /just_for_fun/file_access/input/MOCK_DATA.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui 5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie 6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum 7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum 8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida 9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus 10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus 11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed 12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur 13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec 14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum 15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat 16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia 17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis 18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie 19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh 20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti 21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu 22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at 23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec 24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper 25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac 26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend 27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in 28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue 29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl 30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in 31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere 32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet 33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis 34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus 35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu 36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis 37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id 38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet 39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus 40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit 41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum 42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue 43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum 44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut 45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim 46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec 47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue 48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed 49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at 50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien 51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in 52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi 53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula 54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi 55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi 56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris 57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque 58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus 59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer 60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus 61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam 62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer 63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam 64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus 65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra 66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus 67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin 68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam 69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin 70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat 71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi 72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue 73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit 74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia 75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea 76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci 77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a 78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget 79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet 80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere 81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec 82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra 83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci 84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo 85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id 86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti 87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget 88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut 89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum 90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst 91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae 92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla 93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque 94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes 95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc 96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi 97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem 98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit 99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci 100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis 101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam 102 | -------------------------------------------------------------------------------- /part_3_creating_from_csv/input/MOCK_DATA.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui 5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie 6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum 7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum 8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida 9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus 10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus 11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed 12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur 13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec 14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum 15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat 16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia 17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis 18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie 19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh 20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti 21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu 22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at 23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec 24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper 25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac 26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend 27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in 28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue 29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl 30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in 31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere 32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet 33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis 34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus 35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu 36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis 37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id 38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet 39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus 40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit 41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum 42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue 43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum 44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut 45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim 46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec 47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue 48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed 49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at 50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien 51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in 52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi 53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula 54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi 55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi 56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris 57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque 58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus 59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer 60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus 61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam 62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer 63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam 64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus 65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra 66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus 67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin 68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam 69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin 70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat 71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi 72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue 73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit 74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia 75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea 76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci 77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a 78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget 79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet 80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere 81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec 82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra 83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci 84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo 85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id 86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti 87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget 88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut 89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum 90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst 91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae 92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla 93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque 94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes 95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc 96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi 97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem 98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit 99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci 100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis 101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam 102 | -------------------------------------------------------------------------------- /just_for_fun/file_access/output/MOCK_DATA_WITH_PROJECT.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message,project 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3 5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3 6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3 7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2 8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida,D3 9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus,D1 10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus,D3 11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed,D3 12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur,D3 13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec,D3 14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum,D3 15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat,D2 16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia,D1 17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis,D3 18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie,D2 19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh,D3 20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti,D1 21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu,D1 22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D1 23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec,D1 24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper,D3 25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac,D2 26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend,D1 27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in,D2 28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1 29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl,D1 30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in,D1 31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere,D1 32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D3 33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis,D3 34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus,D1 35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu,D1 36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis,D2 37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id,D3 38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D1 39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus,D3 40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit,D1 41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum,D3 42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D2 43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum,D3 44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut,D1 45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim,D1 46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec,D3 47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue,D1 48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed,D3 49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D2 50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien,D3 51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in,D2 52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi,D2 53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula,D1 54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi,D1 55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi,D1 56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris,D3 57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque,D2 58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus,D2 59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer,D3 60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus,D2 61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam,D1 62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer,D2 63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam,D3 64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus,D2 65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,D3 66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus,D2 67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin,D3 68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam,D2 69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin,D2 70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,D2 71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi,D2 72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1 73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit,D2 74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia,D1 75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea,D1 76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci,D2 77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a,D1 78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget,D1 79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet,D2 80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere,D3 81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec,D3 82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra,D1 83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci,D2 84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo,D2 85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id,D1 86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti,D2 87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget,D3 88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut,D2 89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum,D3 90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst,D2 91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae,D2 92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla,D2 93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque,D1 94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes,D1 95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc,D3 96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi,D1 97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem,D1 98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit,D3 99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci,D3 100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis,D2 101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,D3 102 | -------------------------------------------------------------------------------- /part_3_creating_from_csv/input/MOCK_DATA_WITH_PROJECT.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message,project 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3 5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3 6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3 7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2 8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida,D3 9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus,D1 10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus,D3 11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed,D3 12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur,D3 13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec,D3 14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum,D3 15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat,D2 16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia,D1 17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis,D3 18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie,D2 19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh,D3 20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti,D1 21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu,D1 22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D1 23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec,D1 24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper,D3 25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac,D2 26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend,D1 27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in,D2 28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1 29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl,D1 30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in,D1 31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere,D1 32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D3 33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis,D3 34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus,D1 35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu,D1 36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis,D2 37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id,D3 38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D1 39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus,D3 40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit,D1 41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum,D3 42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D2 43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum,D3 44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut,D1 45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim,D1 46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec,D3 47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue,D1 48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed,D3 49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D2 50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien,D3 51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in,D2 52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi,D2 53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula,D1 54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi,D1 55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi,D1 56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris,D3 57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque,D2 58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus,D2 59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer,D3 60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus,D2 61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam,D1 62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer,D2 63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam,D3 64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus,D2 65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,D3 66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus,D2 67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin,D3 68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam,D2 69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin,D2 70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,D2 71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi,D2 72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1 73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit,D2 74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia,D1 75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea,D1 76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci,D2 77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a,D1 78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget,D1 79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet,D2 80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere,D3 81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec,D3 82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra,D1 83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci,D2 84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo,D2 85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id,D1 86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti,D2 87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget,D3 88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut,D2 89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum,D3 90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst,D2 91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae,D2 92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla,D2 93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque,D1 94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes,D1 95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc,D3 96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi,D1 97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem,D1 98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit,D3 99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci,D3 100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis,D2 101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,D3 102 | -------------------------------------------------------------------------------- /part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT.csv: -------------------------------------------------------------------------------- 1 | id,first_name,last_name,email,gender,ip_address,message,project 2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2 3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2 4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3 5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3 6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3 7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2 8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida,D3 9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus,D1 10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus,D3 11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed,D3 12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur,D3 13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec,D3 14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum,D3 15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat,D2 16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia,D1 17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis,D3 18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie,D2 19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh,D3 20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti,D1 21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu,D1 22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D1 23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec,D1 24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper,D3 25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac,D2 26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend,D1 27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in,D2 28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1 29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl,D1 30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in,D1 31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere,D1 32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D3 33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis,D3 34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus,D1 35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu,D1 36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis,D2 37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id,D3 38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D1 39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus,D3 40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit,D1 41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum,D3 42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D2 43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum,D3 44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut,D1 45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim,D1 46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec,D3 47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue,D1 48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed,D3 49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D2 50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien,D3 51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in,D2 52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi,D2 53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula,D1 54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi,D1 55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi,D1 56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris,D3 57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque,D2 58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus,D2 59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer,D3 60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus,D2 61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam,D1 62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer,D2 63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam,D3 64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus,D2 65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,D3 66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus,D2 67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin,D3 68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam,D2 69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin,D2 70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,D2 71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi,D2 72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1 73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit,D2 74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia,D1 75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea,D1 76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci,D2 77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a,D1 78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget,D1 79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet,D2 80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere,D3 81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec,D3 82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra,D1 83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci,D2 84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo,D2 85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id,D1 86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti,D2 87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget,D3 88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut,D2 89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum,D3 90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst,D2 91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae,D2 92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla,D2 93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque,D1 94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes,D1 95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc,D3 96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi,D1 97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem,D1 98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit,D3 99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci,D3 100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis,D2 101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,D3 102 | -------------------------------------------------------------------------------- /src/jirascripting/helpers.py: -------------------------------------------------------------------------------- 1 | 2 | import requests 3 | from src.jirascripting.auth_and_headers import jira_auth_and_headers 4 | import json 5 | 6 | 7 | def get_issue(this_issue_key): 8 | """Gets all fields for the epic or story queried 9 | 10 | Parameters: 11 | this_issue_key (string): issue identifier eg: D1-1 12 | Returns: 13 | Json Object: Object has all fields available set and vacant for the story/epic 14 | 15 | """ 16 | auth, headers, base_url = jira_auth_and_headers() 17 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}" 18 | 19 | response = requests.request( 20 | "GET", 21 | url, 22 | headers=headers, 23 | auth=auth 24 | ) 25 | text_contents = json.loads(response.text) 26 | return text_contents 27 | 28 | 29 | def get_servicedesk_issue(this_issue_key): 30 | """Gets all fields for the epic or story queried 31 | 32 | Parameters: 33 | this_issue_key (string): issue identifier eg: D1-1 34 | Returns: 35 | Json Object: Object has all fields available set and vacant for the story/epic 36 | 37 | """ 38 | auth, headers, base_url = jira_auth_and_headers() 39 | url = f"{base_url}/rest/servicedeskapi/request/{this_issue_key}" 40 | 41 | response = requests.request( 42 | "GET", 43 | url, 44 | headers=headers, 45 | auth=auth 46 | ) 47 | text_contents = json.loads(response.text) 48 | return text_contents 49 | 50 | 51 | def get_issue_status_category(this_issue_key): 52 | """Gets all fields for the epic or story queried and returns the status category 53 | 54 | Parameters: 55 | this_issue_key (string): issue identifier eg: D1-1 56 | Returns: 57 | String: status category new, indeterminate or done 58 | 59 | """ 60 | auth, headers, base_url = jira_auth_and_headers() 61 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}" 62 | 63 | response = requests.request( 64 | "GET", 65 | url, 66 | headers=headers, 67 | auth=auth 68 | ) 69 | issue_json = json.loads(response.text) 70 | status_category = issue_json.get('fields', {}).get('status', {}).get('statusCategory', {}).get('key', None) 71 | return status_category 72 | 73 | 74 | def get_issue_status(this_issue_key): 75 | """Gets all fields for the epic or story queried and returns the status category 76 | 77 | Parameters: 78 | this_issue_key (string): issue identifier eg: D1-1 79 | Returns: 80 | String: status category new, indeterminate or done 81 | 82 | """ 83 | auth, headers, base_url = jira_auth_and_headers() 84 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}" 85 | 86 | response = requests.request( 87 | "GET", 88 | url, 89 | headers=headers, 90 | auth=auth 91 | ) 92 | issue_json = json.loads(response.text) 93 | status_ = issue_json.get('fields', {}).get('status', {}).get('name', None) 94 | return status_ 95 | 96 | 97 | def get_single_project(this_project_id): 98 | """Gets all fields set and vacant for the epic or story queried 99 | 100 | Parameters: 101 | this_project_id (string): project identifier eg: D1 102 | Returns: 103 | Json Object: Object has all project information 104 | 105 | """ 106 | auth, headers, base_url = jira_auth_and_headers() 107 | 108 | # single project 109 | url = f"{base_url}/rest/api/3/project/{this_project_id}" 110 | 111 | response = requests.request( 112 | "GET", 113 | url, 114 | headers=headers, 115 | auth=auth 116 | ) 117 | json_res = json.loads(response.text) 118 | return json_res 119 | 120 | 121 | def get_all_projects(): 122 | """Gets all projects in this jira instance, will return archived projects also 123 | 124 | Returns: 125 | Json Object: describes the projects n this jira instance 126 | 127 | """ 128 | projects_ = [] 129 | auth, headers, base_url = jira_auth_and_headers() 130 | url = f"{base_url}/rest/api/3/project/search" 131 | 132 | while url is not None: 133 | response = requests.request( 134 | "GET", 135 | url, 136 | headers=headers, 137 | auth=auth 138 | ) 139 | json_res = json.loads(response.text) 140 | current_list_of_projects = json_res.get('values') 141 | for proj in current_list_of_projects: 142 | projects_.append(proj) 143 | url = json_res.get("nextPage", None) 144 | 145 | return projects_ 146 | 147 | 148 | def create_epic_link(link_from, link_to, link_type): 149 | """Links epics together in a number of meaningful ways 150 | Parameters: 151 | link_from (string): epic key eg: D1-1 this is the new epic, the child 152 | link_to (string): epic key eg: D1-1 this is the uber epic, the parent 153 | link_type (string): Relates, Blocks, Cloners, Duplicate 154 | Returns: 155 | Json Object: 156 | 157 | """ 158 | auth, headers, base_url = jira_auth_and_headers() 159 | url = f"{base_url}/rest/api/3/issueLink" 160 | 161 | payload = json.dumps({ 162 | "outwardIssue": { 163 | "key": f"{link_from}" 164 | }, 165 | "inwardIssue": { 166 | "key": f"{link_to}" 167 | }, 168 | "type": { 169 | "name": f"{link_type}" 170 | } 171 | }) 172 | 173 | response = requests.request( 174 | "POST", 175 | url, 176 | data=payload, 177 | headers=headers, 178 | auth=auth 179 | ) 180 | text_response = "No link created" 181 | if response.ok: 182 | text_response = f"{link_from} now {link_type} {link_to}" 183 | return text_response 184 | 185 | 186 | def get_issue_assignee(this_issue_id): 187 | """Gets all stories attached to an epic 188 | 189 | Parameters: 190 | this_issue_id (string): issue identifier eg: D1-1 191 | Returns: 192 | Json Object: Object has assignee_name, assignee_email, reporter_name, reporter_email 193 | 194 | """ 195 | auth, headers, base_url = jira_auth_and_headers() 196 | url = f"{base_url}/rest/api/3/issue/{this_issue_id}" 197 | response = requests.request( 198 | "GET", 199 | url, 200 | headers=headers, 201 | auth=auth 202 | ) 203 | 204 | json_res = json.loads(response.text) 205 | assignee_email = json_res['fields'].get('assignee', {}).get('emailAddress', None) 206 | assignee_name = json_res['fields'].get('assignee', {}).get('displayName', None) 207 | assignee_id = json_res['fields'].get('assignee', {}).get('accountId', None) 208 | this_assignee = {"assignee_name": assignee_name, "assignee_email": assignee_email, "assignee_id": assignee_id} 209 | 210 | return this_assignee 211 | 212 | 213 | def get_stories_from_epic(epic): 214 | """Gets all stories attached to an epic 215 | 216 | Parameters: epic (string): Epic identifier eg: SECCOMPPM-93 Returns: Json Object: Key is story key, attributes: 217 | status_name, status_category, priority_name, project_name and project_key 218 | 219 | """ 220 | epic_name = epic 221 | start_at = 0 222 | stories_in_epic = {} 223 | auth, headers, base_url = jira_auth_and_headers() 224 | url = f"{base_url}/rest/agile/1.0/epic/{epic_name}/issue?maxResults=50&start_at={start_at}" 225 | while url is not None: 226 | response = requests.request( 227 | "GET", 228 | url, 229 | headers=headers, 230 | auth=auth 231 | ) 232 | ret_json = json.loads(response.text) 233 | total_expected_results = ret_json.get('total', 0) 234 | for this_issue in ret_json["issues"]: 235 | this_issue_key = this_issue.get("key", None) 236 | stories_in_epic[f'{this_issue_key}'] = {} 237 | stories_in_epic[f'{this_issue_key}']["status_name"] = this_issue.get( 238 | 'fields', {}).get('status', {}).get('name', None) 239 | stories_in_epic[f'{this_issue_key}']["status_category"] = this_issue.get( 240 | 'fields', {}).get('status', {}).get('statusCategory', {}).get('key', None) 241 | stories_in_epic[f'{this_issue_key}']["project_key"] = this_issue.get( 242 | 'fields', {}).get('project', {}).get('key', None) 243 | stories_in_epic[f'{this_issue_key}']["project_name"] = this_issue.get( 244 | 'fields', {}).get('project', {}).get('name', None) 245 | stories_in_epic[f'{this_issue_key}']["priority_name"] = this_issue.get( 246 | 'fields', {}).get('priority', {}).get('name', None) 247 | if len(stories_in_epic) != total_expected_results: 248 | start_at = start_at + 50 249 | url = f"{base_url}/rest/agile/1.0/epic/{epic_name}/issue?maxResults=50&start_at={start_at}" 250 | else: 251 | url = None 252 | 253 | return stories_in_epic 254 | 255 | 256 | def add_comment_to_story(this_issue_key, comment): 257 | auth, headers, base_url = jira_auth_and_headers() 258 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}/comment" 259 | comment_template = {'body': {}} 260 | comment_template['body']['type'] = "doc" 261 | comment_template['body']['version'] = 1 262 | comment_template['body']['content'] = [] 263 | content_parent = {"type": "paragraph", "content": []} 264 | content_child = {"text": f"{comment}", "type": "text"} 265 | content_parent['content'].append(content_child) 266 | comment_template['body']['content'].append(content_parent) 267 | 268 | payload = json.dumps(comment_template) 269 | 270 | response = requests.request( 271 | "POST", 272 | url, 273 | data=payload, 274 | headers=headers, 275 | auth=auth 276 | ) 277 | return response 278 | 279 | 280 | def add_fancy_comment_to_story(this_issue_key, comment_doc): 281 | auth, headers, base_url = jira_auth_and_headers() 282 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}/comment" 283 | comment_template = {'body': comment_doc} 284 | payload = json.dumps(comment_template) 285 | 286 | response = requests.request( 287 | "POST", 288 | url, 289 | data=payload, 290 | headers=headers, 291 | auth=auth 292 | ) 293 | return response 294 | 295 | 296 | def get_issue_types(): 297 | """Gets all issue types in this jira instance 298 | 299 | Returns: 300 | Json Object: describes the available issue types 301 | 302 | """ 303 | auth, headers, base_url = jira_auth_and_headers() 304 | url = f"{base_url}/rest/api/3/issuetype" 305 | 306 | response = requests.request( 307 | "GET", 308 | url, 309 | headers=headers, 310 | auth=auth 311 | ) 312 | text_contents = json.loads(response.text) 313 | return text_contents 314 | 315 | 316 | def get_priority_types(): 317 | """Gets all priority types in this jira instance 318 | 319 | Returns: 320 | Json Object: describes the available priority types 321 | 322 | """ 323 | auth, headers, base_url = jira_auth_and_headers() 324 | url = f"{base_url}/rest/api/3/priority" 325 | 326 | response = requests.request( 327 | "GET", 328 | url, 329 | headers=headers, 330 | auth=auth 331 | ) 332 | text_contents = json.loads(response.text) 333 | return text_contents 334 | 335 | 336 | def get_all_epic_link_types(): 337 | """Gets all link types in this jira instance 338 | 339 | Returns: 340 | Json Object: describes the available epic linking adjectives 341 | 342 | """ 343 | auth, headers, base_url = jira_auth_and_headers() 344 | url = f"{base_url}/rest/api/3/issueLinkType" 345 | 346 | response = requests.request( 347 | "GET", 348 | url, 349 | headers=headers, 350 | auth=auth 351 | ) 352 | json_res = json.loads(response.text) 353 | epic_link_types = json_res.get('issueLinkTypes') 354 | 355 | return epic_link_types 356 | 357 | 358 | def get_transitions(issue_key_): 359 | """Gets all link types in this jira instance 360 | 361 | Returns: 362 | Json Object: describes the available epic linking adjectives 363 | 364 | """ 365 | auth, headers, base_url = jira_auth_and_headers() 366 | url = f"{base_url}/rest/api/3/issue/{issue_key_}/transitions" 367 | 368 | response = requests.request( 369 | "GET", 370 | url, 371 | headers=headers, 372 | auth=auth 373 | ) 374 | json_res = json.loads(response.text) 375 | # epic_link_types = json_res.get('issueLinkTypes') 376 | 377 | return json_res 378 | 379 | 380 | def get_comments(issue_key_): 381 | """Gets all comments in this issue 382 | 383 | Returns: 384 | Json Object: returns all comments in json in Jira document format 385 | 386 | """ 387 | auth, headers, base_url = jira_auth_and_headers() 388 | url = f"{base_url}/rest/api/3/issue/{issue_key_}/comment" 389 | 390 | response = requests.request( 391 | "GET", 392 | url, 393 | headers=headers, 394 | auth=auth 395 | ) 396 | json_res = json.loads(response.text) 397 | 398 | return json_res 399 | 400 | 401 | def transition_issue(issue_key_, stage_id): 402 | """Transition issue to defined state 403 | Parameters: 404 | issue_key_ (string): issue identifier eg: D1-1 405 | stage_id (string): The integer id of the desired state of the issue (may be gathered from get_transitions) 406 | Returns: 407 | String: Response code, eg. 204 408 | 409 | """ 410 | auth, headers, base_url = jira_auth_and_headers() 411 | url = f"{base_url}/rest/api/3/issue/{issue_key_}/transitions" 412 | payload = json.dumps({ 413 | "transition": { 414 | "id": f"{stage_id}" 415 | }, 416 | }) 417 | response = requests.request( 418 | "POST", 419 | url, 420 | data=payload, 421 | headers=headers, 422 | auth=auth 423 | ) 424 | status = response.status_code 425 | 426 | return f"response: {status}" 427 | 428 | 429 | def get_all_request_types(s_desk_issue_key): 430 | """Gets all comments in this issue 431 | 432 | Returns: 433 | Json Object: returns all comments in json in Jira document format 434 | 435 | """ 436 | auth, headers, base_url = jira_auth_and_headers() 437 | url = f"{base_url}rest/servicedeskapi/requesttype" 438 | 439 | response = requests.request( 440 | "GET", 441 | url, 442 | headers=headers, 443 | auth=auth 444 | ) 445 | json_res = json.loads(response.text) 446 | # epic_link_types = json_res.get('issueLinkTypes') 447 | 448 | return json_res 449 | 450 | 451 | if __name__ == "__main__": 452 | issue_key = "DR-49" 453 | issue = get_issue(issue_key) 454 | print(json.dumps(issue, indent=4)) 455 | 456 | project_key = "D1" 457 | project = get_single_project(project_key) 458 | print(json.dumps(project, indent=4)) 459 | 460 | projects = get_all_projects() 461 | print(json.dumps(projects, indent=4)) 462 | 463 | # First epic key is the new one you create, the second id the one you are linking to 464 | # The third input is the type of link - get_issue_link_types.py is in the repo 465 | link_res = create_epic_link("D1-7", "D1-23", "Relates") 466 | print(link_res) 467 | 468 | get_emails = get_issue_assignee('D1-5') 469 | print(json.dumps(get_emails, indent=4)) 470 | 471 | epic_name = "D1-7" 472 | issues_in_epic = get_stories_from_epic(epic_name) 473 | print(json.dumps(issues_in_epic, indent=4)) 474 | 475 | story_id = "D1-7" 476 | comment_text = "I made it" 477 | res = add_comment_to_story(story_id, comment_text) 478 | print(res) 479 | 480 | story_id = "D1-7" 481 | # Build fancy comments in the same way as fancy descriptions here - 482 | # https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ 483 | fancy_comment_doc = { 484 | "version": 1, 485 | "type": "doc", 486 | "content": [ 487 | { 488 | "type": "paragraph", 489 | "content": [ 490 | { 491 | "type": "text", 492 | "text": "this is " 493 | } 494 | ] 495 | }, 496 | { 497 | "type": "paragraph", 498 | "content": [ 499 | { 500 | "type": "text", 501 | "text": "some text" 502 | } 503 | ] 504 | }, 505 | { 506 | "type": "paragraph", 507 | "content": [ 508 | { 509 | "type": "text", 510 | "text": "and I will tag someone " 511 | }, 512 | { 513 | "type": "mention", 514 | "attrs": { 515 | "id": "557058:e747a920-b560-47ee-82e3-94ffe7a59a1b", 516 | "text": "@DR", 517 | "accessLevel": "" 518 | } 519 | }, 520 | { 521 | "type": "text", 522 | "text": " " 523 | } 524 | ] 525 | } 526 | ] 527 | } 528 | res = add_fancy_comment_to_story(story_id, fancy_comment_doc) 529 | print(res) 530 | 531 | issue_types = get_issue_types() 532 | print(json.dumps(issue_types, indent=4)) 533 | 534 | priorities = get_priority_types() 535 | print(json.dumps(priorities, indent=4)) 536 | 537 | issue_links = get_all_epic_link_types() 538 | print(json.dumps(issue_links, indent=4)) 539 | 540 | comments_in_issue = get_comments(story_id) 541 | print(json.dumps(comments_in_issue, indent=4)) 542 | 543 | transitions = get_transitions(issue_key) 544 | print(json.dumps(transitions, indent=4)) 545 | 546 | transition_this_issue = transition_issue(issue_key, "31") 547 | print(transition_this_issue) 548 | 549 | story_id = "D1-7" 550 | issue_status_category = get_issue_status_category(story_id) 551 | 552 | story_id = "D1-7" 553 | issue_status = get_issue_status(story_id) 554 | --------------------------------------------------------------------------------