diff --git a/src/extensions.tsp b/src/extensions.tsp index fcb0eb8..66991ed 100644 --- a/src/extensions.tsp +++ b/src/extensions.tsp @@ -2,3 +2,4 @@ namespace SolvedAC; alias XInternal = "x-internal"; scalar Color extends string; +alias TODO = unknown; diff --git a/src/models/Emoticon.tsp b/src/models/Emoticon.tsp new file mode 100644 index 0000000..ebd2e8f --- /dev/null +++ b/src/models/Emoticon.tsp @@ -0,0 +1,26 @@ +using TypeSpec.OpenAPI; + +namespace SolvedAC; + +/** + * 난이도 투표 등에 사용할 수 있는 이모티콘입니다. + */ +model Emoticon { + /** + * 고유 식별자입니다. + * @example "hanbyeol-01" + */ + emoticonId: string; + + /** + * 사진으로 가는 하이퍼링크입니다. + * @example "https://static.solved.ac/emoticons/fool.png" + */ + emoticonUrl: url; + + /** + * 한국어 이름입니다. + * @example "난 바보야" + */ + displayName: string; +} diff --git a/src/models/_barrel.tsp b/src/models/_barrel.tsp index 81f122e..0057532 100644 --- a/src/models/_barrel.tsp +++ b/src/models/_barrel.tsp @@ -24,3 +24,4 @@ import "./Item.tsp"; import "./Organization.tsp"; import "./OrganizationType.tsp"; import "./Ranked.tsp"; +import "./Emoticon.tsp"; diff --git a/src/openapi.yaml b/src/openapi.yaml deleted file mode 100644 index 5d530df..0000000 --- a/src/openapi.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# yaml-language-server: $schema=https://spec.openapis.org/oas/3.1/schema/2021-05-20 ---- -openapi: "3.1.0" - -paths: - /account/verify_credentials: - $ref: "./paths/account/verify_credentials.yaml#/paths/Path" - -components: - schemas: - IconScheme: - $ref: "./schemas/icon-scheme.yaml#/components/schemas/IconScheme" - Settings: - $ref: "./schemas/settings.yaml#/components/schemas/Settings" diff --git a/src/operations/account/_barrel.tsp b/src/operations/account/_barrel.tsp index 86f46b8..c9405cf 100644 --- a/src/operations/account/_barrel.tsp +++ b/src/operations/account/_barrel.tsp @@ -1,2 +1,3 @@ import "./redeem.tsp"; import "./update_settings.tsp"; +import "./verify_credentials.tsp"; diff --git a/src/operations/account/verify_credentials.tsp b/src/operations/account/verify_credentials.tsp new file mode 100644 index 0000000..c9b3873 --- /dev/null +++ b/src/operations/account/verify_credentials.tsp @@ -0,0 +1,183 @@ +/** + * @TODO: 반환에 성공한 경우 문서화하기 + */ +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace SolvedAC; +/** + * 현재 로그인한 계정 정보를 가져옵니다. + * + * **주의**: 로그인이 필요한 API는 사이트 내에서 호출할 수 없으므로 별도 도구를 이용해주십시오. + */ +@summary("로그인 정보 가져오기") +@tag("account") +@useAuth(TokenAuth) +@get +@route("/account/verify_credentials") +op verifyAccountCredentials( + /** + * 응답을 받을 언어입니다. + */ + @header + `x-solvedac-language`?: Language, +): Unauthorized | VerifyCredentials.Ok; + +namespace VerifyCredentials { + /** + * 리딤 코드가 올바르지 않은 경우입니다. + */ + @extension(XInternal, true) + model Ok { + @statusCode status: 200; + @body body: Credential; + } + + @extension(XInternal, true) + model Credential { + user: UserWithSettings; + aggredOn: Agreements; + + /** + * 보유할 수 있는 모든 이모티콘에 대해 이모티콘 정보에 덧붙여 보유 여부를 함께 담은 목록입니다. + * + * @example + * [ + * { + * "emoticonId": "hanbyeol-01", "emoticonUrl": "https://static.solved.ac/emoticons/fool.png", + * "displayName": "난 바보야", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-02", "emoticonUrl": "https://static.solved.ac/emoticons/lgtm.png", + * "displayName": "LGTM", "unlocked": false + * }, + * { + * "emoticonId": "hanbyeol-03", "emoticonUrl": "https://static.solved.ac/emoticons/real.png", + * "displayName": "ㄹㅇㅋㅋ", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-04", "emoticonUrl": "https://static.solved.ac/emoticons/why-work.png", + * "displayName": "이게 왜 됨?", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-05", "emoticonUrl": "https://static.solved.ac/emoticons/i-wont-do.png", + * "displayName": "응, 안 해", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-06", "emoticonUrl": "https://static.solved.ac/emoticons/overclock.png", + * "displayName": "두뇌풀가동!", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-07", "emoticonUrl": "https://static.solved.ac/emoticons/hello-world.png", + * "displayName": "Hello, World!", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-08", "emoticonUrl": "https://static.solved.ac/emoticons/i-hate-math.png", + * "displayName": "수학시러!", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-09", "emoticonUrl": "https://static.solved.ac/emoticons/am-i-screwed.png", + * "displayName": "망?했네?", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-10", "emoticonUrl": "https://static.solved.ac/emoticons/dont-decieve.png", + * "displayName": "기만ㄴㄴ", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-11", "emoticonUrl": "https://static.solved.ac/emoticons/i-hate-coding.png", + * "displayName": "코딩시러!", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-12", "emoticonUrl": "https://static.solved.ac/emoticons/thinking-face.png", + * "displayName": "흠터레스팅", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-13", "emoticonUrl": "https://static.solved.ac/emoticons/why-dont-work.png", + * "displayName": "이게 왜 안 됨?", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-14", "emoticonUrl": "https://static.solved.ac/emoticons/well-programmed.png", + * "displayName": "잘짰네ㅎ", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-15", "emoticonUrl": "https://static.solved.ac/emoticons/please-dont-explode.png", + * "displayName": "터지면 안대...", "unlocked": true + * }, + * { + * "emoticonId": "hanbyeol-16", "emoticonUrl": "https://static.solved.ac/emoticons/nooo.png", + * "displayName": "으에에~", "unlocked": false + * } + * ] + */ + emoticons: EmoticonUnlockStatus[]; + + bookmarks: TODO; + + /** + * 받은 알림 수입니다. + * @example 0 + */ + notificationCount: uint32; + + /** + * 마지막으로 솔브드 상태가 변한 시각입니다. + * @example "2024-03-17T19:24:42.000Z" + */ + lastSolvedStateChangedAt: offsetDateTime; + } + + /** + * 사용자 동의 여부입니다. + */ + model Agreements { + /** + * 동의한 약관 버전입니다. + * @example "tos_v1" + */ + tos: string; + + /** + * 동의한 개인정보 처리방침 버전입니다. + * @example "privacy_v2" + */ + privacy: string; + } + + @extension(XInternal, true) + model EmoticonUnlockStatus extends Emoticon { + /** + * 해금 여부입니다. + * @example true + */ + unlocked: boolean; + } + + @extension(XInternal, true) + @withVisibility("brief") + model UserWithSettings extends User { + /** + * 설정입니다. + */ + settings: UserSettings; + + /** + * 사용 중인 이메일 주소입니다. + * + * @example `"me@shiftpsh.com"` + */ + email: string; + } + + model UserSettings { + twitterPostOnProblemSolve: "true"; + screenTheme: "default"; + twitterPostHandle: "true"; + twitterPostOnRatingIncrease: "true"; + twitterPostOnTierIncrease: "true"; + twitterPostOnClassIncrease: "true"; + pro_hideAds: "true"; + siteLanguage: "ko"; + showIllustBackground: "true"; + showMovieBackground: "true"; + } +} diff --git a/src/paths/account/verify_credentials.yaml b/src/paths/account/verify_credentials.yaml deleted file mode 100644 index 2d918d6..0000000 --- a/src/paths/account/verify_credentials.yaml +++ /dev/null @@ -1,60 +0,0 @@ -# yaml-language-server: $schema=https://spec.openapis.org/oas/3.1/schema/2021-05-20 ---- -# for the intellisense -openapi: "3.1.0" -info: { title: "", version: "" } - -paths: - Path: - get: - summary: "로그인 정보 가져오기" - description: | - 현재 로그인한 계정 정보를 가져옵니다. - - **주의**: 로그인이 필요한 API는 사이트 내에서 호출할 수 없으므로 별도 도구를 이용해주십시오. - tags: - - account - operationId: verifyAccountCredentials - - security: - - solvedacToken: [] - - responses: - "403": - description: "solvedacToken이 올바르지 않은 경우입니다." - "200": - description: "서버가 반환에 성공한 경우입니다." - content: - application/json: - schema: - type: "object" - properties: - user: - description: "계정의 사용자 정보입니다." - allOf: - - $ref: "../../schemas/user.yaml#/components/schemas/User" - - type: "object" - properties: - settings: - $ref: "../../schemas/settings.yaml#/components/schemas/Settings" - email: - description: "계정의 이메일 주소입니다." - type: "string" - format: "email" - example: "kiwiyou.dev@gmail.com" - solved: - description: "해당 계정의 사용자가 푼 문제 정보입니다." - type: "array" - items: - type: "object" - properties: - id: - description: "문제 ID입니다." - type: "number" - example: 1002 - status: - description: | - 현재 문제 풀이 상태입니다. 알려진 값은 다음이 있습니다. - `"solved"`, `"tried"` - type: "string" - example: "tried" diff --git a/src/schemas/icon-scheme.yaml b/src/schemas/icon-scheme.yaml deleted file mode 100644 index 25b384f..0000000 --- a/src/schemas/icon-scheme.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# yaml-language-server: $schema=https://spec.openapis.org/oas/3.1/schema/2021-05-20 ---- -# for the intellisense -openapi: "3.1.0" -info: { title: "", version: "" } - -components: - schemas: - IconScheme: - title: IconScheme - description: "난이도 아이콘 표시 정책입니다." - type: "string" - enum: - - default - - hide-warn - - hide diff --git a/src/schemas/settings.yaml b/src/schemas/settings.yaml deleted file mode 100644 index a57ddc1..0000000 --- a/src/schemas/settings.yaml +++ /dev/null @@ -1,58 +0,0 @@ -# yaml-language-server: $schema=https://spec.openapis.org/oas/3.1/schema/2021-05-20 ---- -# for the intellisense -openapi: "3.1.0" -info: { title: "", version: "" } - -components: - schemas: - Settings: - title: Settings - description: "사용자의 solved.ac 설정 정보입니다." - type: "object" - properties: - screenTheme: - description: "사이트 디자인 테마입니다." - type: "string" - enum: ["default", "light", "dark", "black"] - tagDisplayLanguage: - allOf: - - $ref: "./language.yaml#/components/schemas/Language" - - description: "태그 이름을 나타낼 때 사용할 언어입니다." - iconSchemeSolved: - allOf: - - $ref: "./icon-scheme.yaml#/components/schemas/IconScheme" - - description: "해결한 문제의 난이도 아이콘입니다." - iconSchemeNotSolved: - allOf: - - $ref: "./icon-scheme.yaml#/components/schemas/IconScheme" - - description: "해결하지 못한 문제의 난이도 아이콘입니다." - problemSortBy: - description: "문제 목록의 기본 정렬 순서입니다." - type: "string" - enum: ["id", "level", "title", "solved", "average_try", "random"] - twitterPostHandle: - description: "트윗에 핸들을 포함하는지 여부입니다." - type: "string" - format: "boolean" - example: "true" - twitterPostOnClassIncrease: - description: "CLASS가 올랐을 때 트윗을 보내는지 여부입니다." - type: "string" - format: "boolean" - example: "false" - twitterPostOnProblemSolve: - description: "문제를 처음 해결했을 때 트윗을 보내는지 여부입니다." - type: "string" - format: "boolean" - example: "true" - twitterPostOnRatingIncrease: - description: "AC 레이팅이 올랐을 때 트윗을 보내는지 여부입니다." - type: "string" - format: "boolean" - example: "false" - twitterPostOnTierIncrease: - description: "티어가 올랐을 때 트윗을 보내는지 여부입니다." - type: "string" - format: "boolean" - example: "true"