Agentero
Connect your own Agent, keep research context in a local Vault. Seamlessly migrate from Zotero, read, understand, link, and reuse your research context.
AI translation
스마트캠퍼스 과제를 마감 순으로 모아 보는 과제 플래너
Translation pending
ProductivityJavaScript · PLpgSQLGitHub @eunchan96OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗스마트캠퍼스 과제, 직접 적은 과제, 시험 일정을 마감 순으로 모아 보는 학기 플래너입니다. 단독 웹으로도, 노션 페이지에 임베드해서도 씁니다. 같은 보드 코드를 입력한 기기끼리 과제가 동기화됩니다.
main push 시 자동 배포)보기
과제
시험
스마트캠퍼스 강의 영상 (할 일)
기타 일정 (할 일 · 휴강 등)
T는 기타 · 할 일로 열림)과목 줄임말 · 짧은 이름
공부 중 알림 (폰)
새 과제 알림
스마트캠퍼스 공지
미제출
캘린더로 보내기
calendar-feed Edge Function, 읽기 전용 열쇠, 새로 만들면 이전 주소는 막힘).반복
노션 간단 모드
?compact를 붙이면 다가오는 일정 6개만 크게 보여요. 노션 임베드용.마감 알림
공부 모드 (왼쪽 위 일정 공부 글자, 단축키 S)
오늘 · 내일 · 이번 주로 내일이나 이번 주(모레~7일 뒤) 중 고른 날에 넣어 두면 그날 오늘 공부에 나와요. 지난 7일 안에 넣고 못 한 계획은 오늘 공부 아래 "지난 계획"으로 흐리게 나오고 ← 버튼으로 오늘로 옮겨요친구 버튼(공부 중인 친구 수, 받은 신청이 있으면 +N). 닉네임을 정하면 친구 코드(XXXX-XXXX)가 생기고, 친구 코드로 신청 → 상대가 수락하면 서로 친구가 돼요 (서로 신청하면 바로). 오늘 공부 시간과 지금 공부 중인지만 보이고 과목 · 계획은 안 보여요. 친구를 끊으면 양쪽에서 함께 지워져요. 코드를 새로 만들면 이전 코드로는 신청할 수 없어요떠 있는 타이머
친구 랭킹
폰 홈 화면 위젯
upcoming 60), 안드로이드는 위젯 앱에서 위젯마다 따로widgets/ios/S-DAY.js). 홈 화면 · 잠금 화면 위젯. 위젯 편집의 Parameter에 study · timer · upcoming을 적으면 한 스크립트로 다른 종류도 돼요widgets/android의 위젯 앱 (GitHub Actions가 빌드해서 Releases의 android-widget에 S-DAY-widget.apk로 올림). 앱에 위젯 주소를 붙여 넣고 홈 화면에서 S-DAY 위젯 세 가지 중 골라 추가분류 (학기 · 기간 · 넓은 의미의 과목)
지금(오늘이 기간 안에 드는 분류 + 기간 없는 분류를 모두 합쳐서) · 분류 하나 · 미분류(어느 분류에도 없는 것) · 전체, 맨 아래 분류 관리. 폰에서는 필터 안의 칩+ 과목 추가로 새 과목찾기
/, Esc로 닫기), 과목 필터, 완료 숨기기, 중요한 과제만 보기그 밖에
S 일정 ↔ 공부, 1 2 탭(목록 · 캘린더 / 오늘 · 기록), N 새 과제, E 새 시험, T 새 할 일, / 검색, 공부 · 오늘에서 Space 타이머 시작 · 끝내기, Esc 닫기index.html 화면 뼈대 (연결 화면, 앱, 상세 패널, 설정)
assets/style.css 디자인 토큰과 스타일 (흰 바탕 + 형광펜 콘셉트)
assets/js/app.js 시작, 화면 그리기, 이벤트, 단축키
assets/js/views.js 목록 / 캘린더 보기
assets/js/store.js 상태, 낙관적 업데이트, 동기화, 되돌리기 삭제
assets/js/api.js Supabase RPC와 Edge Function 호출, 오류 문구
assets/js/util.js 날짜·학기 계산, 과목 색, DOM 헬퍼
assets/js/canvas.js 스마트캠퍼스 데이터 변환, 북마클릿
assets/js/picker.js 달력, 시계 다이얼
assets/js/push.js 마감 알림 켜기 / 끄기
assets/js/subject-picker.js 과목 고르기 (색 점 목록, 찾기, 새 과목 추가)
assets/js/study.js 공부 모드 (오늘: 타이머 · 계획 · 타임라인, 기록: 주간 · 월간, 친구)
sw.js, manifest.webmanifest PWA (캐시, 알림 표시, 바로가기)
supabase/migrations/ DB 스키마와 함수
supabase/functions/canvas-sync/ 스마트캠퍼스 피드 동기화
supabase/functions/push-notify/ 마감 알림 · 한 번짜리 알림 발송 (10분마다)
supabase/functions/calendar-feed/ 캘린더 구독용 .ics
브라우저 (노션 임베드 / 모바일 브라우저)
│ POST /rest/v1/rpc/dday_* (publishable key + 보드 코드)
│ POST /functions/v1/canvas-sync (보드 코드)
▼
Supabase
├─ public.dday_* 함수 ← 외부에서 호출 가능한 입구
├─ Edge Function canvas-sync ← Canvas 피드를 읽어 병합
├─ pg_cron ← 하루 3번 canvas-sync 실행
└─ app 스키마 (boards, tasks) ← API 비노출, 직접 접근 차단
보드마다 두 가지 중 하나로 자동 연동합니다. 둘 다 canvas-sync Edge Function이 하루 3번(07:03, 13:03, 21:03 KST), 그리고 상단 새로고침 버튼을 누르면 바로 실행합니다 (다른 기기 변경 사항도 함께 불러옴).
스마트캠퍼스 계정 → 설정 → 승인된 통합 → + 새 액세스 토큰에서 만든 토큰을 설정에 붙여 넣으면, 서버가 Canvas REST API로 직접 읽습니다.
GET /api/v1/courses?enrollment_state=active&enrollment_type=student → 과목별 GET /api/v1/courses/:id/assignments?include[]=submissiontoken_invalid로 기록하고, 화면 위쪽 안내와 함께 알림을 켠 기기로 한 번 알려 줍니다.https://호스트만, IP · localhost 안 됨)를 바꾸면 그 주소로 동기화합니다 (boards.canvas_api_origin, 기본 https://canvas.ssu.ac.kr). 토큰도 그 학교 것이어야 하고, 강의 영상은 learningx를 쓰는 학교만 가져옵니다.sessionless_launch를 열어 learningx가 주는 임시 쿠키를 받고 GET /learningx/api/v1/courses/:id/modules?include_detail=true에서 영상 항목(attendance_item)의 기한과 시청 완료 여부를 읽습니다. 임시 쿠키는 실행 중 메모리에만 두고 저장하지 않습니다. 진도를 세지 않는 영상(omit_progress)은 봤는지 알 수 없어서 넣지 않고, 새로 넣는 건 아직 안 봤고 기한이 남은 것만입니다.스마트캠퍼스 캘린더 화면의 "캘린더 피드" 주소(…/feeds/calendars/user_….ics)를 등록하면 피드를 읽어 과제를 넣습니다. 토큰을 쓰지 않을 때의 대안입니다.
UID:event-assignment-*인 항목만 과제로 봅니다.SUMMARY의 과제명 [과목명 (학수번호)]를 과제명과 과목으로 나눕니다.*_custom 플래그로 기억해 이후 동기화가 덮어쓰지 않습니다.토큰을 쓰지 않을 때 피드의 30일 제한과 제출 정보 부족을 보완하려고, 설정에 "D-day로 가져오기" 북마클릿을 둡니다. 토큰을 연결하면 이 항목은 숨깁니다.
/api/v1/courses와 과목별 /api/v1/courses/:id/assignments?include[]=submission을 모읍니다. 토큰이 필요 없습니다.postMessage로 데이터를 넘기고, 앱에서 미리 보기 후 dday_canvas_import로 병합합니다./api/v1/planner/items)를 브라우저에서 열어 저장한 파일을 올려도 됩니다. 이 경우 파일 이름 없이 제출 여부까지만 가져옵니다.피드 주소는 로그인 없이 일정을 볼 수 있는 개인 주소라서, DB의 잠긴 스키마에만 저장하고 API로 다시 읽어 갈 수 없게 했습니다. 예약 실행 인증값은 Supabase Vault에 둡니다.
처음에는 노션 HTML 블록에 파일을 직접 넣었지만, 블록이 샌드박스 iframe으로 렌더링되면서 두 가지가 막혔습니다.
<form> 제출이 동작하지 않음 → 폼 태그 대신 버튼 클릭 이벤트로 처리fetch가 차단됨 → 위젯을 Vercel에 올리고 노션에서는 URL 임베드로 표시로그인 없이 쓰기 위해 보드 코드가 곧 열쇠인 구조입니다.
app 스키마에 두고, anon/authenticated 역할의 접근 권한을 모두 회수했습니다. RLS도 켜 두고 정책은 두지 않았습니다.SECURITY DEFINER 함수 5개만 실행할 수 있고, 각 함수는 보드 코드를 검증한 뒤 해당 보드의 데이터만 다룹니다.Supabase 보안 어드바이저는 "로그인 없이 실행 가능한 SECURITY DEFINER 함수" 경고를 띄우는데, 위 구조상 의도된 것입니다.
모든 함수는 POST {SUPABASE_URL}/rest/v1/rpc/{함수명}으로 호출하고, 헤더에 apikey를 넣습니다.
| 함수 | 인자 | 반환 | 설명 |
|---|---|---|---|
dday_create_board | 없음 | text | 새 보드를 만들고 코드 반환 |
dday_list | p_code | jsonb 배열 | 보드의 과제 목록 (마감 순) |
dday_upsert | p_code, p_task | jsonb | 과제 추가 또는 수정 |
dday_delete | p_code, p_id | 없음 | 과제 삭제 (스마트캠퍼스 과제는 숨김) |
dday_import | p_code, p_tasks | int | 여러 과제 일괄 추가 (이미 있는 id는 건너뜀) |
dday_set_canvas_feed | p_code, p_url | jsonb | 피드 주소 등록, 빈 값이면 해제 |
dday_set_canvas_token | p_code, p_token | jsonb | 액세스 토큰 등록 (Vault에 저장), 빈 값이면 해제 |
dday_canvas_status | p_code | jsonb | 연동 여부(feed, token, tokenHint), 마지막 동기화 시각, 오류 |
dday_push_subscribe | p_code, p_sub, p_leads | jsonb | 이 기기 알림 켜기 또는 알림 시점 변경 (p_sub은 PushSubscription.toJSON(), p_leads는 분 단위) |
dday_push_unsubscribe | p_code, p_endpoint | 없음 | 이 기기 알림 끄기 |
dday_push_status | p_code, p_endpoint | jsonb | 이 기기 알림 상태와 알림 시점 |
dday_study | p_code, p_from | jsonb | 공부 기록(p_from 이후, 최대 40일), 날짜별 합계(400일), 최근 계획, 하루 목표, 프로필 |
dday_svc_* 함수는 Edge Function(service_role) 전용이라 외부에서 호출할 수 없습니다.
dday_upsert의 memo, starred는 보내지 않으면 기존 값을 유지합니다.
Edge Function POST {SUPABASE_URL}/functions/v1/canvas-sync에 { "code": "<보드 코드>" }를 보내면 그 보드를 바로 동기화하고 { added, updated, total }을 돌려줍니다.
과제 형식:
{ "id": "lzx1a2b3", "subject": "데이터베이스", "title": "ER 다이어그램", "due": "2026-10-20T14:59:00.000Z", "done": false,
"memo": "", "starred": false, "source": "manual", "link": null, "doneAt": null, "createdAt": "…" }
Edge Function push-notify에 { "code", "endpoint" }를 보내면 그 기기로 테스트 알림을 보냅니다. 예약 실행(10분마다)은 x-cron-secret 헤더로 인증하고, 알림 시점이 지난 과제마다 가장 가까운 시점 하나만 보낸 뒤 기록합니다. VAPID 개인 키는 Vault(dday_vapid_private)에만 있고, 공개 키는 assets/js/push.js와 함수에 들어 있습니다.
오류는 invalid_code, too_many_tasks(보드당 500개 제한), invalid_import, invalid_feed_url, no_feed, feed_* 메시지로 돌아옵니다.
supabase/migrations/의 SQL을 순서대로 실행합니다. canvas_cron 마이그레이션의 함수 URL은 자기 프로젝트 ref로 바꿉니다.supabase/functions/canvas-sync와 push-notify를 Edge Function으로 배포합니다. 알림을 쓰려면 VAPID 키를 만들어(npx web-push generate-vapid-keys) 개인 키는 Vault에 dday_vapid_private로 넣고, 공개 키는 assets/js/push.js와 함수의 VAPID_PUBLIC에 넣습니다. 인증은 함수 안에서 보드 코드와 Vault 값으로 하므로 JWT 검증은 끕니다.assets/js/api.js 상단의 PROJECT(Supabase 프로젝트 주소)와 API_KEY(publishable key)를 자기 프로젝트 값으로 바꿉니다./embed로 그 주소를 넣습니다.빌드 과정은 없지만 ES 모듈을 쓰기 때문에 로컬에서는 python3 -m http.server처럼 간단한 서버로 열어야 합니다.
생각 중인 것:
boards.owner_id를 이용한 로그인 계정 연결dday_subject_colors / dday_set_subject_color | p_code, p_subject, p_color | jsonb | 바꾼 과목 색 목록 · 색 바꾸기(#RRGGBB, null이면 기본 색) |
dday_subject_prefs / dday_set_subject_order | p_code, p_order | jsonb | 과목 색 · 순서 · 직접 추가한 과목 함께 읽기 · 순서 저장(과목 이름 배열, 최대 200개) |
dday_set_custom_subjects | p_code, p_list | jsonb | 직접 추가한 과목 목록 저장 (최대 100개, 모든 기기에서 같게) |
dday_set_groups | p_code, p_data | jsonb | 분류 목록(groups), 과목 소속(members, "*"은 모든 분류), 쓰지 않는 과목(inactive), 삭제한 자동 학기(removed) 저장 |
dday_rename_subject | p_code, p_from, p_to | jsonb | 과목 이름 바꾸기 (과제 · 공부 기록 · 계획 · 색 · 순서 · 분류 소속까지, 스마트캠퍼스 원래 이름은 subject_aliases로 새 이름에 연결) |
dday_widget_key / dday_widget_status | p_code | text / boolean | 위젯 열쇠 새로 만들기(이전 열쇠는 막힘) · 있는지 |
dday_timer / dday_timer_set | p_code, p_state | jsonb | 기기 사이 타이머 상태 읽기 · 저장 (updatedAt이 더 새로울 때만 덮어씀) |
dday_study_range | p_code, p_from, p_to | jsonb 배열 | 기간 안의 공부 기록 (최대 45일, 기록 탭에서 예전 주 · 달) |
dday_study_add / dday_study_remove | p_code, 기록 / p_id | jsonb / 없음 | 공부 기록 저장(같은 id면 덮어씀) · 지우기(p_removed=false면 되돌리기) |
dday_study_plan / dday_study_plan_remove | p_code, 계획 / p_id | jsonb / 없음 | 공부 계획 저장 · 지우기 |
dday_study_goal | p_code, p_minutes | int | 하루 목표(분) |
dday_study_live | p_code, p_on | 없음 | 친구에게 "공부 중" 표시 (켜 두면 15분마다 연장, 끊기면 저절로 꺼짐) |
dday_study_profile / _profile_hide / _new_code | p_code, p_nickname | jsonb | 닉네임 정하기(친구 코드 생성) · 공개 그만하기 · 코드 새로 만들기 |
dday_friends / dday_friend_add / dday_friend_remove | p_code, p_friend_code | jsonb 배열 | 친구 목록(수락된 친구만: 닉네임, 오늘 · 이번 주 · 이번 달 초, 공부 중 시작 시각) · 신청(상대가 먼저 신청했으면 바로 친구) · 끊기 · 거절 · 신청 취소(양쪽 모두 지움) |
dday_friend_accept / dday_friend_requests | p_code, p_friend_code / p_code | jsonb | 받은 신청 수락 · 받은 신청과 보낸 신청 목록 |
dday_set_canvas_origin | p_code, p_origin | jsonb | 학교 LMS 주소 바꾸기 (빈 값이면 숭실대) |