# gwspace :)
A Python library for interacting with Google Workspace APIs. Created specifically for building AI Agents and automation workflows.

## WHY use gwspace?
Working with Google Workspace APIs directly can be complex and time-consuming. The official documentation often requires navigating multiple endpoints, scopes, and OAuth flows, which can be hectic and overwhelming.

gwspace simplifies this by providing easy-to-use functions to access Gmail, Calendar, Drive, Tasks, Slides, Meet, and other Google services. Whether you want to build AI agents that interact with Google Workspace or automate everyday tasks, gwspace handles the heavy lifting for you, so you can focus on building, not wrestling with documentation.

Have a good time building:)

---

To use these Google Services, you need to download a `credentials.json` file from the Google Cloud Console.  

## Steps to Download `credentials.json` 

### 1. Open Google Cloud Console
[https://console.cloud.google.com/](https://console.cloud.google.com/)

### 2. Select (or Create) a Project
- Click the **project dropdown** (top-left).  
- Choose your existing project **or** create a new one.  

### 3. Enable Required APIs
1. In the left sidebar, go to **APIs & Services > Library**.  
2. Enable the APIs:  
   - Google Calendar API  
   - Gmail API  
   - Google Tasks API  
   - Google Meet API (via Google Workspace SDK if needed)  
   - Task
   - Drive
   - Slides

### 4. Configure OAuth Consent Screen
1. Go to **APIs & Services > OAuth consent screen**.  
2. Select **External** 
3. Fill in the required fields:  
   - App name  
   - User support email  
   - Developer contact email  
4. Click **Save**.  

### 5. Create Credentials
1. Go to **APIs & Services > Credentials**.  
2. Click **Create Credentials > OAuth client ID**.  
3. Choose **Desktop App** (for local testing).  
4. Click **Create**.  

### 6. Download `credentials.json` (It might be named as client_....)
- First of all rename the downloaded file to credentials.json. 
- After creating credentials, click the **download icon**.  
- Rename the file to **`credentials.json`**.  
- Place it in your project directory.

### 7. Adding `credentials.json` path in .env:
- Create .env file if you have not created it yet for your project.
- Add the path to your `credentials.json` file as the value of the `GOOGLE_CREDENTIALS_PATH` environment variable in your `.env` file.

Now you are ready to go, just remember that for the first when you will execute your program that uses
any of function from this library it will ask you to Sign in to your Google Account from where you downloaded
the credentials.json. And it will again ask you to allow access for the enabled services; just allow all and It
will create a token.json file in your root directory.

That's it :)

---

## Developer Guide
### Calendar:

#### `get_events_between`
Gets events from Google Calendar between the given start and end datetime.
    Takes Start time and End time in ISO Format and will return the all events if any in that range.

    Args:
    start_datetime: Start datetime in ISO format (e.g., '2025-04-19T10:00:00Z')
    end_datetime: End datetime in ISO format (e.g., '2025-04-19T18:00:00Z')

    Returns:
        List: List of dictionaries containing events between start_datetime and end_datetime.

    Raises:
        Exception: For errors while getting events between start_datetime and end_datetime.

    Example:
        ```python
            def test_get_events_between():
                try:
                    events = get_events_between(
                        start_datetime="2025-09-01T00:00:00Z",
                        end_datetime="2025-09-30T11:59:59Z"
                    )
                    assert isinstance(events, List)
                    return f'Test case passed: {events}'
                except Exception as e:
                    return f'Error retrieving events: {e}'
        ```

#### `create_event`
Creates an event in the Google Calendar if there is no event in that time slot.
    If there will be an existing event in that start and end time slot; It will not create another event and will return.
    Start Time, End Time, Summary is must; Description and Location are optional fields.

    Args:
    start_datetime: Start datetime in ISO format (e.g., '2025-04-19T10:00:00Z')
    end_datetime: End datetime in ISO format (e.g., '2025-04-19T12:00:00Z')
    summary: Summary or title of the event; what that event is about. It will be shown as title in the Google Calendar.
    description: Description of the event. It is the Optional field.
    location: Location of the Event. It is also an optional field.

    Returns:
        Dict: Dictionary containing events created.

    Raises:
        Exception: For errors while creating the event.
    
    Example:
    ```python
            def test_create_event():
                try:
                    event = create_event(
                        start_datetime="2025-09-16T10:00:00Z",
                        end_datetime="2025-09-16T12:00:00Z",
                        summary="Test Event",
                        description="This is a test event created for unit testing.",
                        location="Google Meet"
                    )
                    assert event is not None
                    return f'Test case passed: {event}'
                except Exception as e:
                    return f'Error creating event: {e}'
        ```

#### `delete_event`
Delete the event between the mentioned time if there is an event.

    Args:
    start_datetime: Start datetime in ISO format (e.g., '2025-04-19T10:00:00Z')
    end_datetime: End datetime in ISO format (e.g., '2025-04-19T18:00:00Z')

    Returns:
        Str: Confirmation of the deletion.

    Raises:
        Exception: For errors to delete the event.

    Example:
        ```python
            def test_delete_event():
                try:
                    deleted_event = delete_event(
                        start_datetime="2025-09-16T10:00:00Z",
                        end_datetime="2025-09-16T12:00:00Z")
                    return f'Test case passed: {deleted_event}'
                except Exception as e:
                    return f'Error retrieving events: {e}'
        ```

### Classroom:

#### `create_google_classroom`
Create a new note in Google Keep.

    Args:
        owner_id (str): The owner of the classroom. Works fine when passed "me".
        classroom_name (str): The name of the Classroom.
        subject (str, optional): The subject of the Classroom.
        description (str, optional): The description of the Google Classroom.
        section (str, optional): The section of the Classroom. Defaults to None.
        room (str, optional): The room of the Classroom. Defaults to None.

    Returns:
        dict: Confirmation of note creation and note metadata. The id that is returned in the response is
        important field as all other functions need course_id.
    
    Example:
        ```python
        def test_create_classroom():
            try:
                classroom = create_google_classroom(
                    owner_id= "me",
                    classroom_name= 'Test',
                    subject= 'Test Subject',
                    description= 'This is a test note created for unit testing.',
                    section= 'A',
                    room= '101'
                )
                assert classroom is not None
                return f'Test case passed: {classroom}'
            except Exception as e:
                return f'Error creating classroom: {e}'
        ```

#### `get_classroom_details`
To get the details about the classroom using the course id that was returned when creating the classroom.
    It will give you details like:
        - Name
        - Section
        - Description
        - Enrollment code
        and many other values.
    Args:
        course_id (str): The ID of the Classroom that you received when creating the classroom.
        
    Returns:
        dict: Details of the classroom.
    
    Example:
        ```python
        def test_get_classroom_details():
            try:
                classroom = get_classroom_details(
                    course_id= "818379112875",
                )
                assert classroom is not None
                return f'Test case passed: {classroom}'
            except Exception as e:
                return f'Error creating invite: {e}'
        ```

#### `invite_user_to_classroom`
To add the user to the classroom.
    It will firstly check if that student or teacher is already enrolled if not only then it will send the invite.

    Args:
        course_id (str): The ID of the Classroom that you received when creating the classroom.
        user_email (str): The email address of the user to invite.
        role (str, optional): The role of the user. User can be student, teacher, or admin. Defaults to 'student'.

    Returns:
        dict: Confirmation of user creation and user metadata.
    
    Example:
        ```python
        def test_invite_user_to_classroom():
            try:
                invite = invite_user_to_classroom(
                    course_id= "818379112875",
                    user_email= 'dsaworld33@gmail.com',
                    role= 'teacher',
                )
                assert invite is not None
                return f'Test case passed: {invite}'
            except Exception as e:
                return f'Error creating invite: {e}'
        ```

#### `create_assignment`
To create a new coursework assignment.

    Args:
        course_id (str): The ID of the course.
        title (str): The title of the coursework.
        description (str): The description of the coursework.
        materials (Optional[List]): The materials of the coursework. It will be a list of nested dictionaries. Like this:
            [
                {"link": {"url": "http://example.com"}},
                {"link": {"url": "http://example.com"}},
            ]
        
    Example:
        ```python
        def test_create_assignment():
            try:
                assignment = create_assignment(
                    course_id= "818379112875",
                    title= 'Test Assignment',
                    description= 'A test assignment created for unit testing.',
                    materials= [
                        {"link": {"url": "https://docs.google.com/document/d/1IVcw5OxVJstVUlCKVy4Ap4TOmsn75gjGejt_9TlkkZ0/edit?usp=drive_link"}}
                    ]
                )
                assert assignment is not None
                return f'Test case passed: {assignment}'
            except Exception as e:
                return f'Error creating assignment: {e}'
        ```

#### `add_teacher`
Function for adding a teacher to a classroom. Only admin role user can add the teacher directly.
    The difference between invite_user_to_classroom is that invite sends an invitation email and the
    role can be selected dynamically. (Means you can send invitation of student, teacher, admin from
    that single function.)
    But in this you can only add teacher, and it will be directly added without any invite.

    One thing to note here is that this function might give error if you are using normal gmail account,
    to add users you should have a domain account.

    Args:
        course_id (str): The ID of the course.
        teachers_email (str): The email of the teacher to add the student to.

    Returns:
        dict: Confirmation of student creation and student metadata.
    
    Example:
        ```python
        def test_add_teacher():
            try:
                teacher= add_teacher(
                    course_id= "818379112875",
                    teachers_email= 'jmm.usmanyaqoob@gmail.com',
                )
                assert teacher is not None
                return f'Test case passed: {teacher}'
            except Exception as e:
                return f'Error adding teacher: {e}'
        ```

#### `add_student`
Function for adding a student to a classroom. Only admin and teacher role user can add the student directly.

    One thing to note here is that this function might give error if you are using normal gmail account,
    to add users you should have a domain account.

    Args:
        course_id (str): The ID of the course.
        student_email (str): The email of the user to add the student to.

    Returns:
        dict: Confirmation of student creation and student metadata.
    
    Example:
        ```python
        def test_add_student():
            try:
                student= add_student(
                    course_id= "818379112875",
                    student_email= 'jmm.usmanyaqoob@gmail.com',
                )
                assert student is not None
                return f'Test case passed: {student}'
            except Exception as e:
                return f'Error adding student: {e}'
        ```

#### `join_classroom`
Function for joining the classroom as student. You can directly join the classroom as student only.

    One thing to note here is that this function might give error if you are using normal gmail account,
    to add users you should have a domain account.

    Args:
        course_id (str): The ID of the course.
        student_email (str): The email of the user to add the student to.

    Returns:
        dict: Confirmation of student joining.
    
    Example:
        ```python
        def test_join_classroom():
            try:
                join= join_classroom(
                    course_id= "818379112875",
                    student_email= 'jmm.usmanyaqoob@gmail.com'
                )
                assert join is not None
                return f'Test case passed: {join}'
            except Exception as e:
                return f'Error joining classroom: {e}'
        ```

#### `get_students`
To get the list of the students that are enrolled in the Google Classroom.
    It will return a list of dictionaries with all details like email, name, id of the students.

    Args:
        course_id (str): The ID of the course.

    Returns:
        list: List of the students that are enrolled in the Google Classroom.
    
    Example:
        ```python
        def test_get_students():
            try:
                students= get_students(
                    course_id= "818379112875"
                )
                assert students is not None
                return f'Test case passed: {students}'
            except Exception as e:
                return f'Error getting students list: {e}'
        ```

#### `get_teachers`
To get the list of the teachers that are enrolled in the Google Classroom.
    It will return a list of dictionaries with all details like email, name, id of the teachers.

    Args:
        course_id (str): The ID of the course.

    Returns:
        list: List of the students that are enrolled in the Google Classroom.
    
    Example:
        ```python
        def test_get_teachers():
            try:
                teachers= get_teachers(
                    course_id= "818379112875"
                )
                assert teachers is not None
                return f'Test case passed: {teachers}'
            except Exception as e:
                return f'Error getting teachers list: {e}'
        ```

#### `delete_student`
To delete the student in the Google Classroom. This function will firstly check if
    student that is to be deleted is even enrolled in the Google Classroom or not.

    Args:
        course_id (str): The ID of the course.
        student_email (str): The email of the student to delete.

    Returns:
        dict: Confirmation of classroom deletion.
    
    Example:
        ```python
        def test_delete_student():
            try:
                deletion= delete_student(
                    course_id= "818379112875",
                    student_email='dsaworld33@gmail.com'
                )
                assert deletion is not None
                return f'Test case passed: {deletion}'
            except Exception as e:
                return f'Error deletion of student: {e}'
        ```

#### `delete_teacher`
To delete the teacher in the Google Classroom. This function will firstly check if
    teacher that is to be deleted is even enrolled in the Google Classroom or not.

    Args:
        course_id (str): The ID of the course.
        teacher_email (str): The email of the student to delete.

    Returns:
        dict: Confirmation of classroom deletion.
    
    Example:
        ```python
        def test_delete_teacher():
            try:
                deletion= delete_teacher(
                    course_id= "818379112875",
                    teacher_email='dsaworld33@gmail.com'
                )
                assert deletion is not None
                return f'Test case passed: {deletion}'
            except Exception as e:
                return f'Error deletion of teacher: {e}'
        ```

#### `list_classrooms`
This function will list all the classroom you are part of. It will return the list of dictionaries with
    all the details about the classrooms that you are enrolled in.

    Returns:
        List of the classroom you are part of.
    
    Example:
        ```python
        def test_list_classrooms():
            try:
                classrooms= list_classrooms()
                return f'Test case passed: {classrooms}'
            except Exception as e:
                return f'Error getting the classrooms: {e}'
        ```

#### `delete_classroom`
To delete the Google Classroom using the classroom or course id. This function will firstly check if
    you are even a part of that classroom or not. I think only admin and teacher can delete the classroom (not sure about this).

    One more thing that you cannot delete the course with status as ACTIVE so we will make the status ARCHIVED and then delete it.

    Args:
        course_id (str): The ID of the course.

    Returns:
        dict: Confirmation of classroom deletion.
    
    Example:
        ```python
        def test_delete_classroom():
            try:
                deletion= delete_classroom(
                    course_id= "818379112875")
                assert deletion is not None
                return f'Test case passed: {deletion}'
            except Exception as e:
                return f'Error deletion of classroom: {e}'
        ```

### Docs:

#### `create_docs`
Creates a Google Docs document that you can use.

    Args:
        doc_title (str): The title of the document.

    Returns:
         dict: Confirmation of the creation and the doc ID.
    
    Example:
        ```python
        def test_create_docs():
            try:
                title= 'Testing'
                docs_creation = create_docs(
                    doc_title= title,
                )
                return f'Test case passed: {docs_creation}'
            except Exception as e:
                return f'Error creating docs: {e}'
        ```

#### `insert_text`
To insert the text into Google Docs document.

    Basically to work with the addition of text in the Google Docs, we have to consider index.
    And we have to properly add text in each tab by mentioning each index.
    So it is just converting the text into list of paragraphs by splitting the
    text on the double line, and then It will add each paragraph to the list.

    So with this technique the paragraphs will be properly added in the doc. But if the function is
    called on the doc that already has the text; It will move the text ahead, and it will add the new given text
    in the start.

    Args:
        doc_id (str): The id of the document in which you want to insert the text.
        text (str): The text to add.
        start (int, optional): The index of the first paragraph to add. Basically purpose of this is that when we add text in the end (in the update_doc function) we reuse this insert function and just give it the last index as start. So by default its value is set to 1 because in this function it will always add the text in the start.

    Returns:
        Confirmation of the addition of the text.
    
    Example:
        ```python
        def test_insert_text():
            try:
                doc_id= '149SxkXIxroJK0zC-Y5NTaWmTFehsSSpeZ8SyFeMwoB4'
                text= '''
                Hello.
                
                My name is Tester.
                
                I am Testing this insertion of text in the google doc.
                '''
                docs_creation = insert_text(
                    doc_id= doc_id,
                    text= text,
                )
                return f'Test case passed: {docs_creation}'
            except Exception as e:
                return f'Error Inserting Text in docs: {e}'

        ```

#### `get_docs_content`
To get the content of the Google Docs document. It just brings the normal text; no style. It does take care of the spaces.

    Args:
        doc_id (str): The id of the document of which you want to get the content.

    Returns:
        str: The content of the document.
    
    Example:
        ```python
        def test_get_docs_content():
            try:
                doc_id = '149SxkXIxroJK0zC-Y5NTaWmTFehsSSpeZ8SyFeMwoB4'
                content = get_docs_content(
                    doc_id=doc_id,)
                return f'Test case passed: {content}'
            except Exception as e:
                return f'Error Getting Text from doc: {e}'
        ```

#### `delete_doc`
To Delete the Google Docs document. It used the drive service to delete the Google Docs document
    because Google Doc Service does not have deletion functionality.

    Args:
        doc_id (str): The id of the document to delete.

    Returns:
        str: The confirmation of the deletion.
    
    Example:
        ```python
        def test_delete_doc():
            try:
                doc_id = '1gec6zFOtrOkweHLbCr9nq8C1ryxlbM5oDRhgYEIa22Q'
                deletion = delete_doc(
                    doc_id=doc_id,)
                return f'Test case passed: {deletion}'
            except Exception as e:
                return f'Error Getting deleting doc: {e}'
        ```

#### `update_doc`
Module to update the document, It is different from insert_text functionality in the way that
    It adds the given text in the end of the document. On the other hand insert_text function
    adds the text in the start of the document regardless if the document is empty or have any
    previous text.

    I did not find any solution for adding text in the end from Google official documentation;
    So this is the custom solution and here is how it tries to add text in the end:
    - Gets the content of the doc.
    - Figure out the last end index where text is present.
    - Just use insert_text function to add the text in the end by giving it where to start from via 'start' parameter.

    Args:
        doc_id (str): The id of the document to update.
        text (str): The text to add.

    Returns:
        str: The Confirmation of the addition of the text.
    
    Example:
        ```python
        def test_update_doc():
            try:
                doc_id = '149SxkXIxroJK0zC-Y5NTaWmTFehsSSpeZ8SyFeMwoB4'
                text = '''
                This is to test update feature ok.
                
                
                I am testing the update feature.
                
                
                I am done testing. 
                '''
                docs_creation = update_doc(
                    doc_id= doc_id,
                    text= text,
                )
                return f'Test case passed: {docs_creation}'
            except Exception as e:
                return f'Error Inserting Text in docs: {e}'
        ```

### Drive:

#### `download_file`
Download a file from Google Drive.
    Supports both binary files and Google Docs editor files. Basically there are separate ways to download the binary files like
    images and other Google Docs files.

    Args:
        file_id (str): The Drive file ID.

    Returns:
        bytes: The file content in bytes, or None if failed.
                It returns the file content in bytes, and you have to create appropriate file and add that content in it.
                That means if you are downloading docs than create a xlsx file and add the content in it.

                Like:
                    with open("output_file.xlsx", "wb") as f:
                        f.write(data)
    
    Example:
        ```python
        def test_download_file():
            try:
                data = download_file(
                    file_id= '126-Qh-8mCCWjdma1D4sdQpfgvEk_kQr6FxrwmnGrDZA'
                )
                if data:
                    with open("output_file.xlsx", "wb") as f:
                        f.write(data)
                return f'Test case passed: {data}'
            except Exception as e:
                return f'Error while Downloading file: {e}'
        ```

#### `delete_file`
To delete the file from the Google Drive.

    Args:
        file_id (str): ID of the file to be deleted.

    Returns:
        str: Confirmation of the deletion of the file from the Google Drive.
    
    Example:
        ```python
        def test_delete_file():
            try:
                data = delete_file(
                    file_id= '126-Qh-8mCCWjdmd1D4sdQpfgvEk_kQr6FxrwmnGrDZA'
                )
                return f'Test case passed: {data}'
            except Exception as e:
                return f'Error while Deleting the file: {e}'

        ```

#### `create_folder`
To create the folder in the Google Drive.

    Args:
        folder_name (str): Name of the folder to be created.

    Returns:
        dict: Dictionary having folder ID. Like: {'id': '1pUwhqaXuvHKQiq3_RGqVrPpAIE7VkLU4'}
    
    Example:
        ```python
        def test_create_folder():
            try:
                insertion = create_folder(
                    folder_name= "Test"
                )
                return f'Test case passed: {insertion}'
            except Exception as e:
                return f'Error while Folder Creation: {e}'
        ```

### Gmail:

#### `send_gmail`
To email someone with your connected Google account.
    Connected account means the one whose credentials.json you are using.

    Args:
    email_to: Gmail of the receiver of the email. It is a must required field.
    email_from: Gmail of the sender of the email; It will always be the one you used to create the credentials.json file.
    email_subject: Subject of the Email to be sent.
    email_content: content of the email to be sent.

    Returns:
        Details of the message sent.

    Raises:
        Exception: For errors to send the email.

    Example:
        ```python
        def test_send_email():
            try:
                send_main = send_gmail(
                    email_to='',
                    email_from='',
                    email_subject='Testing Agent',
                    email_content='Testing Email Content!'
                )
                assert send_main is not None
                return f'Test case passed: {send_main}'
            except Exception as e:
                return f'Error creating emails: {e}'

        ```

#### `get_emails`
Get the given number of latest unread emails from the gmail.
    we will only get Subject, and Sender email because we will be passing this to the LLM.
    For the privacy of a sender try not getting the sender email too.

    -> It will only get your primary emails.

    The limit of specific number of emails is being set because most of
    the people have alot of unread emails that can be a pain point.

    Args:
    num_emails: Number of emails that you want to get.

     Returns:
        List: List of the emails.

    Raises:
        Exception: For errors to get the emails.
    
    Example:
        ```python
        def test_get_emails():
            try:
                num_emails = 10
                emails = get_emails(
                    num_emails=num_emails
                )
                return f'Test case passed: {emails}'
            except Exception as e:
                return f'Error getting emails: {e}'
        ```

### Meet:

#### `create_space`
There is no sync function for creating spaces.
    So this an asynchronous function that creates spaces which is actually google meet link for the meeting.

    Returns:
        dict: Meeting space details.

    Raises:
        Exception: For errors to create space.

    Example:
        ```python
        async def test_create_space():
    try:
        meeting_space=  await create_space()
        return f'Test case passed: {meeting_space}'
    except Exception as e:
        return f'Error Getting Tasks: {e}'

        ```

### Sheets:

#### `create_spreadsheet`
Create a spreadsheet in Google Sheets.

    Args:
        title (str): Title of the spreadsheet.

    Returns:
        dict: Dictionary containing the spreadsheet ID,
            e.g. `{"spreadsheetId": "ID of the spreadsheet"}`.

    Example:
        ```python
        def test_create_sheet():
            try:
                sheet = create_spreadsheet(title='Test')
                print(f'Test case passed: {sheet}')
            except Exception as e:
                print(f'Error creating sheet: {e}')
        ```

#### `read_spreadsheet`
To read the spreadsheet in google sheets.

    Args:
        spreadsheet_id (str): Spreadsheet id
        cells_range (str): Range of the cells - It will decide how many cells will be read (range will be like A1:C2)
        sheet_name (str): As a single spreadsheet can have multiple sheets, this parameter takes the specific
                            name of the sheet to retrieve the data from. If value not provided, It
                            will retrieve from first sheet in the spreadsheet.
    Returns:
        dict: Dictionary with information and Data.
                Like:
                {'range': 'Sheet1!A1:C2', 'majorDimension': 'ROWS', 'values': [['1', '2', '3'], ['4', '5', '6']]}
    Example:
            ```python
        def test_read_spreadsheet():
            try:
                data = read_spreadsheet(
                    spreadsheet_id="1MIzcEON-5G4sBPoPQPMEQeRi22CtTA4AZxNjqwkg-CE",
                    cells_range= "A1:C2",
                    sheet_name= "Sheet1"
                )
                return f'Test case passed: {data}'
            except Exception as e:
                return f'Error retrieving data: {e}'
            ```

#### `insert_data_in_spreadsheet`
To insert the data in the specific sheet of the spreadsheet or by default in the first sheet.

    Args:
        spreadsheet_id (str): Spreadsheet id
        cells_range (str): Range of the cells in which data will be inserted.
        value_input_option (str): It can be either of two values:
                    - RAW: 	The input is not parsed and is inserted as a string. For example, the input "=1+2" places the string, not the formula, "=1+2" in the cell.
                    (Non-string values like booleans or numbers are always handled as RAW.)
                    - USER_ENTERED: The input is parsed exactly as if it were entered into the Sheets UI. For example, "Mar 1 2016" becomes a date, and "=1+2" becomes a formula.
                    Formats can also be inferred, so "$100.15" becomes a number with currency formatting.
        values (list): List of values to be inserted into the spreadsheet.
                        like [[1,2], [3,4]]
        sheet_name (str): As a single spreadsheet can have multiple sheets, this parameter takes the specific sheet name to insert the data into. If sheet_name is not provided it will
                            insert in the first sheet.

    Returns:
        dict: Information about the insertion/update.

                Like:
                    {'spreadsheetId': '1MIzcEON-5G4sBPoPQPMEQeRi22CtTA4AZxNjbwkg-CE', 'updatedRange': 'Sheet1!A3:C4', 'updatedRows': 2, 'updatedColumns': 3, 'updatedCells': 6}

    Example:
            ```python
            def test_insert_data_in_spreadsheet():
                try:
                    insertion = insert_data_in_spreadsheet(
                        spreadsheet_id="126-Qh-8mCCWjdmd1D4sdQpfgvEk_kQr6FxrwmnGrDZA",
                        cells_range= "A3:C4",
                        value_input_option= "USER_ENTERED",
                        values= [[110, 11, 12], [113, 14, 151]],
                        sheet_name= "Sheet1"
                    )
                    return f'Test case passed: {insertion}'
                except Exception as e:
                    return f'Error data insertion: {e}'
        ```

#### `delete_spreadsheet`
Delete a Google Spreadsheet by its ID. It will use delete_file function from the drive to delete the spreadsheet.

    Args:
        spreadsheet_id (str): The ID of the spreadsheet to delete.

    Returns:
        str: Confirmation message if successful.
    
    Example:
        ```python
            def test_delete_spreadsheet():
                try:
                    deletion = delete_spreadsheet(
                        spreadsheet_id="12Osrhvm1NPDH5MqwlvtSiV7nbC016hrei_ehhn4uzMs"
                    )
                    return f'Test case passed: {deletion}'
                except Exception as e:
                    return f'Error while deleting spreadsheet: {e}'
        ```

### Slides:

#### `create_presentation`
To create the empty presentation in the Google Slides.

    Args:
        title (str): The title of the presentation.

    Returns:
        dict: The confirmation of the creation and presentation ID.
    
    Example:
        ```python
        def test_create_presentation():
            try:
                title= 'Testing'
                pptx_creation = create_presentation(
                    title= title,
                )
                return f'Test case passed: {pptx_creation}'
            except Exception as e:
                return f'Error creating presentation: {e}'
        ```

#### `create_slide`
Create a slide in the presentation with specific slide ID.

    The same Slide ID might be useful in inserting the text in that slide.

    Args:
        presentation_id (str): The presentation ID where the slide will be created.
        slide_id (str): The slide ID.
        slide_position (int): The position of the slide in the presentation remember not to give the number greater than slides present.
        slide_type (str): The type of slide if you want to choose a predefined Layout.

            It takes following values:

            - BLANK: Blank layout, with no placeholders.
            - TITLE: Layout with a title and a subtitle.
            - TITLE_AND_BODY: Layout with a title and body.
            - TITLE_ONLY: Layout with only a title.
            - SECTION_HEADER: Layout with a section title.
            - ONE_COLUMN_TEXT: Layout with one title and one body, arranged in a single column.

    Returns:
        dict: The confirmation of the creation and presentation ID.
    
    Example:
        ```python
        def test_create_slide():
            try:
                slide_creation = create_slide(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                    slide_id= 'slide_5',
                    slide_position= 5,
                    slide_type= 'ONE_COLUMN_TEXT'
                )
                return f'Test case passed: {slide_creation}'
            except Exception as e:
                return f'Error creating slide: {e}'
        ```

#### `get_presentation`
To get the presentation with the presentation ID.

    Args:
        presentation_id (str): ID of the presentatiton.
    
    Example:
        ```python
        def test_get_presentation():
            try:
                presentation = get_presentation(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw')
                return f'Test case passed: {presentation}'
            except Exception as e:
                return f'Error getting presentation: {e}'
        ```

#### `add_content_in_blank_slide`
Use this if you have created a BLANK Slide.

    To add content to the specific slide of a specific presentation.
    So basically to add the content in the specific slide you have pass the presentation ID that you received
    when you created the presentation, slideID that you received when you created the slide.
    And we can not simply add the text; We have to create the shape first so every shape will have an ID.

    Args:
        presentation_id (str): The presentation ID.
        slide_id (str): The slide ID where the content will be added.
        slide_title (str): The title of the content in the slide. It is optional parameter as slides having no title box will not receive title text.
        slide_text (str): The text of the content in the slide. It is also a optional parameter as slides having only title will not have body.

    Returns:
        str: The presentation ID.

#### `add_content_in_slide`
This function basically insert the content in the slide's Title and Body.
    It takes Slide title and body text; finds the appropriate placeholders, if present it insert the title
    and body text in the appropriate placeholders.
    This is the main difference between this function and add_content_in_empty_slide that It will insert the title
    and body text if there are placeholders for the title and body on the other hand add_content_in_empty_slide will
    make the text boxes and placeholders to insert the text.

    It will take the slide_id and will insert the title and body text in that specific slide.

    Args:
        presentation_id (str): The presentation ID.
        slide_id (str): The slide ID where the content will be added.
        slide_title (str): The title of the content in the slide. Optional as all slides may not have title.
        slide_subtitle (str): The subtitle of the content in the slide. Optional as all slides may not have subtitle.
        slide_body_text (str): The text of the body in the slide. Optional as all slides may not have body.

    Returns:
        str: The presentation ID.
    
    Example:
        ```python
        def test_add_content():
            try:
                body= '''
                - Hello 1 
                - Hello 2
                - Hello 3
                '''
                content_addition = add_content_in_slide(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                    slide_id= 'slide_1',
                    slide_title= 'Slide Title',
                    slide_subtitle= 'Slide Subtitle',
                    slide_body_text= body
                )
                return f'Test case passed: {content_addition}'
            except Exception as e:
                return f'Error Inserting text to slide: {e}'
        ```

#### `delete_slide`
To delete any slide of any presentation given slide id to be deleted and presentation id in which that slide is.

    Args:
        presentation_id (str): The presentation ID.
        slide_id (str): The slide ID.

    Returns:
        dict: Status and Confirmation message.
    
    Example:
        ```python
        def test_delete_slide():
            try:
                slide_creation = delete_slide(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                    slide_id= 'slide_1',
                )
                return f'Test case passed: {slide_creation}'
            except Exception as e:
                return f'Error Deleting slide: {e}'
        ```

#### `delete_presentation`
To delete presentation given presentation id of the presentation to be deleted.
    It will move the presentation to Trash, and it can be recovered from it.

    Args:
        presentation_id (str): The presentation ID.

    Returns:
        dict: Status and Confirmation message.
    
    Example:
        ```python
        def test_delete_presentation():
            try:
                slide_creation = delete_presentation(
                    presentation_id= '1mFTFIv-Y3CtwJ6_i0b7SxWiHdqaosNH-jo7mH3Ycbyw',
                )
                return f'Test case passed: {slide_creation}'
            except Exception as e:
                return f'Error Deleting Presentation: {e}'
        ```

### Tasks:

#### `get_tasks_list_names_and_ids`
Module to get list of tasks names and ids.

    Returns:
        list: List of task names and ids.

    Raises:
        Exception: For errors to get the list.
    
    Example:
        ```python
        def test_get_tasks_list_names_and_ids():
            try:
                lists = get_tasks_list_names_and_ids()
                return f'Test case passed: {lists}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```

#### `get_pending_tasks_of_specific_list`
Module to get pending tasks of specific list.

    Args:
        list_name (str): Name of list.

    Returns:
        list: List of pending tasks.

    Raises:
        Exception: If there is no list named as the mentioned in the parameters.
        Exception: For errors to get the pending tasks.
    
    Example:
        ```python
        def test_get_pending_tasks_of_specific_list():
            try:
                tasks = get_pending_tasks_of_specific_list(
                    list_name='Monday'
                )
                return f'Test case passed: {tasks}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```

#### `create_new_list`
Module to create new list.

    Args:
        list_name (str): Name of list.

    Returns:
        dict: New list.

    Raises:
        Exception: If there is already an existing list with that name.
        Exception: For errors to create the list.
    
    Example:
        ```python
        def test_create_new_list():
            try:
                create_list = create_new_list(
                    list_name='Testing.'
                )
                return f'Test case passed: {create_list}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```

#### `add_task_to_list`
Module to add task to list.

    Args:
        task_name (str): Name of task.
        list_name (str): Name of list.
        due_date (Optional[str], optional): Due date of task.
        task_details (Optional[str], optional): Task details.

    Returns:
        dict: Task details.

    Raises:
        Exception: If there is already an existing task with that name.
        Exception: For errors to add the task.
        Exception: If the list that was mentioned does not exist.
    
    Example:
        ```python
        def test_add_task_to_list():
            try:
                create_list = add_task_to_list(
                    list_name='Testing.',
                    task_name='Testing task',
                    task_details='content testing',
                    due_date=datetime.datetime.now(datetime.UTC).isoformat()
                )
                return f'Test case passed: {create_list}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```

#### `mark_task_complete`
Module to mark task as complete in the specified list.

    Args:
        task_name (str): Name of task that you want to mark as complete.
        list_name (str): Name of list that task is in.

    Returns:
        str: Task Mark as complete Confirmation.

    Raises:
        Exception: If there is no list named as mentioned list.
        Exception: If task that was mentioned does not exist.
        Exception: For errors to mark the task as completed.
    
    Example:
        ```python
        def test_mark_task_complete():
            try:
                list_name = 'Monday'
                task_name = 'Push to git'
                mark_as_complete = mark_task_complete(
                    task_name=task_name,
                    list_name=list_name
                )
                return f'Test case passed: {mark_as_complete}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```

#### `delete_list`
Module to delete an entire list.

    Args:
        list_name (str): Name of list of to be deleted.

    Returns:
        str: Deleted list Confirmation.

    Raises:
        Exception: If there is no list named as the mentioned in the parameters.
        Exception: For errors to delete the list.
    
    Example:
        ```python
        def test_delete_list():
            try:
                list_name = 'Testing.'
                deletion = delete_list(
                    list_name=list_name
                )
                return f'Test case passed: {deletion}'
            except Exception as e:
                return f'Error Getting Tasks: {e}'
        ```
---




   