universal-mcp-applications 0.1.22__py3-none-any.whl → 0.1.39rc8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of universal-mcp-applications might be problematic. Click here for more details.
- universal_mcp/applications/ahrefs/app.py +92 -238
- universal_mcp/applications/airtable/app.py +23 -122
- universal_mcp/applications/apollo/app.py +122 -475
- universal_mcp/applications/asana/app.py +605 -1755
- universal_mcp/applications/aws_s3/app.py +36 -103
- universal_mcp/applications/bill/app.py +644 -2055
- universal_mcp/applications/box/app.py +1246 -4159
- universal_mcp/applications/braze/app.py +410 -1476
- universal_mcp/applications/browser_use/README.md +15 -1
- universal_mcp/applications/browser_use/__init__.py +1 -0
- universal_mcp/applications/browser_use/app.py +94 -37
- universal_mcp/applications/cal_com_v2/app.py +207 -625
- universal_mcp/applications/calendly/app.py +103 -242
- universal_mcp/applications/canva/app.py +75 -140
- universal_mcp/applications/clickup/app.py +331 -798
- universal_mcp/applications/coda/app.py +240 -520
- universal_mcp/applications/confluence/app.py +497 -1285
- universal_mcp/applications/contentful/app.py +36 -151
- universal_mcp/applications/crustdata/app.py +42 -121
- universal_mcp/applications/dialpad/app.py +451 -924
- universal_mcp/applications/digitalocean/app.py +2071 -6082
- universal_mcp/applications/domain_checker/app.py +3 -54
- universal_mcp/applications/e2b/app.py +14 -64
- universal_mcp/applications/elevenlabs/app.py +9 -47
- universal_mcp/applications/exa/README.md +8 -4
- universal_mcp/applications/exa/app.py +408 -186
- universal_mcp/applications/falai/app.py +24 -101
- universal_mcp/applications/figma/app.py +91 -175
- universal_mcp/applications/file_system/app.py +2 -13
- universal_mcp/applications/firecrawl/app.py +186 -163
- universal_mcp/applications/fireflies/app.py +59 -281
- universal_mcp/applications/fpl/app.py +92 -529
- universal_mcp/applications/fpl/utils/fixtures.py +15 -49
- universal_mcp/applications/fpl/utils/helper.py +25 -89
- universal_mcp/applications/fpl/utils/league_utils.py +20 -64
- universal_mcp/applications/ghost_content/app.py +66 -175
- universal_mcp/applications/github/app.py +28 -65
- universal_mcp/applications/gong/app.py +140 -300
- universal_mcp/applications/google_calendar/app.py +26 -78
- universal_mcp/applications/google_docs/app.py +324 -354
- universal_mcp/applications/google_drive/app.py +194 -793
- universal_mcp/applications/google_gemini/app.py +29 -64
- universal_mcp/applications/google_mail/README.md +1 -0
- universal_mcp/applications/google_mail/app.py +93 -214
- universal_mcp/applications/google_searchconsole/app.py +25 -58
- universal_mcp/applications/google_sheet/app.py +174 -623
- universal_mcp/applications/google_sheet/helper.py +26 -53
- universal_mcp/applications/hashnode/app.py +57 -269
- universal_mcp/applications/heygen/app.py +77 -155
- universal_mcp/applications/http_tools/app.py +10 -32
- universal_mcp/applications/hubspot/README.md +1 -1
- universal_mcp/applications/hubspot/app.py +7508 -99
- universal_mcp/applications/jira/app.py +2419 -8334
- universal_mcp/applications/klaviyo/app.py +737 -1619
- universal_mcp/applications/linkedin/README.md +23 -4
- universal_mcp/applications/linkedin/app.py +861 -155
- universal_mcp/applications/mailchimp/app.py +696 -1851
- universal_mcp/applications/markitdown/app.py +8 -20
- universal_mcp/applications/miro/app.py +333 -815
- universal_mcp/applications/ms_teams/app.py +85 -207
- universal_mcp/applications/neon/app.py +144 -250
- universal_mcp/applications/notion/app.py +36 -51
- universal_mcp/applications/onedrive/README.md +24 -0
- universal_mcp/applications/onedrive/__init__.py +1 -0
- universal_mcp/applications/onedrive/app.py +316 -0
- universal_mcp/applications/openai/app.py +42 -165
- universal_mcp/applications/outlook/README.md +22 -9
- universal_mcp/applications/outlook/app.py +606 -262
- universal_mcp/applications/perplexity/README.md +2 -1
- universal_mcp/applications/perplexity/app.py +162 -20
- universal_mcp/applications/pipedrive/app.py +1021 -3331
- universal_mcp/applications/posthog/app.py +272 -541
- universal_mcp/applications/reddit/app.py +88 -204
- universal_mcp/applications/resend/app.py +41 -107
- universal_mcp/applications/retell/app.py +23 -50
- universal_mcp/applications/rocketlane/app.py +250 -963
- universal_mcp/applications/scraper/README.md +7 -4
- universal_mcp/applications/scraper/app.py +245 -283
- universal_mcp/applications/semanticscholar/app.py +36 -78
- universal_mcp/applications/semrush/app.py +43 -77
- universal_mcp/applications/sendgrid/app.py +826 -1576
- universal_mcp/applications/sentry/app.py +444 -1079
- universal_mcp/applications/serpapi/app.py +40 -143
- universal_mcp/applications/sharepoint/README.md +16 -14
- universal_mcp/applications/sharepoint/app.py +245 -154
- universal_mcp/applications/shopify/app.py +1743 -4479
- universal_mcp/applications/shortcut/app.py +272 -534
- universal_mcp/applications/slack/app.py +58 -109
- universal_mcp/applications/spotify/app.py +206 -405
- universal_mcp/applications/supabase/app.py +174 -283
- universal_mcp/applications/tavily/app.py +2 -2
- universal_mcp/applications/trello/app.py +853 -2816
- universal_mcp/applications/twilio/app.py +14 -50
- universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
- universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
- universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
- universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
- universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
- universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
- universal_mcp/applications/whatsapp/app.py +35 -186
- universal_mcp/applications/whatsapp/audio.py +2 -6
- universal_mcp/applications/whatsapp/whatsapp.py +17 -51
- universal_mcp/applications/whatsapp_business/app.py +86 -299
- universal_mcp/applications/wrike/app.py +80 -153
- universal_mcp/applications/yahoo_finance/app.py +19 -65
- universal_mcp/applications/youtube/app.py +120 -306
- universal_mcp/applications/zenquotes/app.py +4 -4
- {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/METADATA +4 -2
- {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/RECORD +113 -117
- {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/WHEEL +1 -1
- universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
- universal_mcp/applications/hubspot/api_segments/api_segment_base.py +0 -54
- universal_mcp/applications/hubspot/api_segments/crm_api.py +0 -7337
- universal_mcp/applications/hubspot/api_segments/marketing_api.py +0 -1467
- universal_mcp/applications/unipile/README.md +0 -28
- universal_mcp/applications/unipile/__init__.py +0 -1
- universal_mcp/applications/unipile/app.py +0 -1077
- {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
-
|
|
3
2
|
from universal_mcp.applications.application import APIApplication
|
|
4
3
|
from universal_mcp.integrations import Integration
|
|
5
4
|
|
|
@@ -9,42 +8,44 @@ class GoogleDocsApp(APIApplication):
|
|
|
9
8
|
super().__init__(name="google_docs", integration=integration)
|
|
10
9
|
self.base_api_url = "https://docs.googleapis.com/v1/documents"
|
|
11
10
|
|
|
12
|
-
def create_document(self, title: str) -> dict[str, Any]:
|
|
11
|
+
async def create_document(self, title: str) -> dict[str, Any]:
|
|
13
12
|
"""
|
|
14
|
-
Creates a blank Google Document with a specified title
|
|
13
|
+
Creates a blank Google Document with a specified title by sending a POST request to the Google Docs API. The function returns a dictionary containing the new document's metadata, including the unique document ID required by other functions for subsequent modifications or retrieval. Note that you need to call other google_docs functions (e.g. `google_docs__insert_text`) to actually add content after creating the document.
|
|
15
14
|
|
|
16
15
|
Args:
|
|
17
|
-
title: The title for the new Google Document to be created
|
|
16
|
+
title: The title for the new Google Document to be created.
|
|
18
17
|
|
|
19
18
|
Returns:
|
|
20
|
-
A dictionary containing the Google Docs API
|
|
19
|
+
A dictionary containing the response from the Google Docs API with document details and metadata.
|
|
21
20
|
|
|
22
21
|
Raises:
|
|
23
|
-
HTTPError: If the API request fails due to network issues, authentication errors, or invalid parameters
|
|
24
|
-
RequestException: If there are connection errors or timeout issues during the API request
|
|
22
|
+
HTTPError: If the API request fails due to network issues, authentication errors, or invalid parameters.
|
|
23
|
+
RequestException: If there are connection errors or timeout issues during the API request.
|
|
25
24
|
|
|
26
25
|
Tags:
|
|
27
26
|
create, document, api, important, google-docs, http
|
|
28
27
|
"""
|
|
29
28
|
url = self.base_api_url
|
|
30
29
|
document_data = {"title": title}
|
|
31
|
-
response = self.
|
|
30
|
+
response = await self._apost(url, data=document_data)
|
|
32
31
|
response.raise_for_status()
|
|
33
|
-
|
|
32
|
+
payload = response.json()
|
|
33
|
+
payload["Note"] = "You must load and call other google docs content functions (like google_docs__insert_text)"
|
|
34
|
+
return payload
|
|
34
35
|
|
|
35
36
|
def get_document(self, document_id: str) -> dict[str, Any]:
|
|
36
37
|
"""
|
|
37
|
-
Retrieves the complete
|
|
38
|
+
Retrieves the complete, raw JSON object for a Google Document by its ID. This function returns the full, unprocessed API response with all metadata and structural elements, distinguishing it from `get_document_content`, which parses this data to extract only the title and plain text.
|
|
38
39
|
|
|
39
40
|
Args:
|
|
40
|
-
document_id: The unique identifier of the
|
|
41
|
+
document_id: The unique identifier of the Google Document to retrieve.
|
|
41
42
|
|
|
42
43
|
Returns:
|
|
43
|
-
A dictionary containing the document data
|
|
44
|
+
A dictionary containing the complete document data as returned by the Google Docs API.
|
|
44
45
|
|
|
45
46
|
Raises:
|
|
46
|
-
HTTPError: If the API request fails or the document
|
|
47
|
-
JSONDecodeError: If the API response cannot be parsed
|
|
47
|
+
HTTPError: If the API request fails or the specified document cannot be found.
|
|
48
|
+
JSONDecodeError: If the API response is not valid JSON and cannot be parsed.
|
|
48
49
|
|
|
49
50
|
Tags:
|
|
50
51
|
retrieve, read, api, document, google-docs, important
|
|
@@ -53,38 +54,182 @@ class GoogleDocsApp(APIApplication):
|
|
|
53
54
|
response = self._get(url)
|
|
54
55
|
return response.json()
|
|
55
56
|
|
|
56
|
-
def
|
|
57
|
-
self, document_id: str, content: str, index: int = 1
|
|
58
|
-
) -> dict[str, Any]:
|
|
57
|
+
async def get_document_content(self, document_id: str) -> dict[str, Any]:
|
|
59
58
|
"""
|
|
60
|
-
|
|
59
|
+
Retrieves and converts a Google Docs document into Markdown-formatted content.
|
|
60
|
+
|
|
61
|
+
This method calls the Google Docs API via `get_document`, then parses the document structure
|
|
62
|
+
to extract paragraphs, headings, lists, tables, images, equations, footnotes, and horizontal rules.
|
|
63
|
+
The final result is a clean Markdown string that closely mirrors the layout and content of
|
|
64
|
+
the original document, including support for nested lists and multi-row tables.
|
|
61
65
|
|
|
62
66
|
Args:
|
|
63
|
-
document_id: The unique
|
|
64
|
-
content: The text content to be inserted into the document
|
|
65
|
-
index: The zero-based position in the document where the text should be inserted (default: 1)
|
|
67
|
+
document_id (str): The unique ID of the Google Document to retrieve.
|
|
66
68
|
|
|
67
69
|
Returns:
|
|
68
|
-
A dictionary
|
|
70
|
+
dict[str, Any]: A dictionary with the following keys:
|
|
71
|
+
- 'title' (str): The document's title.
|
|
72
|
+
- 'content' (str): The document content converted to Markdown.
|
|
73
|
+
Markdown Output Supports:
|
|
74
|
+
- Paragraphs and line breaks
|
|
75
|
+
- Headings (Heading 1-6)
|
|
76
|
+
- Bulleted and numbered lists (with nesting)
|
|
77
|
+
- Tables (converted to Markdown tables)
|
|
78
|
+
- Inline images (`` format)
|
|
79
|
+
- Equations (LaTeX-style `$...$`)
|
|
80
|
+
- Footnotes (`[^1]` references and notes at the end)
|
|
81
|
+
- Horizontal rules (`---`)
|
|
82
|
+
|
|
83
|
+
Tags:
|
|
84
|
+
google-docs, markdown, document-parsing, text-extraction, conversion, structured-data
|
|
85
|
+
"""
|
|
86
|
+
import re
|
|
87
|
+
|
|
88
|
+
response = self.get_document(document_id)
|
|
89
|
+
title = response.get("title", "")
|
|
90
|
+
body_content = response.get("body", {}).get("content", [])
|
|
91
|
+
inline_objects = response.get("inlineObjects", {})
|
|
92
|
+
lists = response.get("lists", {})
|
|
93
|
+
footnotes_data = response.get("footnotes", {})
|
|
94
|
+
text_chunks: list[str] = []
|
|
95
|
+
footnotes: dict[str, str] = {}
|
|
96
|
+
footnote_index: dict[str, int] = {}
|
|
97
|
+
current_list_counters: dict[str, int] = {}
|
|
98
|
+
|
|
99
|
+
def extract_text_from_paragraph(paragraph: dict) -> str:
|
|
100
|
+
"""Extracts paragraph text with inline formatting."""
|
|
101
|
+
text = ""
|
|
102
|
+
for elem in paragraph.get("elements", []):
|
|
103
|
+
if "textRun" in elem:
|
|
104
|
+
content = elem["textRun"].get("content", "")
|
|
105
|
+
text += content
|
|
106
|
+
elif "inlineObjectElement" in elem:
|
|
107
|
+
obj_id = elem["inlineObjectElement"]["inlineObjectId"]
|
|
108
|
+
obj = inline_objects.get(obj_id, {})
|
|
109
|
+
embed = obj.get("inlineObjectProperties", {}).get("embeddedObject", {})
|
|
110
|
+
image_source = embed.get("imageProperties", {}).get("contentUri", "")
|
|
111
|
+
if image_source:
|
|
112
|
+
text += f"\n\n\n\n"
|
|
113
|
+
return text
|
|
114
|
+
|
|
115
|
+
def extract_table(table: dict) -> str:
|
|
116
|
+
rows = []
|
|
117
|
+
for i, row in enumerate(table.get("tableRows", [])):
|
|
118
|
+
cells = []
|
|
119
|
+
for cell in row.get("tableCells", []):
|
|
120
|
+
cell_text = ""
|
|
121
|
+
for content in cell.get("content", []):
|
|
122
|
+
if "paragraph" in content:
|
|
123
|
+
cell_text += extract_text_from_paragraph(content["paragraph"]).strip()
|
|
124
|
+
cells.append(cell_text)
|
|
125
|
+
row_line = "| " + " | ".join(cells) + " |"
|
|
126
|
+
rows.append(row_line)
|
|
127
|
+
if i == 0:
|
|
128
|
+
rows.insert(1, "| " + " | ".join(["---"] * len(cells)) + " |")
|
|
129
|
+
return "\n".join(rows)
|
|
130
|
+
|
|
131
|
+
def extract_heading_style(paragraph: dict) -> str:
|
|
132
|
+
"""Returns appropriate Markdown heading level."""
|
|
133
|
+
style = paragraph.get("paragraphStyle", {})
|
|
134
|
+
heading = style.get("namedStyleType", "")
|
|
135
|
+
match = re.match("HEADING_(\\d)", heading)
|
|
136
|
+
if match:
|
|
137
|
+
level = int(match.group(1))
|
|
138
|
+
return "#" * level
|
|
139
|
+
return ""
|
|
140
|
+
|
|
141
|
+
def extract_list_prefix(paragraph: dict) -> str:
|
|
142
|
+
"""Generates proper list prefix (numbered or bullet)."""
|
|
143
|
+
list_id = paragraph.get("bullet", {}).get("listId")
|
|
144
|
+
if not list_id:
|
|
145
|
+
return ""
|
|
146
|
+
glyph = paragraph["bullet"].get("glyph", None)
|
|
147
|
+
nesting = paragraph["bullet"].get("nestingLevel", 0)
|
|
148
|
+
list_info = lists.get(list_id, {})
|
|
149
|
+
list_type = list_info.get("listProperties", {}).get("nestingLevels", [{}])[nesting].get("glyphType")
|
|
150
|
+
indent = " " * nesting
|
|
151
|
+
if list_type and "DECIMAL" in list_type:
|
|
152
|
+
current_list_counters[list_id] = current_list_counters.get(list_id, 1)
|
|
153
|
+
prefix = f"{current_list_counters[list_id]}. "
|
|
154
|
+
current_list_counters[list_id] += 1
|
|
155
|
+
else:
|
|
156
|
+
prefix = "- "
|
|
157
|
+
return indent + prefix
|
|
158
|
+
|
|
159
|
+
def extract_equation(paragraph: dict) -> str:
|
|
160
|
+
return "\n\n$" + paragraph.get("equation", {}).get("equation", "") + "$\n\n"
|
|
161
|
+
|
|
162
|
+
def extract_footnote_ref(footnote_id: str) -> str:
|
|
163
|
+
if footnote_id not in footnote_index:
|
|
164
|
+
footnote_index[footnote_id] = len(footnotes) + 1
|
|
165
|
+
fn_content = footnotes_data.get(footnote_id, {}).get("content", [])
|
|
166
|
+
fn_text = ""
|
|
167
|
+
for item in fn_content:
|
|
168
|
+
if "paragraph" in item:
|
|
169
|
+
fn_text += extract_text_from_paragraph(item["paragraph"]).strip()
|
|
170
|
+
footnotes[footnote_id] = fn_text
|
|
171
|
+
return f"[^{footnote_index[footnote_id]}]"
|
|
172
|
+
|
|
173
|
+
for element in body_content:
|
|
174
|
+
if "paragraph" in element:
|
|
175
|
+
para = element["paragraph"]
|
|
176
|
+
if "equation" in para:
|
|
177
|
+
text_chunks.append(extract_equation(para))
|
|
178
|
+
continue
|
|
179
|
+
heading_md = extract_heading_style(para)
|
|
180
|
+
list_prefix = extract_list_prefix(para)
|
|
181
|
+
para_text = extract_text_from_paragraph(para).strip()
|
|
182
|
+
if para_text:
|
|
183
|
+
if heading_md:
|
|
184
|
+
text_chunks.append(f"{heading_md} {para_text}")
|
|
185
|
+
elif list_prefix:
|
|
186
|
+
text_chunks.append(f"{list_prefix}{para_text}")
|
|
187
|
+
else:
|
|
188
|
+
text_chunks.append(para_text)
|
|
189
|
+
elif "table" in element:
|
|
190
|
+
table_md = extract_table(element["table"])
|
|
191
|
+
text_chunks.append(table_md)
|
|
192
|
+
elif "horizontalRule" in element:
|
|
193
|
+
text_chunks.append("\n---\n")
|
|
194
|
+
elif "tableOfContents" in element:
|
|
195
|
+
text_chunks.append("<!-- Table of Contents -->")
|
|
196
|
+
elif "footnoteReference" in element:
|
|
197
|
+
footnote_id = element["footnoteReference"]["footnoteId"]
|
|
198
|
+
ref = extract_footnote_ref(footnote_id)
|
|
199
|
+
text_chunks.append(ref)
|
|
200
|
+
if footnotes:
|
|
201
|
+
text_chunks.append("\n## Footnotes\n")
|
|
202
|
+
for fid, index in sorted(footnote_index.items(), key=lambda x: x[1]):
|
|
203
|
+
text_chunks.append(f"[^{index}]: {footnotes[fid]}")
|
|
204
|
+
content = "\n\n".join((chunk.strip() for chunk in text_chunks if chunk.strip()))
|
|
205
|
+
return {"title": title, "content": content}
|
|
206
|
+
|
|
207
|
+
async def insert_text(self, document_id: str, content: str, index: int = 1) -> dict[str, Any]:
|
|
208
|
+
"""
|
|
209
|
+
Inserts a text string at a specified index within a Google Document using the batchUpdate API. Unlike functions that format existing text or delete content ranges, this method specifically adds new textual content to the document body.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
213
|
+
content: The text content to be inserted into the document.
|
|
214
|
+
index: The zero-based position in the document where the text should be inserted (default is 1).
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
A dictionary containing the Google Docs API response after performing the batch update operation.
|
|
69
218
|
|
|
70
219
|
Raises:
|
|
71
|
-
HTTPError:
|
|
72
|
-
RequestException:
|
|
220
|
+
HTTPError: If the API request fails, for example due to invalid document_id or insufficient permissions.
|
|
221
|
+
RequestException: If there are network connectivity issues or problems contacting the API endpoint.
|
|
73
222
|
|
|
74
223
|
Tags:
|
|
75
224
|
update, insert, document, api, google-docs, batch, content-management, important
|
|
76
225
|
"""
|
|
77
226
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
78
|
-
batch_update_data = {
|
|
79
|
-
|
|
80
|
-
{"insertText": {"location": {"index": index}, "text": content}}
|
|
81
|
-
]
|
|
82
|
-
}
|
|
83
|
-
response = self._post(url, data=batch_update_data)
|
|
227
|
+
batch_update_data = {"requests": [{"insertText": {"location": {"index": index}, "text": content}}]}
|
|
228
|
+
response = await self._apost(url, data=batch_update_data)
|
|
84
229
|
response.raise_for_status()
|
|
85
230
|
return response.json()
|
|
86
231
|
|
|
87
|
-
def apply_text_style(
|
|
232
|
+
async def apply_text_style(
|
|
88
233
|
self,
|
|
89
234
|
document_id: str,
|
|
90
235
|
start_index: int,
|
|
@@ -98,56 +243,48 @@ class GoogleDocsApp(APIApplication):
|
|
|
98
243
|
background_color: dict[str, float] | None = None,
|
|
99
244
|
) -> dict[str, Any]:
|
|
100
245
|
"""
|
|
101
|
-
Applies character-level formatting
|
|
246
|
+
Applies character-level formatting (e.g., bold, italic, color, links) to a specified text range. This function modifies text attributes directly, distinguishing it from `update_paragraph_style` which handles block-level properties like alignment.
|
|
102
247
|
|
|
103
248
|
Args:
|
|
104
|
-
document_id: The unique identifier of the Google Document to
|
|
105
|
-
start_index: The zero-based start index of the text range to style
|
|
106
|
-
end_index: The zero-based end index of the text range to style
|
|
107
|
-
bold: Whether
|
|
108
|
-
italic: Whether
|
|
109
|
-
underline: Whether
|
|
110
|
-
font_size:
|
|
111
|
-
link_url: URL to
|
|
112
|
-
foreground_color: RGB color
|
|
113
|
-
background_color: RGB color
|
|
249
|
+
document_id: The unique identifier of the Google Document to update.
|
|
250
|
+
start_index: The zero-based start index of the text range to apply the style.
|
|
251
|
+
end_index: The zero-based end index (exclusive) of the text range to apply the style.
|
|
252
|
+
bold: Whether to apply bold formatting to the text.
|
|
253
|
+
italic: Whether to apply italic formatting to the text.
|
|
254
|
+
underline: Whether to apply underline formatting to the text.
|
|
255
|
+
font_size: Font size in points (e.g., 12.0 for 12pt) to apply to the text.
|
|
256
|
+
link_url: URL to apply as a hyperlink to the text.
|
|
257
|
+
foreground_color: RGB color dictionary with 'red', 'green', and 'blue' floats (0.0 to 1.0) for the text color.
|
|
258
|
+
background_color: RGB color dictionary with 'red', 'green', and 'blue' floats (0.0 to 1.0) for the text background color.
|
|
114
259
|
|
|
115
260
|
Returns:
|
|
116
|
-
A dictionary containing the Google Docs API response
|
|
261
|
+
A dictionary containing the Google Docs API response, or a message if no styling was applied.
|
|
117
262
|
|
|
118
263
|
Raises:
|
|
119
|
-
HTTPError:
|
|
120
|
-
RequestException:
|
|
264
|
+
HTTPError: If the Google Docs API request fails.
|
|
265
|
+
RequestException: If there are network connectivity issues during the API request.
|
|
121
266
|
|
|
122
267
|
Tags:
|
|
123
|
-
style, format, text, document, api, google-docs,
|
|
268
|
+
style, format, text, document, api, google-docs, important
|
|
124
269
|
"""
|
|
125
270
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
126
|
-
|
|
127
|
-
# Build the text style object with only common properties
|
|
128
271
|
text_style = {}
|
|
129
272
|
fields_to_update = []
|
|
130
|
-
|
|
131
273
|
if bold:
|
|
132
274
|
text_style["bold"] = True
|
|
133
275
|
fields_to_update.append("bold")
|
|
134
|
-
|
|
135
276
|
if italic:
|
|
136
277
|
text_style["italic"] = True
|
|
137
278
|
fields_to_update.append("italic")
|
|
138
|
-
|
|
139
279
|
if underline:
|
|
140
280
|
text_style["underline"] = True
|
|
141
281
|
fields_to_update.append("underline")
|
|
142
|
-
|
|
143
282
|
if font_size is not None:
|
|
144
283
|
text_style["fontSize"] = {"magnitude": font_size, "unit": "PT"}
|
|
145
284
|
fields_to_update.append("fontSize")
|
|
146
|
-
|
|
147
285
|
if link_url is not None:
|
|
148
286
|
text_style["link"] = {"url": link_url}
|
|
149
287
|
fields_to_update.append("link")
|
|
150
|
-
|
|
151
288
|
if foreground_color is not None:
|
|
152
289
|
text_style["foregroundColor"] = {
|
|
153
290
|
"color": {
|
|
@@ -159,7 +296,6 @@ class GoogleDocsApp(APIApplication):
|
|
|
159
296
|
}
|
|
160
297
|
}
|
|
161
298
|
fields_to_update.append("foregroundColor")
|
|
162
|
-
|
|
163
299
|
if background_color is not None:
|
|
164
300
|
text_style["backgroundColor"] = {
|
|
165
301
|
"color": {
|
|
@@ -171,11 +307,8 @@ class GoogleDocsApp(APIApplication):
|
|
|
171
307
|
}
|
|
172
308
|
}
|
|
173
309
|
fields_to_update.append("backgroundColor")
|
|
174
|
-
|
|
175
|
-
# If no styling requested, return early
|
|
176
310
|
if not text_style:
|
|
177
311
|
return {"message": "No styling applied"}
|
|
178
|
-
|
|
179
312
|
batch_update_data = {
|
|
180
313
|
"requests": [
|
|
181
314
|
{
|
|
@@ -187,11 +320,10 @@ class GoogleDocsApp(APIApplication):
|
|
|
187
320
|
}
|
|
188
321
|
]
|
|
189
322
|
}
|
|
190
|
-
|
|
191
|
-
response = self._post(url, data=batch_update_data)
|
|
323
|
+
response = await self._apost(url, data=batch_update_data)
|
|
192
324
|
return self._handle_response(response)
|
|
193
325
|
|
|
194
|
-
def update_paragraph_style(
|
|
326
|
+
async def update_paragraph_style(
|
|
195
327
|
self,
|
|
196
328
|
document_id: str,
|
|
197
329
|
start_index: int,
|
|
@@ -204,184 +336,127 @@ class GoogleDocsApp(APIApplication):
|
|
|
204
336
|
tab_id: str | None = None,
|
|
205
337
|
) -> dict[str, Any]:
|
|
206
338
|
"""
|
|
207
|
-
Applies paragraph-level formatting
|
|
339
|
+
Applies paragraph-level formatting like alignment, named styles (e.g., 'HEADING_1'), and text direction to a text range in a Google Doc. Distinct from `apply_text_style`, which handles character formatting, this method modifies properties for entire paragraphs using the batchUpdate API.
|
|
208
340
|
|
|
209
341
|
Args:
|
|
210
|
-
document_id: The unique identifier of the Google Document to
|
|
211
|
-
start_index: The zero-based start index of the paragraph range to style
|
|
212
|
-
end_index: The zero-based end index of the paragraph range to style (exclusive)
|
|
213
|
-
named_style_type: The named style type (e.g., 'NORMAL_TEXT', 'TITLE', 'HEADING_1'
|
|
214
|
-
alignment:
|
|
215
|
-
direction:
|
|
216
|
-
spacing_mode:
|
|
217
|
-
segment_id:
|
|
218
|
-
tab_id:
|
|
342
|
+
document_id: The unique identifier of the Google Document to update.
|
|
343
|
+
start_index: The zero-based start index of the paragraph range to style.
|
|
344
|
+
end_index: The zero-based end index of the paragraph range to style (exclusive).
|
|
345
|
+
named_style_type: The named style type to apply (e.g., 'NORMAL_TEXT', 'TITLE', 'HEADING_1').
|
|
346
|
+
alignment: Paragraph alignment option ('START', 'CENTER', 'END', 'JUSTIFIED').
|
|
347
|
+
direction: Content direction of the paragraph ('LEFT_TO_RIGHT', 'RIGHT_TO_LEFT').
|
|
348
|
+
spacing_mode: Spacing mode for the paragraph ('NEVER_COLLAPSE', 'COLLAPSE_LISTS').
|
|
349
|
+
segment_id: Optional segment ID for the text range.
|
|
350
|
+
tab_id: Optional tab ID for the text range.
|
|
219
351
|
|
|
220
352
|
Returns:
|
|
221
|
-
A dictionary containing the Google Docs
|
|
353
|
+
A dictionary containing the API response from the Google Docs batchUpdate request.
|
|
222
354
|
|
|
223
355
|
Raises:
|
|
224
|
-
HTTPError:
|
|
225
|
-
RequestException:
|
|
356
|
+
HTTPError: If the API request to update the document fails due to an HTTP error.
|
|
357
|
+
RequestException: If there are network connectivity issues during the API request.
|
|
226
358
|
|
|
227
359
|
Tags:
|
|
228
|
-
style, format, paragraph, document, api, google-docs, batch, content-management
|
|
360
|
+
style, format, paragraph, document, api, google-docs, batch, content-management, important
|
|
229
361
|
"""
|
|
230
362
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
231
|
-
|
|
232
|
-
# Build the paragraph style object with only specified properties
|
|
233
363
|
paragraph_style = {}
|
|
234
364
|
fields_to_update = []
|
|
235
|
-
|
|
236
365
|
if named_style_type is not None:
|
|
237
366
|
paragraph_style["namedStyleType"] = named_style_type
|
|
238
367
|
fields_to_update.append("namedStyleType")
|
|
239
|
-
|
|
240
368
|
if alignment is not None:
|
|
241
369
|
paragraph_style["alignment"] = alignment
|
|
242
370
|
fields_to_update.append("alignment")
|
|
243
|
-
|
|
244
371
|
if direction is not None:
|
|
245
372
|
paragraph_style["direction"] = direction
|
|
246
373
|
fields_to_update.append("direction")
|
|
247
|
-
|
|
248
374
|
if spacing_mode is not None:
|
|
249
375
|
paragraph_style["spacingMode"] = spacing_mode
|
|
250
376
|
fields_to_update.append("spacingMode")
|
|
251
|
-
|
|
252
|
-
# If no styling requested, return early
|
|
253
377
|
if not paragraph_style:
|
|
254
378
|
return {"message": "No paragraph styling applied"}
|
|
255
|
-
|
|
256
|
-
# Build the range object
|
|
257
379
|
range_obj: dict[str, Any] = {"startIndex": start_index, "endIndex": end_index}
|
|
258
|
-
|
|
259
|
-
# Add optional parameters if provided
|
|
260
380
|
if segment_id is not None:
|
|
261
381
|
range_obj["segmentId"] = segment_id
|
|
262
382
|
if tab_id is not None:
|
|
263
383
|
range_obj["tabId"] = tab_id
|
|
264
|
-
|
|
265
384
|
batch_update_data = {
|
|
266
385
|
"requests": [
|
|
267
|
-
{
|
|
268
|
-
"updateParagraphStyle": {
|
|
269
|
-
"range": range_obj,
|
|
270
|
-
"paragraphStyle": paragraph_style,
|
|
271
|
-
"fields": ",".join(fields_to_update),
|
|
272
|
-
}
|
|
273
|
-
}
|
|
386
|
+
{"updateParagraphStyle": {"range": range_obj, "paragraphStyle": paragraph_style, "fields": ",".join(fields_to_update)}}
|
|
274
387
|
]
|
|
275
388
|
}
|
|
276
|
-
|
|
277
|
-
response = self._post(url, data=batch_update_data)
|
|
389
|
+
response = await self._apost(url, data=batch_update_data)
|
|
278
390
|
return self._handle_response(response)
|
|
279
391
|
|
|
280
|
-
def delete_content_range(
|
|
281
|
-
self,
|
|
282
|
-
document_id: str,
|
|
283
|
-
start_index: int,
|
|
284
|
-
end_index: int,
|
|
285
|
-
segment_id: str | None = None,
|
|
286
|
-
tab_id: str | None = None,
|
|
392
|
+
async def delete_content_range(
|
|
393
|
+
self, document_id: str, start_index: int, end_index: int, segment_id: str | None = None, tab_id: str | None = None
|
|
287
394
|
) -> dict[str, Any]:
|
|
288
395
|
"""
|
|
289
|
-
|
|
396
|
+
Removes content from a specified index range in a Google Document via the batchUpdate API. Unlike functions that delete entire elements (e.g., `delete_header`), this provides granular control by targeting content based on its precise start and end location, optionally within a specific segment or tab.
|
|
290
397
|
|
|
291
398
|
Args:
|
|
292
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
293
|
-
start_index: The zero-based start index of the content range to delete
|
|
294
|
-
end_index: The zero-based end index of the content range to delete (exclusive)
|
|
295
|
-
segment_id:
|
|
296
|
-
tab_id:
|
|
399
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
400
|
+
start_index: The zero-based start index of the content range to delete.
|
|
401
|
+
end_index: The zero-based end index of the content range to delete (exclusive).
|
|
402
|
+
segment_id: Optional; the ID of the header, footer, or footnote segment containing the content.
|
|
403
|
+
tab_id: Optional; the ID of the tab containing the content to delete.
|
|
297
404
|
|
|
298
405
|
Returns:
|
|
299
|
-
A dictionary
|
|
406
|
+
A dictionary representing the Google Docs API response after performing the delete operation.
|
|
300
407
|
|
|
301
408
|
Raises:
|
|
302
|
-
HTTPError:
|
|
303
|
-
RequestException:
|
|
409
|
+
HTTPError: Raised when the API request fails due to issues such as invalid document ID or insufficient permissions.
|
|
410
|
+
RequestException: Raised when there are network connectivity issues or problems with the API endpoint.
|
|
304
411
|
|
|
305
412
|
Tags:
|
|
306
413
|
delete, remove, content, document, api, google-docs, batch, content-management, important
|
|
307
414
|
"""
|
|
308
415
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
309
|
-
|
|
310
|
-
# Build the delete content range request
|
|
311
|
-
delete_request: dict[str, Any] = {
|
|
312
|
-
"range": {"startIndex": start_index, "endIndex": end_index}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
# Add optional parameters if provided
|
|
416
|
+
delete_request: dict[str, Any] = {"range": {"startIndex": start_index, "endIndex": end_index}}
|
|
316
417
|
if segment_id is not None:
|
|
317
418
|
delete_request["range"]["segmentId"] = segment_id
|
|
318
419
|
if tab_id is not None:
|
|
319
420
|
delete_request["tabId"] = tab_id
|
|
320
|
-
|
|
321
421
|
batch_update_data = {"requests": [{"deleteContentRange": delete_request}]}
|
|
322
|
-
|
|
323
|
-
response = self._post(url, data=batch_update_data)
|
|
422
|
+
response = await self._apost(url, data=batch_update_data)
|
|
324
423
|
return self._handle_response(response)
|
|
325
424
|
|
|
326
|
-
def insert_table(
|
|
327
|
-
self,
|
|
328
|
-
document_id: str,
|
|
329
|
-
location_index: int,
|
|
330
|
-
rows: int,
|
|
331
|
-
columns: int,
|
|
332
|
-
segment_id: str = None,
|
|
333
|
-
tab_id: str = None,
|
|
425
|
+
async def insert_table(
|
|
426
|
+
self, document_id: str, location_index: int, rows: int, columns: int, segment_id: str = None, tab_id: str = None
|
|
334
427
|
) -> dict[str, Any]:
|
|
335
428
|
"""
|
|
336
|
-
Inserts a table with specified
|
|
429
|
+
Inserts a table with specified rows and columns at a given index in a Google Document using the batchUpdate API. It can optionally place the table within specific document segments, such as headers or footers, handling structural additions rather than text or style modifications.
|
|
337
430
|
|
|
338
431
|
Args:
|
|
339
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
340
|
-
location_index: The zero-based index where the table should be inserted
|
|
341
|
-
rows: The number of rows
|
|
342
|
-
columns: The number of columns
|
|
343
|
-
segment_id:
|
|
344
|
-
tab_id:
|
|
432
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
433
|
+
location_index: The zero-based index within the document body or segment where the table should be inserted.
|
|
434
|
+
rows: The number of rows the inserted table should have.
|
|
435
|
+
columns: The number of columns the inserted table should have.
|
|
436
|
+
segment_id: Optional ID of the header, footer, or footnote segment where the table will be inserted (if applicable).
|
|
437
|
+
tab_id: Optional ID of the tab containing the insertion location.
|
|
345
438
|
|
|
346
439
|
Returns:
|
|
347
|
-
A dictionary containing the Google Docs API
|
|
440
|
+
A dictionary containing the response from the Google Docs API after performing the table insertion.
|
|
348
441
|
|
|
349
442
|
Raises:
|
|
350
|
-
HTTPError:
|
|
351
|
-
RequestException:
|
|
443
|
+
HTTPError: Raised when the API request fails due to reasons such as invalid document ID or insufficient permissions.
|
|
444
|
+
RequestException: Raised when there are network connectivity issues or problems reaching the API endpoint.
|
|
352
445
|
|
|
353
446
|
Tags:
|
|
354
|
-
table, insert, document, api, google-docs, batch, content-management
|
|
447
|
+
table, insert, document, api, google-docs, batch, content-management, important
|
|
355
448
|
"""
|
|
356
449
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
357
|
-
|
|
358
|
-
# Build the location object according to Google Docs API specification
|
|
359
450
|
location = {"index": location_index}
|
|
360
|
-
|
|
361
|
-
# Add segment_id if provided (empty string for document body, specific ID for header/footer/footnote)
|
|
362
451
|
if segment_id is not None:
|
|
363
452
|
location["segmentId"] = segment_id
|
|
364
|
-
|
|
365
|
-
# Add tab_id if provided
|
|
366
453
|
if tab_id is not None:
|
|
367
454
|
location["tabId"] = tab_id
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
"requests": [
|
|
371
|
-
{
|
|
372
|
-
"insertTable": {
|
|
373
|
-
"location": location,
|
|
374
|
-
"rows": rows,
|
|
375
|
-
"columns": columns,
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
]
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
response = self._post(url, data=batch_update_data)
|
|
455
|
+
batch_update_data = {"requests": [{"insertTable": {"location": location, "rows": rows, "columns": columns}}]}
|
|
456
|
+
response = await self._apost(url, data=batch_update_data)
|
|
382
457
|
return self._handle_response(response)
|
|
383
458
|
|
|
384
|
-
def create_footer(
|
|
459
|
+
async def create_footer(
|
|
385
460
|
self,
|
|
386
461
|
document_id: str,
|
|
387
462
|
footer_type: str = "DEFAULT",
|
|
@@ -390,48 +465,39 @@ class GoogleDocsApp(APIApplication):
|
|
|
390
465
|
section_break_tab_id: str = None,
|
|
391
466
|
) -> dict[str, Any]:
|
|
392
467
|
"""
|
|
393
|
-
Creates a footer of a specified type in a Google Document
|
|
468
|
+
Creates a footer of a specified type in a Google Document using the batch update API. This function, distinct from `create_header`, can optionally associate the new footer with a specific section break, enabling section-specific footers within the document.
|
|
394
469
|
|
|
395
470
|
Args:
|
|
396
|
-
document_id: The unique identifier of the Google Document to
|
|
397
|
-
footer_type: The type of footer to create
|
|
398
|
-
section_break_location_index:
|
|
399
|
-
section_break_segment_id:
|
|
400
|
-
section_break_tab_id:
|
|
471
|
+
document_id: The unique identifier of the Google Document to update.
|
|
472
|
+
footer_type: The type of footer to create, such as 'DEFAULT' or 'HEADER_FOOTER_TYPE_UNSPECIFIED'.
|
|
473
|
+
section_break_location_index: Optional index of the SectionBreak location to associate with the footer.
|
|
474
|
+
section_break_segment_id: Optional segment ID of the SectionBreak location.
|
|
475
|
+
section_break_tab_id: Optional tab ID of the SectionBreak location.
|
|
401
476
|
|
|
402
477
|
Returns:
|
|
403
|
-
A dictionary containing the Google Docs API response
|
|
478
|
+
A dictionary containing the Google Docs API response from the create footer operation.
|
|
404
479
|
|
|
405
480
|
Raises:
|
|
406
|
-
HTTPError:
|
|
407
|
-
RequestException:
|
|
481
|
+
HTTPError: Raised when the API request fails due to reasons like invalid document_id or insufficient permissions.
|
|
482
|
+
RequestException: Raised when there are network connectivity issues or problems with the API endpoint.
|
|
408
483
|
|
|
409
484
|
Tags:
|
|
410
|
-
footer, create, document, api, google-docs, batch, content-management
|
|
485
|
+
footer, create, document, api, google-docs, batch, content-management, important
|
|
411
486
|
"""
|
|
412
487
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
413
|
-
|
|
414
|
-
# Build the create footer request
|
|
415
488
|
create_footer_request = {"type": footer_type}
|
|
416
|
-
|
|
417
|
-
# Add section break location if provided
|
|
418
489
|
if section_break_location_index is not None:
|
|
419
490
|
section_break_location = {"index": section_break_location_index}
|
|
420
|
-
|
|
421
491
|
if section_break_segment_id is not None:
|
|
422
492
|
section_break_location["segmentId"] = section_break_segment_id
|
|
423
|
-
|
|
424
493
|
if section_break_tab_id is not None:
|
|
425
494
|
section_break_location["tabId"] = section_break_tab_id
|
|
426
|
-
|
|
427
495
|
create_footer_request["sectionBreakLocation"] = section_break_location
|
|
428
|
-
|
|
429
496
|
batch_update_data = {"requests": [{"createFooter": create_footer_request}]}
|
|
430
|
-
|
|
431
|
-
response = self._post(url, data=batch_update_data)
|
|
497
|
+
response = await self._apost(url, data=batch_update_data)
|
|
432
498
|
return self._handle_response(response)
|
|
433
499
|
|
|
434
|
-
def create_footnote(
|
|
500
|
+
async def create_footnote(
|
|
435
501
|
self,
|
|
436
502
|
document_id: str,
|
|
437
503
|
location_index: int = None,
|
|
@@ -442,101 +508,75 @@ class GoogleDocsApp(APIApplication):
|
|
|
442
508
|
end_of_segment_tab_id: str = None,
|
|
443
509
|
) -> dict[str, Any]:
|
|
444
510
|
"""
|
|
445
|
-
|
|
511
|
+
Inserts a numbered footnote reference into a Google Document using the batchUpdate API. The footnote can be placed at a precise index or at the end of a document segment, distinct from the `create_footer` function which adds standard page footers.
|
|
446
512
|
|
|
447
513
|
Args:
|
|
448
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
449
|
-
location_index: The index
|
|
450
|
-
location_segment_id: The segment ID
|
|
451
|
-
location_tab_id: The tab ID for the location (optional)
|
|
452
|
-
end_of_segment_location:
|
|
453
|
-
end_of_segment_segment_id: The segment ID
|
|
454
|
-
end_of_segment_tab_id: The tab ID for end
|
|
514
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
515
|
+
location_index: The zero-based index within the document where the footnote reference will be inserted (optional if inserting at end of segment).
|
|
516
|
+
location_segment_id: The segment ID where the footnote reference should be inserted (optional, usually empty for the document body).
|
|
517
|
+
location_tab_id: The tab ID for the location within the segment (optional).
|
|
518
|
+
end_of_segment_location: If True, inserts the footnote reference at the end of a segment instead of a specific index (default is False).
|
|
519
|
+
end_of_segment_segment_id: The segment ID indicating where to insert the footnote at the end of a segment (optional).
|
|
520
|
+
end_of_segment_tab_id: The tab ID for the end-of-segment location (optional).
|
|
455
521
|
|
|
456
522
|
Returns:
|
|
457
|
-
A dictionary containing the Google Docs API
|
|
523
|
+
A dictionary containing the response from the Google Docs API after performing the footnote creation operation.
|
|
458
524
|
|
|
459
525
|
Raises:
|
|
460
|
-
HTTPError:
|
|
461
|
-
RequestException:
|
|
526
|
+
HTTPError: Raised when the API request fails, such as due to an invalid document ID or insufficient permissions.
|
|
527
|
+
RequestException: Raised when there are network connectivity issues or problems reaching the API endpoint.
|
|
462
528
|
|
|
463
529
|
Tags:
|
|
464
|
-
footnote, create, document, api, google-docs, batch, content-management
|
|
530
|
+
footnote, create, document, api, google-docs, batch, content-management, important
|
|
465
531
|
"""
|
|
466
532
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
467
|
-
|
|
468
|
-
# Build the create footnote request
|
|
469
533
|
create_footnote_request = {}
|
|
470
|
-
|
|
471
534
|
if end_of_segment_location:
|
|
472
|
-
# Use endOfSegmentLocation
|
|
473
535
|
end_of_segment_location_obj = {}
|
|
474
|
-
|
|
475
536
|
if end_of_segment_segment_id is not None:
|
|
476
537
|
end_of_segment_location_obj["segmentId"] = end_of_segment_segment_id
|
|
477
|
-
|
|
478
538
|
if end_of_segment_tab_id is not None:
|
|
479
539
|
end_of_segment_location_obj["tabId"] = end_of_segment_tab_id
|
|
480
|
-
|
|
481
|
-
create_footnote_request["endOfSegmentLocation"] = (
|
|
482
|
-
end_of_segment_location_obj
|
|
483
|
-
)
|
|
540
|
+
create_footnote_request["endOfSegmentLocation"] = end_of_segment_location_obj
|
|
484
541
|
else:
|
|
485
|
-
# Use specific location
|
|
486
542
|
location = {"index": location_index}
|
|
487
|
-
|
|
488
543
|
if location_segment_id is not None:
|
|
489
544
|
location["segmentId"] = location_segment_id
|
|
490
|
-
|
|
491
545
|
if location_tab_id is not None:
|
|
492
546
|
location["tabId"] = location_tab_id
|
|
493
|
-
|
|
494
547
|
create_footnote_request["location"] = location
|
|
495
|
-
|
|
496
548
|
batch_update_data = {"requests": [{"createFootnote": create_footnote_request}]}
|
|
497
|
-
|
|
498
|
-
response = self._post(url, data=batch_update_data)
|
|
549
|
+
response = await self._apost(url, data=batch_update_data)
|
|
499
550
|
return self._handle_response(response)
|
|
500
551
|
|
|
501
|
-
def delete_footer(
|
|
502
|
-
self,
|
|
503
|
-
document_id: str,
|
|
504
|
-
footer_id: str,
|
|
505
|
-
tab_id: str = None,
|
|
506
|
-
) -> dict[str, Any]:
|
|
552
|
+
async def delete_footer(self, document_id: str, footer_id: str, tab_id: str = None) -> dict[str, Any]:
|
|
507
553
|
"""
|
|
508
|
-
Deletes a specific footer from a Google Document using its unique ID via a
|
|
554
|
+
Deletes a specific footer from a Google Document using its unique ID via a batchUpdate API request. This operation removes the entire footer object, optionally within a specific tab, distinguishing it from functions that delete headers (`delete_header`) or general content (`delete_content_range`).
|
|
509
555
|
|
|
510
556
|
Args:
|
|
511
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
512
|
-
footer_id: The
|
|
513
|
-
tab_id:
|
|
557
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
558
|
+
footer_id: The identifier of the footer to delete.
|
|
559
|
+
tab_id: Optional identifier of the tab containing the footer to delete.
|
|
514
560
|
|
|
515
561
|
Returns:
|
|
516
|
-
A dictionary containing the Google Docs API
|
|
562
|
+
A dictionary containing the response from the Google Docs API after performing the delete footer operation.
|
|
517
563
|
|
|
518
564
|
Raises:
|
|
519
|
-
HTTPError:
|
|
520
|
-
RequestException:
|
|
565
|
+
HTTPError: Raised when the API request fails due to reasons such as an invalid document ID or insufficient permissions.
|
|
566
|
+
RequestException: Raised for network-related issues or problems reaching the API endpoint.
|
|
521
567
|
|
|
522
568
|
Tags:
|
|
523
|
-
footer, delete, remove, document, api, google-docs, batch, content-management
|
|
569
|
+
footer, delete, remove, document, api, google-docs, batch, content-management, important
|
|
524
570
|
"""
|
|
525
571
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
526
|
-
|
|
527
|
-
# Build the delete footer request
|
|
528
572
|
delete_footer_request = {"footerId": footer_id}
|
|
529
|
-
|
|
530
|
-
# Add tab_id if provided
|
|
531
573
|
if tab_id is not None:
|
|
532
574
|
delete_footer_request["tabId"] = tab_id
|
|
533
|
-
|
|
534
575
|
batch_update_data = {"requests": [{"deleteFooter": delete_footer_request}]}
|
|
535
|
-
|
|
536
|
-
response = self._post(url, data=batch_update_data)
|
|
576
|
+
response = await self._apost(url, data=batch_update_data)
|
|
537
577
|
return self._handle_response(response)
|
|
538
578
|
|
|
539
|
-
def create_header(
|
|
579
|
+
async def create_header(
|
|
540
580
|
self,
|
|
541
581
|
document_id: str,
|
|
542
582
|
header_type: str = "DEFAULT",
|
|
@@ -545,206 +585,136 @@ class GoogleDocsApp(APIApplication):
|
|
|
545
585
|
section_break_tab_id: str = None,
|
|
546
586
|
) -> dict[str, Any]:
|
|
547
587
|
"""
|
|
548
|
-
Creates a header
|
|
588
|
+
Creates a header of a specified type in a Google Document using the batchUpdate API. This function can optionally associate the new header with a specific section break, distinguishing it from the `create_footer` method, which performs the equivalent action for footers.
|
|
549
589
|
|
|
550
590
|
Args:
|
|
551
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
552
|
-
header_type: The type of header to create
|
|
553
|
-
section_break_location_index: The index of the
|
|
554
|
-
section_break_segment_id: The segment ID
|
|
555
|
-
section_break_tab_id: The tab ID
|
|
591
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
592
|
+
header_type: The type of header to create, e.g., 'DEFAULT' or 'HEADER_FOOTER_TYPE_UNSPECIFIED'.
|
|
593
|
+
section_break_location_index: The index position of the section break location within the document, if applicable.
|
|
594
|
+
section_break_segment_id: The segment ID associated with the section break location, if applicable.
|
|
595
|
+
section_break_tab_id: The tab ID associated with the section break location, if applicable.
|
|
556
596
|
|
|
557
597
|
Returns:
|
|
558
|
-
A dictionary containing the Google Docs API
|
|
598
|
+
A dictionary containing the response from the Google Docs API after the header creation request.
|
|
559
599
|
|
|
560
600
|
Raises:
|
|
561
|
-
HTTPError:
|
|
562
|
-
RequestException:
|
|
601
|
+
HTTPError: If the API request fails due to issues such as an invalid document ID or insufficient permissions.
|
|
602
|
+
RequestException: If there are network problems or issues reaching the API endpoint.
|
|
563
603
|
|
|
564
604
|
Tags:
|
|
565
605
|
header, create, document, api, google-docs, batch, content-management, important
|
|
566
606
|
"""
|
|
567
607
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
568
|
-
|
|
569
|
-
# Build the create header request
|
|
570
608
|
create_header_request = {"type": header_type}
|
|
571
|
-
|
|
572
|
-
# Add section break location if provided
|
|
573
609
|
if section_break_location_index is not None:
|
|
574
610
|
section_break_location = {"index": section_break_location_index}
|
|
575
|
-
|
|
576
611
|
if section_break_segment_id is not None:
|
|
577
612
|
section_break_location["segmentId"] = section_break_segment_id
|
|
578
|
-
|
|
579
613
|
if section_break_tab_id is not None:
|
|
580
614
|
section_break_location["tabId"] = section_break_tab_id
|
|
581
|
-
|
|
582
615
|
create_header_request["sectionBreakLocation"] = section_break_location
|
|
583
|
-
|
|
584
616
|
batch_update_data = {"requests": [{"createHeader": create_header_request}]}
|
|
585
|
-
|
|
586
|
-
response = self._post(url, data=batch_update_data)
|
|
617
|
+
response = await self._apost(url, data=batch_update_data)
|
|
587
618
|
return self._handle_response(response)
|
|
588
619
|
|
|
589
|
-
def delete_header(
|
|
590
|
-
self,
|
|
591
|
-
document_id: str,
|
|
592
|
-
header_id: str,
|
|
593
|
-
tab_id: str = None,
|
|
594
|
-
) -> dict[str, Any]:
|
|
620
|
+
async def delete_header(self, document_id: str, header_id: str, tab_id: str = None) -> dict[str, Any]:
|
|
595
621
|
"""
|
|
596
|
-
|
|
622
|
+
Deletes a specific header from a Google Document using its unique ID via a batchUpdate API request. This function, the counterpart to `create_header`, removes headers and can optionally target a header within a specific tab. It requires both the document and header IDs for the operation.
|
|
597
623
|
|
|
598
624
|
Args:
|
|
599
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
600
|
-
header_id: The ID of the header to delete
|
|
601
|
-
tab_id:
|
|
625
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
626
|
+
header_id: The ID of the header to delete.
|
|
627
|
+
tab_id: Optional ID of the tab containing the header to delete.
|
|
602
628
|
|
|
603
629
|
Returns:
|
|
604
|
-
A dictionary containing the Google Docs API
|
|
630
|
+
A dictionary containing the response from the Google Docs API after performing the delete header operation.
|
|
605
631
|
|
|
606
632
|
Raises:
|
|
607
|
-
HTTPError:
|
|
608
|
-
RequestException:
|
|
633
|
+
HTTPError: Raised when the API request fails due to invalid document_id, insufficient permissions, or other HTTP errors.
|
|
634
|
+
RequestException: Raised when network connectivity issues or API endpoint problems occur during the request.
|
|
609
635
|
|
|
610
636
|
Tags:
|
|
611
|
-
header, delete, remove, document, api, google-docs, batch, content-management
|
|
637
|
+
header, delete, remove, document, api, google-docs, batch, content-management, important
|
|
612
638
|
"""
|
|
613
639
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
614
|
-
|
|
615
|
-
# Build the delete header request
|
|
616
640
|
delete_header_request = {"headerId": header_id}
|
|
617
|
-
|
|
618
|
-
# Add tab_id if provided
|
|
619
641
|
if tab_id is not None:
|
|
620
642
|
delete_header_request["tabId"] = tab_id
|
|
621
|
-
|
|
622
643
|
batch_update_data = {"requests": [{"deleteHeader": delete_header_request}]}
|
|
623
|
-
|
|
624
|
-
response = self._post(url, data=batch_update_data)
|
|
644
|
+
response = await self._apost(url, data=batch_update_data)
|
|
625
645
|
return self._handle_response(response)
|
|
626
646
|
|
|
627
|
-
def apply_list_style(
|
|
628
|
-
self,
|
|
629
|
-
document_id: str,
|
|
630
|
-
start_index: int,
|
|
631
|
-
end_index: int,
|
|
632
|
-
bullet_preset: str,
|
|
633
|
-
segment_id: str = None,
|
|
634
|
-
tab_id: str = None,
|
|
647
|
+
async def apply_list_style(
|
|
648
|
+
self, document_id: str, start_index: int, end_index: int, bullet_preset: str, segment_id: str = None, tab_id: str = None
|
|
635
649
|
) -> dict[str, Any]:
|
|
636
650
|
"""
|
|
637
|
-
Applies a predefined bulleted or numbered
|
|
651
|
+
Applies a predefined list style (bulleted or numbered) to paragraphs within a specified range using a chosen preset. Unlike `delete_paragraph_bullets`, which removes list formatting, this function creates it, distinguishing it from other text and paragraph styling methods in the class.
|
|
638
652
|
|
|
639
653
|
Args:
|
|
640
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
641
|
-
start_index: The zero-based start index of the range to
|
|
642
|
-
end_index: The zero-based end index of the range to apply
|
|
643
|
-
bullet_preset:
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
- BULLET_DIAMONDX_ARROW3D_SQUARE: DIAMONDX, ARROW3D and SQUARE for first 3 nesting levels
|
|
647
|
-
- BULLET_CHECKBOX: CHECKBOX bullet glyphs for all nesting levels
|
|
648
|
-
- BULLET_ARROW_DIAMOND_DISC: ARROW, DIAMOND and DISC for first 3 nesting levels
|
|
649
|
-
- BULLET_STAR_CIRCLE_SQUARE: STAR, CIRCLE and SQUARE for first 3 nesting levels
|
|
650
|
-
- BULLET_ARROW3D_CIRCLE_SQUARE: ARROW3D, CIRCLE and SQUARE for first 3 nesting levels
|
|
651
|
-
- BULLET_LEFTTRIANGLE_DIAMOND_DISC: LEFTTRIANGLE, DIAMOND and DISC for first 3 nesting levels
|
|
652
|
-
- BULLET_DIAMONDX_HOLLOWDIAMOND_SQUARE: DIAMONDX, HOLLOWDIAMOND and SQUARE for first 3 nesting levels
|
|
653
|
-
- BULLET_DIAMOND_CIRCLE_SQUARE: DIAMOND, CIRCLE and SQUARE for first 3 nesting levels
|
|
654
|
-
- NUMBERED_DECIMAL_ALPHA_ROMAN: DECIMAL, ALPHA and ROMAN with periods
|
|
655
|
-
- NUMBERED_DECIMAL_ALPHA_ROMAN_PARENS: DECIMAL, ALPHA and ROMAN with parenthesis
|
|
656
|
-
- NUMBERED_DECIMAL_NESTED: DECIMAL with nested numbering (1., 1.1., 2., 2.2.)
|
|
657
|
-
- NUMBERED_UPPERALPHA_ALPHA_ROMAN: UPPERALPHA, ALPHA and ROMAN with periods
|
|
658
|
-
- NUMBERED_UPPERROMAN_UPPERALPHA_DECIMAL: UPPERROMAN, UPPERALPHA and DECIMAL with periods
|
|
659
|
-
- NUMBERED_ZERODECIMAL_ALPHA_ROMAN: ZERODECIMAL, ALPHA and ROMAN with periods
|
|
660
|
-
segment_id: The segment ID for the range (optional)
|
|
661
|
-
tab_id: The tab ID for the range (optional)
|
|
654
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
655
|
+
start_index: The zero-based start index of the text range to which the list style should be applied.
|
|
656
|
+
end_index: The zero-based end index (exclusive) of the text range to apply the list style.
|
|
657
|
+
bullet_preset: Specifies the bullet or numbering style preset to use (e.g., bulleted or numbered formats with specific glyphs).
|
|
658
|
+
segment_id: Optional segment ID within the document where the updates apply.
|
|
659
|
+
tab_id: Optional tab ID within the segment to narrow the update scope.
|
|
662
660
|
|
|
663
661
|
Returns:
|
|
664
|
-
A dictionary
|
|
662
|
+
A dictionary representing the Google Docs API response confirming the application of the bullet list style.
|
|
665
663
|
|
|
666
664
|
Raises:
|
|
667
|
-
HTTPError:
|
|
668
|
-
RequestException:
|
|
665
|
+
HTTPError: Raised when the API request to update the document fails (e.g., invalid document ID or insufficient permissions).
|
|
666
|
+
RequestException: Raised on network issues or problems reaching the API endpoint.
|
|
669
667
|
|
|
670
668
|
Tags:
|
|
671
|
-
bullets, list, paragraph, document, api, google-docs, batch, content-management
|
|
669
|
+
bullets, list, paragraph, document, api, google-docs, batch, content-management, important
|
|
672
670
|
"""
|
|
673
671
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
674
|
-
|
|
675
|
-
# Build the range object
|
|
676
672
|
range_obj = {"startIndex": start_index, "endIndex": end_index}
|
|
677
|
-
|
|
678
|
-
# Add optional parameters if provided
|
|
679
673
|
if segment_id is not None:
|
|
680
674
|
range_obj["segmentId"] = segment_id
|
|
681
675
|
if tab_id is not None:
|
|
682
676
|
range_obj["tabId"] = tab_id
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
"requests": [
|
|
686
|
-
{
|
|
687
|
-
"createParagraphBullets": {
|
|
688
|
-
"range": range_obj,
|
|
689
|
-
"bulletPreset": bullet_preset,
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
]
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
response = self._post(url, data=batch_update_data)
|
|
677
|
+
batch_update_data = {"requests": [{"createParagraphBullets": {"range": range_obj, "bulletPreset": bullet_preset}}]}
|
|
678
|
+
response = await self._apost(url, data=batch_update_data)
|
|
696
679
|
return self._handle_response(response)
|
|
697
680
|
|
|
698
|
-
def delete_paragraph_bullets(
|
|
699
|
-
self,
|
|
700
|
-
document_id: str,
|
|
701
|
-
start_index: int,
|
|
702
|
-
end_index: int,
|
|
703
|
-
segment_id: str = None,
|
|
704
|
-
tab_id: str = None,
|
|
681
|
+
async def delete_paragraph_bullets(
|
|
682
|
+
self, document_id: str, start_index: int, end_index: int, segment_id: str = None, tab_id: str = None
|
|
705
683
|
) -> dict[str, Any]:
|
|
706
684
|
"""
|
|
707
|
-
Removes bullet points or numbering from paragraphs within a specified range in a Google Document. This
|
|
685
|
+
Removes bullet points or numbering from paragraphs within a specified index range in a Google Document. This reverts list formatting to normal text while preserving content, acting as the inverse operation to the `apply_list_style` function.
|
|
708
686
|
|
|
709
687
|
Args:
|
|
710
|
-
document_id: The unique identifier of the Google Document to be updated
|
|
711
|
-
start_index: The zero-based start index of the range to remove bullets from
|
|
712
|
-
end_index: The zero-based end index of the range to remove bullets from (exclusive)
|
|
713
|
-
segment_id:
|
|
714
|
-
tab_id:
|
|
688
|
+
document_id: The unique identifier of the Google Document to be updated.
|
|
689
|
+
start_index: The zero-based start index of the range to remove bullets from.
|
|
690
|
+
end_index: The zero-based end index of the range to remove bullets from (exclusive).
|
|
691
|
+
segment_id: Optional segment ID specifying a subset of the document where the range applies.
|
|
692
|
+
tab_id: Optional tab ID specifying a particular tab within the document where the range applies.
|
|
715
693
|
|
|
716
694
|
Returns:
|
|
717
|
-
A dictionary containing the Google Docs API response after performing the delete bullets operation
|
|
695
|
+
A dictionary containing the Google Docs API response after performing the delete bullets operation.
|
|
718
696
|
|
|
719
697
|
Raises:
|
|
720
|
-
HTTPError:
|
|
721
|
-
RequestException:
|
|
698
|
+
HTTPError: Raised when the API request fails due to invalid document ID, insufficient permissions, or other server-side errors.
|
|
699
|
+
RequestException: Raised when there are network connectivity issues or problems accessing the API endpoint.
|
|
722
700
|
|
|
723
701
|
Tags:
|
|
724
702
|
bullets, delete, remove, list, paragraph, document, api, google-docs, batch, content-management
|
|
725
703
|
"""
|
|
726
704
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
|
727
|
-
|
|
728
|
-
# Build the range object
|
|
729
705
|
range_obj = {"startIndex": start_index, "endIndex": end_index}
|
|
730
|
-
|
|
731
|
-
# Add optional parameters if provided
|
|
732
706
|
if segment_id is not None:
|
|
733
707
|
range_obj["segmentId"] = segment_id
|
|
734
708
|
if tab_id is not None:
|
|
735
709
|
range_obj["tabId"] = tab_id
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
"requests": [{"deleteParagraphBullets": {"range": range_obj}}]
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
response = self._post(url, data=batch_update_data)
|
|
710
|
+
batch_update_data = {"requests": [{"deleteParagraphBullets": {"range": range_obj}}]}
|
|
711
|
+
response = await self._apost(url, data=batch_update_data)
|
|
742
712
|
return self._handle_response(response)
|
|
743
713
|
|
|
744
714
|
def list_tools(self):
|
|
745
715
|
return [
|
|
746
716
|
self.create_document,
|
|
747
|
-
self.
|
|
717
|
+
self.get_document_content,
|
|
748
718
|
self.insert_text,
|
|
749
719
|
self.apply_text_style,
|
|
750
720
|
self.delete_content_range,
|