-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #135 from scombz-utilities/feature/google-classroo…
…m-api Google Classroom連携機能
- Loading branch information
Showing
14 changed files
with
372 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
CRX_PUBLIC_KEY="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import json | ||
import os | ||
|
||
|
||
# chrome向けビルド以外のmanifest.jsonから、keyとoauth2とidentityの設定を削除する | ||
|
||
|
||
def afterBuild(): | ||
|
||
build_dirs = [ | ||
d | ||
for d in os.listdir("build") | ||
if "prod" in d and os.path.isdir(os.path.join("build", d)) and "chrome" not in d | ||
] | ||
|
||
for build_dir in build_dirs: | ||
manifest_path = os.path.join("build", build_dir, "manifest.json") | ||
with open(manifest_path, "r") as f: | ||
manifest = json.load(f) | ||
# keyとoauth2とidentityの設定を削除 | ||
manifest.pop("key", None) | ||
manifest.pop("oauth2", None) | ||
# permissionsからidentityを削除 | ||
if "permissions" in manifest: | ||
manifest["permissions"] = [ | ||
p for p in manifest["permissions"] if p != "identity" | ||
] | ||
with open(manifest_path, "w") as f: | ||
json.dump(manifest, f) | ||
|
||
print(f"Removed done: {manifest_path}") | ||
|
||
|
||
if __name__ == "__main__": | ||
afterBuild() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import type { Saves } from "~settings"; | ||
import { defaultSaves } from "~settings"; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export const getClasses = async (sendResponse?: (response: any) => void) => { | ||
try { | ||
console.log("getClasses Start"); | ||
|
||
// トークンを取得 | ||
const token = await new Promise((resolve, reject) => { | ||
chrome.identity.getAuthToken({ interactive: true }, (token) => { | ||
if (chrome.runtime.lastError || !token) { | ||
reject(chrome.runtime.lastError || "トークン取得に失敗しました。"); | ||
} else { | ||
resolve(token); | ||
} | ||
}); | ||
}); | ||
|
||
// メールアドレスを取得 | ||
const profileResponse = await fetch("https://www.googleapis.com/oauth2/v1/userinfo", { | ||
headers: { Authorization: `Bearer ${token}` }, | ||
}); | ||
const profile = await profileResponse.json(); | ||
console.log("profile", profile); | ||
|
||
if (sendResponse) { | ||
sendResponse({ profile }); | ||
} | ||
|
||
// クラス一覧を取得 | ||
const coursesResponse = await fetch("https://classroom.googleapis.com/v1/courses", { | ||
headers: { Authorization: `Bearer ${token}` }, | ||
}); | ||
const courses = await coursesResponse.json(); | ||
|
||
// 各クラスの課題を取得 | ||
const courseWorkResponses = await Promise.all( | ||
(courses.courses || []).map((course) => | ||
fetch(`https://classroom.googleapis.com/v1/courses/${course.id}/courseWork`, { | ||
headers: { Authorization: `Bearer ${token}` }, | ||
}), | ||
), | ||
); | ||
|
||
console.log("wait courseWorkResponses"); | ||
const courseWorks = await Promise.all(courseWorkResponses.map((response) => response.json())); | ||
|
||
const tasks = []; | ||
const now = new Date(); | ||
|
||
courseWorks.forEach((courseWork, index) => { | ||
const course = courses.courses[index]; | ||
console.log(courseWork); | ||
|
||
courseWork.courseWork.forEach(async (work) => { | ||
if (!work.dueDate) return; | ||
const dueDate = new Date( | ||
work.dueDate.year, | ||
work.dueDate.month, | ||
work.dueDate.day, | ||
work.dueTime?.hours ?? 23, | ||
work.dueTime?.minutes ?? 59, | ||
); | ||
if (dueDate < now) return; | ||
|
||
tasks.push({ | ||
kind: "classroomTask", | ||
course: course.name, | ||
courseId: work.courseId, | ||
courseURL: course.alternateLink, | ||
title: work.title, | ||
link: work.alternateLink, | ||
deadline: `${work.dueDate.year}-${work.dueDate.month}-${work.dueDate.day} ${work.dueTime?.hours ?? 23}:${work.dueTime?.minutes ?? 59}`, | ||
id: work.id, | ||
}); | ||
}); | ||
}); | ||
|
||
const submissionResponse = await Promise.all( | ||
tasks.map((task) => | ||
fetch(`https://classroom.googleapis.com/v1/courses/${task.courseId}/courseWork/${task.id}/studentSubmissions`, { | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}), | ||
), | ||
); | ||
|
||
const submissionsData = await Promise.all(submissionResponse.map((response) => response.json())); | ||
|
||
console.log(submissionsData); | ||
|
||
const submissions = submissionsData.map((data) => data.studentSubmissions || []); | ||
|
||
const noSubmittedTasks = tasks.map((task, index) => { | ||
return { | ||
isSubmitted: !submissions[index] | ||
.map((submission) => ["CREATED", "RECLAIMED_BY_STUDENT"].includes(submission.state)) | ||
.some(Boolean), | ||
...task, | ||
}; | ||
}); | ||
|
||
console.log("noSubmittedTasks", noSubmittedTasks); | ||
|
||
chrome.storage.local.get(defaultSaves, (currentData: Saves) => { | ||
currentData.scombzData.classroomTasklist = noSubmittedTasks.filter((task) => !task.isSubmitted); | ||
chrome.storage.local.set(currentData, () => { | ||
console.log("classroomTasklist saved"); | ||
}); | ||
}); | ||
console.log("getClasses End"); | ||
} catch (error) { | ||
console.error("課題取得エラー:", error); | ||
sendResponse({ error }); | ||
} | ||
}; | ||
|
||
export const logoutGoogle = () => { | ||
chrome.identity.clearAllCachedAuthTokens(() => { | ||
console.log("removed cache"); | ||
}); | ||
const url = chrome.identity.getRedirectURL(); | ||
console.log("logoutGoogle", url); | ||
chrome.tabs.create({ url: `https://accounts.google.com/logout` }); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.