谷歌日历
此包通过 Google Calendar API 提供代理事件列表、创建、更新、删除、日历发现和自由时间查询 googleapis 和OAuth2号卫星。 关于 ./reader 子路径 它给一个主机 , 它会保留它自己的授权 fetch:窗口读取,递增读取,由id读取,事件形状和会场链接候选人. 同样的子路径 伴随着流 使拨款, GoogleCalendarOAuthFlow: 一个只读事件范围 openid 财务报告和审定财务报表 email{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}在交换处和每一次刷新时 都保持着.
安装
npm install @framers/agentos-ext-calendar-google @framers/agentos @framers/agentos-ext-account-sources
同伴依赖性 : @framers/agentos 财务报告和审定财务报表 @framers/agentos-ext-account-sources,每层或以上 peerDependencies 名称; npm view @framers/agentos-ext-calendar-google peerDependencies 打印最新发布的版本。 补助金 ./reader 运行在驱动器的流量(@framers/agentos-ext-google-drive这包的依赖性 两者兼具 所以 ./reader 需要同时安装, 即使在一个只使用其读取的宿主。 该软件包是一个 ES 模块: 导入它; a CommunityJS require() 而不获支持.
使用量
import { AgentOS } from '@framers/agentos';
const agentos = await AgentOS.create({
extensionManifest: {
packs: [
{
package: '@framers/agentos-ext-calendar-google',
options: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
refreshToken: process.env.GOOGLE_REFRESH_TOKEN || process.env.GOOGLE_CALENDAR_REFRESH_TOKEN,
},
},
],
},
});
配置
| 选项 | 秘密编号 | 环境变量 | 需求 | 默认 |
|---|---|---|---|---|
clientId | google.clientId | GOOGLE_CLIENT_ID | 对 | 无默认 |
clientSecret | google.clientSecret | GOOGLE_CLIENT_SECRET | 对 | 无默认 |
refreshToken | google.refreshToken | GOOGLE_REFRESH_TOKEN,则 GOOGLE_CALENDAR_REFRESH_TOKEN | 对 | 无默认 |
accessToken | 没有 | 无标志 | ||
priority | 没有 | 50 | ||
secrets | 没有 | 无地图 | ||
A. 背景情况 logger | 没有 | 无日志 |
在非空证书选项之前 options.secrets,然后按显示的顺序进行环境回落. accessToken 从选项直接读取。 日志接收激活和停用信息 .
工具
| 工具 | 它会做什么 |
|---|---|
calendarListEvents | 以时间范围列出事件,包括摘要,时间,地点和参与者. |
calendarCreateEvent | 创建包含时间、描述、位置和参与者的事件. |
calendarUpdateEvent | 更新现有事件的提供字段. |
calendarDeleteEvent | 用 ID 删除一个事件. |
calendarFindFreeTime | 查询日历的可用性, 并返回符合要求的持续时间的开放槽 . |
calendarListCalendars | 列出带有ID,姓名和时区的可访问日历. |
calendarListEvents
| 参数 | 类型 | 需求 | 说明 |
|---|---|---|---|
calendarId | 字符串 | 没有 | 用于查询的日历 ID (默认为“ 主要”) |
timeMin | 字符串 | 没有 | 以 ISO 8601 格式开始时间范围( 如 “ 2025-01-15 T09: 00: 00Z ”) |
timeMax | 字符串 | 没有 | ISO 8601格式的结束时间范围(例如"2025-01-15T17:00Z") |
maxResults | 编号 | 没有 | 返回的最大事件数( 默认 10, 最多 250) |
calendarCreateEvent
| 参数 | 类型 | 需求 | 说明 |
|---|---|---|---|
calendarId | 字符串 | 没有 | 在(默认为"主")中创建事件的日历 ID |
summary | 字符串 | 对 | 活动名称/摘要 |
start | 字符串 | 对 | 以ISO 8601格式(如"2025-01-15T09:00-05:00")开始日期时间 |
end | 字符串 | 对 | 以ISO 8601格式(如"2025-01-15T10:00-05:00")结束日期时间 |
description | 字符串 | 没有 | 事件简介或说明 |
location | 字符串 | 没有 | 事件地点(地址或地名) |
attendees | 字符串数组 | 没有 | 参与者电子邮件地址阵列 |
timeZone | 字符串 | 没有 | IANA时区(如"American/New York"). 用于启动/ 结束( 如果没有嵌入) . |
calendarUpdateEvent
| 参数 | 类型 | 需求 | 说明 |
|---|---|---|---|
calendarId | 字符串 | 没有 | 包含该事件的日历 ID( 默认为“ 主要 ” ) |
eventId | 字符串 | 对 | 要更新的事件标识 |
summary | 字符串 | 没有 | 更新事件标题/摘要 |
start | 字符串 | 没有 | 以 ISO 8601 格式更新的开始时间 |
end | 字符串 | 没有 | 以 ISO 8601 格式更新的结束日期 |
description | 字符串 | 没有 | 更新事件描述 |
location | 字符串 | 没有 | 更新事件位置 |
timeZone | 字符串 | 没有 | IANA 起始/结束的时区(例如"American/New York") |
calendarDeleteEvent
| 参数 | 类型 | 需求 | 说明 |
|---|---|---|---|
calendarId | 字符串 | 没有 | 包含该事件的日历 ID( 默认为“ 主要 ” ) |
eventId | 字符串 | 对 | 要删除的事件的标识 |
calendarFindFreeTime
| 参数 | 类型 | 需求 | 说明 |
|---|---|---|---|
calendarIds | 字符串数组 | 没有 | 要检查的日历ID( 默认为 ["主"]) |
timeMin | 字符串 | 对 | 以 ISO 8601 格式启动搜索窗口 |
timeMax | 字符串 | 对 | ISO 8601格式搜索窗口结束 |
durationMinutes | 编号 | 对 | 以分钟计的自由时间段的最小期限 |
calendarListCalendars
输入方案没有参数.
凭自己的资助阅读
@framers/agentos-ext-calendar-google/reader 阅读带有访问符号的日历,主机用品,通过 fetch。它不会装入 googleapis 或上述工具.
import { GoogleCalendarReader, meetingLinkCandidates } from '@framers/agentos-ext-calendar-google/reader';
const reader = new GoogleCalendarReader({ accessToken: async () => grant.accessToken() });
// The windowed read: every page of the next seven days, and the last page's sync token.
const now = new Date();
const week = await reader.readWindow({
calendarId: 'primary',
timeMin: now,
timeMax: new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000),
pageSize: 250,
maxPages: 10,
});
for (const event of week.events) {
console.log(event.id, event.start?.dateTime, meetingLinkCandidates(event));
}
// The incremental read: what changed since the token, whatever its dates; a 410 answers gone.
if (week.complete && week.nextSyncToken !== null) {
const changes = await reader.readChanges({ calendarId: 'primary', syncToken: week.nextSyncToken, pageSize: 250, maxPages: 10 });
if (changes.gone) {
// Google refused the token: clear it and read the window again.
} else {
for (const event of changes.events) {
if (event.status === 'cancelled') console.log('ended', event.id);
}
}
}
// One event by its id; a 404 or a 410 answers gone.
const read = await reader.readEvent({ calendarId: 'primary', eventId: 'fixtureevent1' });
每页 readWindow 财务报告和审定财务报表 readChanges 使用 singleEvents=true,从不 orderBy, (中文(简体) ), timeMin 或者说 timeMax 在同步标志旁边; readEvent 自谷歌以来, 没有发送查询 events.get 采取不 singleEvents。读取剪接 maxPages 答题 complete: false 没有任何迹象. onPage 在读取每一页之后运行, 在询问下一页之前运行, 所以一个主机可以续签那里的租赁 .
mapCalendarEvent(raw) 给出事件的形状: 实例的 id 及其 系列' (recurringEventId),状态, start 财务报告和审定财务报表 end 以其所在区域或全天为一瞬间, originalStartTime 对于已移动或已取消的实例, organizerSelf,则 guests 与他们的 self, (中文(简体) ), resource 财务报告和审定财务报表 organizer 旗帜及其 answer, (中文(简体) ), guestsOmitted,会议 video 其解决办法的切入点, location, (中文(简体) ), description, (中文(简体) ), summary 财务报告和审定财务报表 updated。一个视频输入点的地址不解析为 HTTPS 和 主机的读取无效。 一个已取消的序列实例带有它的 id,它的 series' id 和它的最初开始和没有时间;一个被删除的事件的 id 单独;其他每个字段读作无效或空. 尸体没有标识图 null。 。 。 .
meetingLinkCandidates(event) 回答会议地址,以便:会议有视频进入点时单独输入;否则,“会议”和“小组”处理地点名称,然后处理描述名称,每次一次。 地址仅持有可打印的ASCII:它以空白,控制字符,引文,括号或ASCII过后的任何字符为结尾,如卷曲引文,意识形态逗号或emoji,服务都不在其地址中写作. 句子结束的句子., (中文(简体) ), ,, (中文(简体) ), ;, (中文(简体) ), :, (中文(简体) ), ! 财务报告和审定财务报表 ?)从尾而去. 位置和描述被读取为HTML写作: 字符引用读取为它所取名的字符. 一个人物,地址在它,所以 ?, (中文(简体) ), ? 财务报告和审定财务报表 ? 改为 ?,以及 &, (中文(简体) ), & 财务报告和审定财务报表 & 作为 &。提及空白、控制字符、引号或括号,例如: , (中文(简体) ), " 或者说 <,以该字符结尾的地址,以命名的方式提及任何其他字符和未命名字符的编号;在这种引用之后写好的地址作为下一个. hangoutLink 永远不读。 一个主机让第一个候选人 自己的机器人供应商接受.
失败就是失败 CalendarReadFault 谁 reason 是一个固定的单词, Google 的文本从未携带过; 它的信息是 calendar_read_<reason>数字 :
| 原因 | 何时 |
|---|---|
refused | 401或403个没有比例或配额的名字 |
limited | 429或403 命名一个比率或配额(rateLimitExceeded, (中文(简体) ), userRateLimitExceeded, (中文(简体) ), quotaExceeded, (中文(简体) ), dailyLimitExceeded(中文(简体) ) |
failed | 任何其他的答案,网络故障,不是JSON的机体,或者页面格式错误 |
timeout | 一个过去电话 deadlineMs (默认为一万),从等待其符号到最后的回答字节 |
too_large | 过去的答案 maxBytes (默认情况下为8,388,608) |
cancelled | 打电话的 signal 在接到电话之前 或在等待其信使时 在Google的回答或身体上中止 |
configuration | 输入错误, 绑定或地址 |
截止时间和信号 保持无论象征性供应商, fetchImpl 或答者听从他们:在停站之后发出的一种迹象,是永不降临的;在停止之后发出的一个迹象,是永不朗诵的。 错误 accessToken 供应商投掷是东道主自己的,例如拒绝赠款或刷新另一个流程,然后通过抛出,从不作为 CalendarReadFault。 。 。 .
readChanges 答题 { gone: true } 410,还有 readEvent 404或410。 两者都不行.
这个 api 选项名称。 只在CI上使用(CI=true在回转时或 .invalid 主机, 没有用户信息、 查询或片段, 在回转主机上覆盖 HTTPS 或 plain HTTP ; 任何其他地址都丢 configuration。 。 。 .
补助金
GoogleCalendarOAuthFlow在同一个子路径上,是Google为人物日历提供的赠款: Drive包 GoogleOAuthFlow (单位:千美元)@framers/agentos-ext-google-drive根据日历的规定, calendarGrant它问一个只读的事件范围, https://www.googleapis.com/auth/calendar.events.owned.readonly ("看到你拥有的Google日历上的事件") 默认或 https://www.googleapis.com/auth/calendar.events.readonly ("阅所历事 scope 选项,使用 openid 财务报告和审定财务报表 email,离线并征得同意,不增加范围. 补助金只有在其范围恰到好处时,在交换和每次刷新时才算数.
import { GoogleCalendarOAuthFlow, GoogleCalendarReader } from '@framers/agentos-ext-calendar-google/reader';
const callback = 'https://app.example.com/calendar/google/callback';
// The request that sends the person to Google: keep the state and the verifier until they come back.
const begun = new GoogleCalendarOAuthFlow({ clientId, clientSecret }, null).beginCalendar(callback);
// The request Google sends the person back to. `store` is an IOAuthTokenStore, such as the auth module's
// SealedTokenStore under the connection's namespace.
const flow = new GoogleCalendarOAuthFlow({ clientId, clientSecret }, store);
const tokens = await flow.complete({ code, state, expectedState: begun.state, codeVerifier: begun.codeVerifier, redirectUri: callback });
const address = tokens.metadata?.email; // the address the grant was made for, read from the ID token; the store never sees it
await flow.keep(connectionId, tokens);
// Later: an access token for the reader, refreshed one at a time a key; and the grant's end.
const reader = new GoogleCalendarReader({ accessToken: () => flow.accessToken(connectionId) });
await flow.forget(connectionId); // revokes the kept refresh token at Google's revocation address and clears the grant
complete 以 metadata.email,则指该符号终点的答案名称的地址ID标志,小写. idTokenAccount(idToken, clientId, now) 读取该信物的主张并拒绝,因为 GoogleOAuthFault invalid_response发行者不是Google的 听众不是客户 而是授权方azp),当存在时,是另一个客户端,其过期时间不是现在的有限数字,地址未经核实或缺失,或者地址缺失或变形(OpenID Connect Core 1.0, 第3.1.3.7节, 第3和5项拒绝第二受众和另一当事人);签名没有被检查,因为从指针终点本身收到的一个指针由连接的TLS(OpenID Connect Core 1.0, 第3.1.3.7节, 第6项)验证. keep 将刷新符号和瞄准镜交给商店 永远不要地址、访问标志或ID标志.
在交易所拒绝发放缺少范围、额外持有一个或缺少刷新信号的赠款(GoogleOAuthFault scope 或者说 refresh_token); 刷新器,其答案名称在集外显示 scope,一个名字,没有人保留保存的设定. revoke(token) 当 Google 撤销已过期或被撤销的令牌或解答时, 将其张贴到 Google 的撤销地址并解决; 任何其他拒绝都是 Auth 模块的 OAuthGrantRefused。流的选项是 Drive 包的(fetchImpl, (中文(简体) ), signal 单凭CI就站着 endpoints与 scope 替换 grant它的缺点是驱动器包 GoogleOAuthFault,从这个子路径导出, 所以一个主机安装这个包 从这里捕捉他们。 非对象的选项, 如在其位置上给出的抓取, 以及两个抛出以外的范围 configuration。 。 。 .
页:1
软件包需要节点.js >=22缺少所需的 OAuth 证书使工厂投掷,即使 accessToken 提供。 激活初始化了OAuth客户端;服务操作需要初始化. 包也登记 googleCalendarService 与善良 productivity。 。 。 .
事件创建、更新和删除更改所选日历 。 创建和更新发送 start 财务报告和审定财务报表 end 作为 dateTime 字段。 应用更新工具 timeZone 仅与供应 start 或者说 end。参与者被创建工具接受;更新工具没有参与者参数.
事件列表默认为 primary,按起始时间和上限命令事件 maxResults 时间 250时空搜索默认值 calendarIds 改为 primary,将重叠的繁忙间隔合并,并返回符合最小期限的全部空白。 工具失败返回 success: false 还有一个 error 留言.
释放
新版本发表于 架设层/剂-外延 由 GitHub Actions 通过 npm 信任的出版, 并附有出处声明 .
许可证
阿帕奇 - 2.0