diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index ff35ebb..f9632b9 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -36,6 +36,8 @@ jobs: env: multim_misskey_token: ${{secrets.multim_misskey_token}} multim_misskey_instance: ${{secrets.multim_misskey_instance}} + multim_misskeyv13_token: ${{secrets.multim_misskeyv13_token}} + multim_misskeyv13_instance: ${{secrets.multim_misskeyv13_instance}} USERNAME: ${{ github.actor }} TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index 271db44..53e940e 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -33,5 +33,7 @@ jobs: env: multim_misskey_token: ${{secrets.multim_misskey_token}} multim_misskey_instance: ${{secrets.multim_misskey_instance}} + multim_misskeyv13_token: ${{secrets.multim_misskeyv13_token}} + multim_misskeyv13_instance: ${{secrets.multim_misskeyv13_instance}} USERNAME: ${{ github.actor }} TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build.gradle.kts b/build.gradle.kts index 099ca54..af50ba1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -86,11 +86,15 @@ subprojects { props.load(file("${project.rootProject.projectDir}/local.properties").inputStream()) systemProperties("multim_misskey_token" to props["multim_misskey_token"]) systemProperties("multim_misskey_instance" to props["multim_misskey_instance"]) + systemProperties("multim_misskeyv13_token" to props["multim_misskeyv13_token"]) + systemProperties("multim_misskeyv13_instance" to props["multim_misskeyv13_instance"]) } catch (e: Exception) { println("local.properties not found") systemProperties("multim_misskey_token" to System.getenv("multim_misskey_token")) systemProperties("multim_misskey_instance" to System.getenv("multim_misskey_instance")) + systemProperties("multim_misskeyv13_token" to System.getenv("multim_misskeyv13_token")) + systemProperties("multim_misskeyv13_instance" to System.getenv("multim_misskeyv13_instance")) } useJUnitPlatform() diff --git a/impl/misskeyv13/build.gradle.kts b/impl/misskeyv13/build.gradle.kts new file mode 100644 index 0000000..14043d1 --- /dev/null +++ b/impl/misskeyv13/build.gradle.kts @@ -0,0 +1,41 @@ +dependencies { + implementation(project(":core")) +} + +sourceSets { + test { + kotlin { + compileClasspath += project(":core").sourceSets.test.get().output + runtimeClasspath += project(":core").sourceSets.test.get().output + } + } +} + +kotlin { + +} + +//tasks{ +// val sourcesJar by creating(Jar::class) { +// archiveClassifier.set("sources") +// from(sourceSets["main"].allSource) +// } +//} +// +//afterEvaluate { +// publishing { +// publications { +// +// +// create("maven") { +// groupId = project.group.toString() +// artifactId = "multim-${project.name}" +// version = project.version.toString() +// from(components["kotlin"]) +// artifact(tasks["sourcesJar"]) +// } +// +// +// } +// } +//} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/MisskeyV12Info.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/MisskeyV12Info.kt new file mode 100644 index 0000000..1d010e4 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/MisskeyV12Info.kt @@ -0,0 +1,33 @@ +package dev.usbharu.multim.misskey.v13 + +import dev.usbharu.multim.ServiceInfo +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.api.MisskeyMultiMApis +import dev.usbharu.multim.misskey.v13.common.api.MisskeyAccountApi +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.common.api.MisskeyEmojiApi +import dev.usbharu.multim.misskey.v13.common.api.MisskeyIApi +import dev.usbharu.multim.misskey.v13.common.api.MisskeyStatusApi +import dev.usbharu.multim.misskey.v13.common.api.MisskeyTimelineApi +import dev.usbharu.multim.model.SingleTokenAuth + +object MisskeyV13Info : ServiceInfo( + Regex("misskey"), + Regex("^13\\.[\\d.]+"), + { auth, baseUrl, client -> MisskeyApiClient(auth as SingleTokenAuth, baseUrl, client) }, + + { apiClient -> MisskeyApis(apiClient as MisskeyApiClient) }, + { + if (it is MisskeyApis) { + MisskeyMultiMApis( + MisskeyStatusApi(it), + MisskeyAccountApi(it), + MisskeyTimelineApi(it), + MisskeyEmojiApi(it), + MisskeyIApi(it) + ) + } else { + TODO() + } + } +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Ap.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Ap.kt new file mode 100644 index 0000000..d21b546 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Ap.kt @@ -0,0 +1,21 @@ +package dev.usbharu.multim.misskey.v13.api + +import com.github.michaelbull.result.mapError +import dev.usbharu.multim.error.* +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.ApShowRequest +import dev.usbharu.multim.misskey.v13.model.ApShowResponse +import io.ktor.client.plugins.* + +class Ap(val client: MisskeyApiClient) { + suspend fun show(apShowRequest: ApShowRequest): MultiMResult { + return client.post(apShowRequest, "api/ap/show").mapError { + val multiMError: MultiMError = when (it) { + is HttpClientServerError -> MultiMHttpError(it.throwable as ServerResponseException) + is HttpClientClientError -> MultiMHttpError(it.throwable as ClientRequestException) + else -> MultiMError("Api Client Error", it.throwable, ErrorType.UNKNOWN) + } + multiMError + } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Drive.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Drive.kt new file mode 100644 index 0000000..879ac9d --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Drive.kt @@ -0,0 +1,128 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.* +import io.ktor.client.call.* +import io.ktor.client.request.forms.* +import io.ktor.http.* + +class Drive(val client: MisskeyApiClient) { + @Suppress("MemberNameEqualsClassName") + suspend fun drive(): MultiMResult { + return client.postEmpty("api/drive").mapMultiMError() + } + + suspend fun files(filesRequest: DriveFilesRequest): MultiMResult { + return client.post(filesRequest, "api/drive/files") + .mapMultiMError() + } + + suspend fun folders(foldersRequest: DriveFoldersRequest): MultiMResult { + return client.post( + foldersRequest, + "api/drive/folders" + ).mapMultiMError() + } + + inner class Files { + suspend fun attachedNotes(attachedNotesRequest: DriveFilesAttachedNotesRequest) + : MultiMResult { + return client.post( + attachedNotesRequest, + "api/drive/files/attached-notes" + ).mapMultiMError() + } + + suspend fun checkExistence(checkExistenceRequest: DriveFilesCheckExistenceRequest) + : MultiMResult { + return client.post( + checkExistenceRequest, + "api/drive/files/check-existence" + ).mapMultiMError() + } + + //TODO Result型対応 + suspend fun create(createRequest: DriveFilesCreateRequest): DriveFilesCreateResponse { + return client.client.submitFormWithBinaryData( + client.baseUrl + "api/drive/files/create", + formData = formData { + append("\"i\"", client.auth.token) + append("\"file\"", createRequest.file, Headers.build { + append(HttpHeaders.ContentDisposition, "filename=${createRequest.name}") + }) + }).body() +// return client.post(createRequest, "api/drive/files/create") + } + + suspend fun delete(deleteRequest: DriveFilesDeleteRequest): MultiMResult { + return client.postWithoutResponse(deleteRequest, "api/drive/files/delete") + .mapMultiMError() + } + + suspend fun findByHash(findByHashRequest: DriveFilesFindByHashRequest) + : MultiMResult { + return client.post( + findByHashRequest, + "api/drive/files/find-by-hash" + ).mapMultiMError() + } + + suspend fun find(findRequest: DriveFilesFindRequest): MultiMResult { + return client.post( + findRequest, + "api/drive/files/find" + ).mapMultiMError() + } + + suspend fun show(showRequest: DriveFilesShowRequestByUrl): MultiMResult { + return client.post( + showRequest, + "api/drive/files/show" + ).mapMultiMError() + } + + suspend fun show(showRequest: DriveFilesShowRequestByFileId): MultiMResult { + return client.post( + showRequest, + "api/drive/files/show" + ).mapMultiMError() + } + + suspend fun update(updateRequest: DriveFilesUpdateRequest): MultiMResult { + return client.post( + updateRequest, + "api/drive/files/update" + ).mapMultiMError() + } + + suspend fun uploadFromUrl(uploadFromUrlRequest: DriveFilesUploadFromUrlRequest): MultiMResult { + return client.postWithoutResponse( + uploadFromUrlRequest, + "api/drive/files/upload-from-url" + ).mapMultiMError() + } + } + + inner class Folders { + suspend fun create(foldersCreateRequest: DriveFoldersCreateRequest): MultiMResult { + return client.post( + foldersCreateRequest, + "api/drive/folders/create" + ).mapMultiMError() + } + + suspend fun delete(foldersDeleteRequest: DriveFoldersDeleteRequest): MultiMResult { + return client.postWithoutResponse(foldersDeleteRequest, "api/drive/folders/delete") + .mapMultiMError() + } + + suspend fun find(foldersFindRequest: DriveFoldersFindRequest): MultiMResult { + return client.post( + foldersFindRequest, + "api/drive/folders/find" + ).mapMultiMError() + } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Following.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Following.kt new file mode 100644 index 0000000..a7a5821 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Following.kt @@ -0,0 +1,58 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.* + +class Following(val client: MisskeyApiClient) { + suspend fun create(followingCreateRequest: FollowingCreateRequest): MultiMResult { + return client.post( + followingCreateRequest, + "api/following/create" + ).mapMultiMError() + } + + suspend fun delete(followingDeleteRequest: FollowingDeleteRequest): MultiMResult { + return client.post( + followingDeleteRequest, + "api/following/delete" + ).mapMultiMError() + } + + suspend fun invalidate(followingInvalidateRequest: FollowingInvalidateRequest) + : MultiMResult { + return client.post( + followingInvalidateRequest, + "api/following/invalidate" + ).mapMultiMError() + } + + inner class Requests { + suspend fun accept(followingRequestsAcceptRequest: FollowingRequestsAcceptRequest): MultiMResult { + return client.postWithoutResponse( + followingRequestsAcceptRequest, + "api/following/requests/list" + ).mapMultiMError() + } + + suspend fun cancel(followingRequestsCancelRequest: FollowingRequestsCancelRequest): MultiMResult { + return client.postWithoutResponse( + followingRequestsCancelRequest, + "api/following/requests/cancel" + ).mapMultiMError() + } + + suspend fun list(): MultiMResult { + return client.postEmpty("api/following/requests/list") + .mapMultiMError() + } + + suspend fun reject(followingRequestsRejectRequest: FollowingRequestsRejectRequest): MultiMResult { + return client.postWithoutResponse( + followingRequestsRejectRequest, + "api/following/requests/reject" + ).mapMultiMError() + } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/I.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/I.kt new file mode 100644 index 0000000..23151f2 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/I.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.IIRequest +import dev.usbharu.multim.misskey.v13.model.IIResponse + +@Suppress("MemberNameEqualsClassName") +class I(val misskeyApiClient: MisskeyApiClient) { + suspend fun i(iiRequest: IIRequest = IIRequest()): MultiMResult { + return misskeyApiClient.post(iiRequest, "api/i").mapMultiMError() + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Meta.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Meta.kt new file mode 100644 index 0000000..ff55355 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Meta.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.MetaRequest +import dev.usbharu.multim.misskey.v13.model.MetaResponse + +@Suppress("MemberNameEqualsClassName") +class Meta(val client: MisskeyApiClient) { + suspend fun meta(metaRequest: MetaRequest): MultiMResult { + return client.post(metaRequest, "api/meta") + .mapMultiMError() + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Miauth.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Miauth.kt new file mode 100644 index 0000000..499b6e1 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Miauth.kt @@ -0,0 +1,32 @@ +package dev.usbharu.multim.misskey.v13.api + +import com.github.michaelbull.result.map +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.MiauthCheckRequest +import dev.usbharu.multim.misskey.v13.model.MiauthCheckResponse +import io.ktor.client.statement.* +import java.util.* + + +class Miauth(val client: MisskeyApiClient) { + + suspend fun auth(): MultiMResult { + + val body = client.get(client.baseUrl + "/miauth/" + UUID.randomUUID() + "/") { + url { + + parameters.append("name", "multim-test") + parameters.append("permission", "read:account,write:notes") + } + }.map { it.bodyAsText() } + return body.mapMultiMError() + } + + suspend fun check(params: MiauthCheckRequest): MultiMResult { + return client.postEmpty("", "/api/miauth/${params.sessionId}/check") + .mapMultiMError() + } + +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/MisskeyApis.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/MisskeyApis.kt new file mode 100644 index 0000000..7b4d13e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/MisskeyApis.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.api.PlatformApis +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient + +class MisskeyApis(misskeyApiClient: MisskeyApiClient) : PlatformApis(misskeyApiClient) { + val notes = Notes(misskeyApiClient) + val ap = Ap(misskeyApiClient) + val miauth = Miauth(misskeyApiClient) + val timeline = Timeline(misskeyApiClient) + val following = Following(misskeyApiClient) + val users = Users(misskeyApiClient) + val meta = Meta(misskeyApiClient) + val i = I(misskeyApiClient) +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/MisskeyMultiMApis.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/MisskeyMultiMApis.kt new file mode 100644 index 0000000..ec85ce4 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/MisskeyMultiMApis.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.api.* +import dev.usbharu.multim.factory.MultiMApis + +class MisskeyMultiMApis( + statusApi: StatusApi, + accountApi: AccountApi, + timelineApi: TimelineApi, + emojiApi: EmojiApi, + iApi: IApi +) : + MultiMApis(statusApi, accountApi, timelineApi, emojiApi, iApi) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Notes.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Notes.kt new file mode 100644 index 0000000..6ead17d --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Notes.kt @@ -0,0 +1,221 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.* +import dev.usbharu.multim.misskey.v13.model.components.Note + +@Suppress("MemberNameEqualsClassName") +class Notes(val client: MisskeyApiClient) { + + suspend fun globalTimeline(globalTimelineRequest: NotesGlobalTimelineRequest = NotesGlobalTimelineRequest()) + : MultiMResult { + return client.post( + globalTimelineRequest, + "api/notes/global-timeline" + ).mapMultiMError() + } + + suspend fun hybridTimeline(hybridTimelineRequest: NotesHybridTimelineRequest = NotesHybridTimelineRequest()) + : MultiMResult { + return client.post( + hybridTimelineRequest, + "api/notes/hybrid-timeline" + ).mapMultiMError() + } + + suspend fun localTimeline(localTimelineRequest: NotesLocalTimelineRequest = NotesLocalTimelineRequest()) + : MultiMResult { + return client.post( + localTimelineRequest, + "api/notes/local-timeline" + ).mapMultiMError() + } + + suspend fun show(showRequest: NotesShowRequest): MultiMResult { + return client.post(showRequest, "api/notes/show") + .mapMultiMError() + } + + suspend fun create(createRequest: NotesCreateRequest): MultiMResult { + return client.post( + createRequest, + "api/notes/create" + ).mapMultiMError() + } + + suspend fun delete(deleteRequest: NotesDeleteRequest) { + client.postWithoutResponse(deleteRequest, "api/notes/delete").mapMultiMError() + } + + suspend fun featured(featuredRequest: NotesFeaturedRequest = NotesFeaturedRequest()) + : MultiMResult { + return client.post( + featuredRequest, + "api/notes/featured" + ).mapMultiMError() + } + + suspend fun mentions(mentionsRequest: NotesMentionsRequest): MultiMResult { + return client.post( + mentionsRequest, + "api/notes/mentions" + ).mapMultiMError() + } + + suspend fun children(childrenRequest: NotesChildrenRequest): MultiMResult { + return client.post( + childrenRequest, + "api/notes/children" + ).mapMultiMError() + } + + suspend fun notes(notesRequest: NotesNotesRequest): MultiMResult { + return client.post(notesRequest, "api/notes") + .mapMultiMError() + } + + suspend fun conversation(conversationRequest: NotesConversationRequest): MultiMResult { + return client.post( + conversationRequest, + "api/notes/conversation" + ).mapMultiMError() + } + + suspend fun reactions(reactionsRequest: NotesReactionsRequest): MultiMResult { + return client.post( + reactionsRequest, + "api/notes/reactions" + ).mapMultiMError() + } + + suspend fun renotes(renoteRequest: NotesRenoteRequest): MultiMResult { + return client.post( + renoteRequest, + "api/notes/renotes" + ).mapMultiMError() + } + + suspend fun replies(repliesRequest: NotesRepliesRequest): MultiMResult { + return client.post( + repliesRequest, + "api/notes/replies" + ).mapMultiMError() + } + + suspend fun searchByTag(searchByTagRequest: NotesSearchByTagRequest): MultiMResult { + return client.post( + searchByTagRequest, + "api/notes/search-by-tag" + ).mapMultiMError() + } + + suspend fun search(searchRequest: NotesSearchRequest): MultiMResult { + return client.post( + searchRequest, + "api/notes/search" + ).mapMultiMError() + } + + suspend fun state(stateRequest: NotesStateRequest): MultiMResult { + return client.post(stateRequest, "api/notes/state") + .mapMultiMError() + } + + suspend fun timeline(timelineRequest: NotesTimelineRequest): MultiMResult { + return client.post( + timelineRequest, + "api/notes/timeline" + ).mapMultiMError() + } + + suspend fun translate(translateRequest: NotesTranslateRequest): MultiMResult { + return client.post( + translateRequest, + "api/notes/translate" + ).mapMultiMError() + } + + suspend fun unrenote(unrenoteRequest: NotesUnrenoteRequest): MultiMResult { + return client.postWithoutResponse(unrenoteRequest, "api/notes/unrenote").mapMultiMError() + } + + suspend fun userListTimeline(userListTimelineRequest: NotesUserListTimelineRequest) + : MultiMResult { + return client.post>( + userListTimelineRequest, + "api/notes/user-list-timeline" + ).mapMultiMError() + } + + + inner class Polls { + suspend fun recommendation(pollsRecommendationRequest: PollsRecommendationRequest) + : MultiMResult { + return client.post>( + pollsRecommendationRequest, + "api/notes/polls/recommendation" + ).mapMultiMError() + } + + suspend fun vote(voteRequest: NotesPollsVoteRequest): MultiMResult { + return client.post( + voteRequest, + "api/notes/polls/vote" + ).mapMultiMError() + } + } + + inner class ThreadMuting { + suspend fun create(threadMutingCreateRequest: NotesThreadMutingCreateRequest): MultiMResult { + return client.postWithoutResponse( + threadMutingCreateRequest, + "api/notes/thread-muting/create" + ).mapMultiMError() + } + + suspend fun delete(threadMutingDeleteRequest: NotesThreadMutingDeleteRequest): MultiMResult { + return client.postWithoutResponse( + threadMutingDeleteRequest, + "api/notes/thread-muting/delete" + ).mapMultiMError() + } + } + + inner class Watching { + suspend fun create(watchingCreateRequest: NotesWatchingCreateRequest): MultiMResult { + return client.postWithoutResponse(watchingCreateRequest, "api/notes/watching/create") + .mapMultiMError() + } + + suspend fun delete(watchingDeleteRequest: NotesWatchingDeleteRequest): MultiMResult { + return client.postWithoutResponse(watchingDeleteRequest, "api/notes/watching/delete") + .mapMultiMError() + } + } + + inner class Favorites { + suspend fun create(favoritesCreateRequest: NotesFavoritesCreateRequest): MultiMResult { + return client.postWithoutResponse(favoritesCreateRequest, "api/notes/favorites/create") + .mapMultiMError() + } + + suspend fun delete(favoritesDeleteRequest: NotesFavoritesDeleteRequest): MultiMResult { + return client.postWithoutResponse(favoritesDeleteRequest, "api/notes/favorites/delete") + .mapMultiMError() + } + } + + inner class Reaction { + suspend fun create(reactionCreateRequest: NotesReactionCreateRequest): MultiMResult { + return client.postWithoutResponse(reactionCreateRequest, "api/notes/reactions/create") + .mapMultiMError() + } + + suspend fun delete(reactionDeleteRequest: NotesReactionDeleteRequest): MultiMResult { + return client.postWithoutResponse(reactionDeleteRequest, "api/notes/reactions/delete") + .mapMultiMError() + } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Timeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Timeline.kt new file mode 100644 index 0000000..cf9345b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Timeline.kt @@ -0,0 +1,43 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.MultiM.json +import dev.usbharu.multim.misskey.v13.common.api.Callback +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.StreamRequest +import dev.usbharu.multim.misskey.v13.model.StreamResponse +import io.ktor.websocket.* +import kotlinx.serialization.decodeFromString + +class Timeline(val client: MisskeyApiClient) { + fun connectChannel(channelConnectRequest: StreamRequest.ConnectRequest) { + client.Streaming().send(channelConnectRequest as StreamRequest) + } + + fun connectChannel( + channelConnectRequest: StreamRequest.ConnectRequest, + callBack: (StreamResponse.ChannelResponse.ChannelBody) -> Unit + ) { + val id = channelConnectRequest.body.id + client.streaming.send(channelConnectRequest as StreamRequest) + val callback: Callback = { + if (it is Frame.Text) { + val response: StreamResponse.ChannelResponse = json.decodeFromString(it.readText()) + if (id == response.body.id) { + callBack(response.body) + } + + } + } + client.streaming.listen(id, callback) + } + + + fun sendToChannel(channelRequest: StreamRequest.ChannelRequest) { + client.streaming.send(channelRequest) + } + + fun disconnectChannel(channelDisconnectRequest: StreamRequest.DisconnectRequest) { + client.streaming.send(channelDisconnectRequest as StreamRequest) + client.streaming.unlisted(channelDisconnectRequest.body.id) + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Users.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Users.kt new file mode 100644 index 0000000..1bd9c55 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/api/Users.kt @@ -0,0 +1,26 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.mapMultiMError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.* +import dev.usbharu.multim.misskey.v13.model.components.Note + +class Users(val client: MisskeyApiClient) { + suspend fun relation(relationRequest: UsersRelationRequest): MultiMResult { + return client.post( + relationRequest, + "api/users/relation" + ).mapMultiMError() + } + + suspend fun notes(notesRequest: UsersNotesRequest): MultiMResult { + return client.post>(notesRequest, "api/users/notes") + .mapMultiMError() + } + + suspend fun show(showRequest: UsersShowRequest): MultiMResult { + return client.post(showRequest, "api/users/show") + .mapMultiMError() + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyAccount.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyAccount.kt new file mode 100644 index 0000000..93f3565 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyAccount.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Account +import dev.usbharu.multim.model.Avatar + +class MisskeyAccount( + val id: String, + screenName: String, + accountName: String, + isBot: Boolean? = false, + avatar: Avatar +) : Account(screenName, accountName, isBot, avatar) { + override val cacheKey: String + get() = accountName +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyAvatar.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyAvatar.kt new file mode 100644 index 0000000..c2d057e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyAvatar.kt @@ -0,0 +1,5 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Avatar + +class MisskeyAvatar(avatarUrl: String) : Avatar(avatarUrl) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyContent.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyContent.kt new file mode 100644 index 0000000..2a9d692 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyContent.kt @@ -0,0 +1,5 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Content + +class MisskeyContent(val content: String) : Content(content) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyEmoji.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyEmoji.kt new file mode 100644 index 0000000..afcc433 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyEmoji.kt @@ -0,0 +1,5 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Emoji + +class MisskeyEmoji(name: String, url: String) : Emoji(name, url) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyField.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyField.kt new file mode 100644 index 0000000..8ffaf59 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyField.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Field + +class MisskeyField(name: String = "", value: String = "") : + Field(name, value, false) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyFile.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyFile.kt new file mode 100644 index 0000000..702bdba --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyFile.kt @@ -0,0 +1,5 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.File + +class MisskeyFile(data: ByteArray, type: String, name: String) : File(data, type, name) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyFiles.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyFiles.kt new file mode 100644 index 0000000..2248a06 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyFiles.kt @@ -0,0 +1,5 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Files + +class MisskeyFiles(files: List) : Files(files) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyProfile.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyProfile.kt new file mode 100644 index 0000000..d41515c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyProfile.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Account +import dev.usbharu.multim.model.Content +import dev.usbharu.multim.model.Field +import dev.usbharu.multim.model.Profile + +class MisskeyProfile( + account: Account, + isBot: Boolean = false, + profileContent: Content, + followingCount: Int = 0, + followersCount: Int = 0, + fields: List = emptyList() +) : Profile(account, isBot, profileContent, followingCount, followersCount, fields) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyReaction.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyReaction.kt new file mode 100644 index 0000000..fcd1fd0 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyReaction.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Reaction + +class MisskeyReaction(name: String, url: String?) : Reaction(name, url) { + fun toLocal(): MisskeyReaction = MisskeyReaction( + name.replace(":", "").split("@").first(), + url + ) + +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyRelation.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyRelation.kt new file mode 100644 index 0000000..50cac4b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyRelation.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.Relation + +class MisskeyRelation( + myself: MisskeyAccount, + other: MisskeyAccount, + following: Boolean, + follower: Boolean, + mute: Boolean, + block: Boolean +) : Relation(myself, other, following, follower, mute, block) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyStatus.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyStatus.kt new file mode 100644 index 0000000..4100e5f --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyStatus.kt @@ -0,0 +1,38 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.* +import kotlinx.datetime.Clock +import kotlinx.datetime.Instant + +@Suppress("LongParameterList") +class MisskeyStatus( + override val id: MisskeyStatusId, + override val account: MisskeyAccount, + content: Content, + reactions: Map = emptyMap(), + myReactions: List = emptyList(), + repostCount: Int = 0, + repliesCount: Int = 0, + reposted: Boolean = false, + emojis: List = emptyList(), + tags: List = emptyList(), + language: String? = null, + poll: Poll? = null, + files: Files? = null, + createdAt:Instant = Clock.System.now() +) : Status( + id, + account, + content, + reactions, + myReactions, + repostCount, + repliesCount, + reposted, + emojis, + tags, + language, + poll, + files, + createdAt +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyStatusId.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyStatusId.kt new file mode 100644 index 0000000..7e0edf0 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyStatusId.kt @@ -0,0 +1,20 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.model.StatusId + +class MisskeyStatusId(val id: String, private val url: String) : StatusId() { + override fun equals(other: Any?): Boolean { + return other?.equals(this) ?: false + } + + override fun hashCode(): Int { + return 0 + } + + override fun getUrl(): String { + return url + } + + override val cacheKey: String + get() = id +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyTimeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyTimeline.kt new file mode 100644 index 0000000..ca29cca --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/MisskeyTimeline.kt @@ -0,0 +1,10 @@ +package dev.usbharu.multim.misskey.v13.common + +import dev.usbharu.multim.misskey.v13.model.StreamRequest +import dev.usbharu.multim.model.Timeline + +data class MisskeyTimeline( + val id: String, + override val name: String, + val channel: StreamRequest.ConnectRequest.Body.Channel +) : Timeline(name) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyAccountApi.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyAccountApi.kt new file mode 100644 index 0000000..7cb9adf --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyAccountApi.kt @@ -0,0 +1,158 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.map +import dev.usbharu.multim.api.AccountApi +import dev.usbharu.multim.error.ErrorType +import dev.usbharu.multim.error.MultiMError +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.TODO +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.NoteConverter.toStatus +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.UsersConverter.toRelation +import dev.usbharu.multim.misskey.v13.common.MisskeyAccount +import dev.usbharu.multim.misskey.v13.common.MisskeyContent +import dev.usbharu.multim.misskey.v13.common.MisskeyProfile +import dev.usbharu.multim.misskey.v13.common.MisskeyStatusId +import dev.usbharu.multim.misskey.v13.model.components.MeDetailed +import dev.usbharu.multim.misskey.v13.model.components.UserDetailedNotMe +import dev.usbharu.multim.misskey.v13.model.FollowingCreateRequest +import dev.usbharu.multim.misskey.v13.model.FollowingDeleteRequest +import dev.usbharu.multim.misskey.v13.model.FollowingRequestsAcceptRequest +import dev.usbharu.multim.misskey.v13.model.FollowingRequestsCancelRequest +import dev.usbharu.multim.misskey.v13.model.FollowingRequestsRejectRequest +import dev.usbharu.multim.misskey.v13.model.UsersNotesRequest +import dev.usbharu.multim.misskey.v13.model.UsersRelationRequest +import dev.usbharu.multim.misskey.v13.model.UsersShowRequest +import dev.usbharu.multim.misskey.v13.model.components.UserLite +import dev.usbharu.multim.model.* + +class MisskeyAccountApi(val misskeyApis: MisskeyApis) : AccountApi { + @Deprecated("statusesに統合") + override suspend fun userTimeline( + account: Account, + since: StatusId?, + until: StatusId? + ): MultiMResult> { + if (account is MisskeyAccount && since is MisskeyStatusId? && until is MisskeyStatusId?) { + return misskeyApis.users.notes( + UsersNotesRequest( + userId = account.id, + sinceId = since?.id, + untilId = until?.id + ) + ).map { + it.map { note -> + note.toStatus() + } + } + + } else { + return TODO() + } + } + + override suspend fun follow(account: Account): MultiMResult { + return if (account is MisskeyAccount) { + misskeyApis.following.create(FollowingCreateRequest(account.id)).map { } + } else { + TODO() + } + } + + override suspend fun unfollow(account: Account): MultiMResult { + return if (account is MisskeyAccount) { + misskeyApis.following.delete(FollowingDeleteRequest(account.id)).map { } + } else { + // サーバーが認知していないアカウントのフォローを辞めることはできないのでfalse + Err(MultiMError("Can not unfollow", null, ErrorType.API)) + } + } + + override suspend fun profile(account: Account): MultiMResult { + if (account is MisskeyAccount) { + val show = misskeyApis.users.show(UsersShowRequest(account.id)) + return show.map { + when (it) { + //todo converterで書く + is MeDetailed -> MisskeyProfile( + account, + account.isBot ?: false, + MisskeyContent(it.description.orEmpty()), + it.followingCount, + it.followersCount, + ) + + is UserDetailedNotMe -> MisskeyProfile( + account, + account.isBot ?: false, + MisskeyContent( + it.description.orEmpty() + ), + it.followingCount, + it.followersCount + ) + + is UserLite -> return Err(MultiMError("不正な返り値",IllegalStateException("不正な返り値"),ErrorType.API)) + } + } + } + return TODO() + } + + override suspend fun statuses( + account: Account, + includeRepost: Boolean, + since: StatusId?, + until: StatusId? + ): MultiMResult> { + return if (account is MisskeyAccount) { + misskeyApis.users.notes( + UsersNotesRequest( + userId = account.id, + includeMyRenotes = includeRepost + ) + ).map { it.map { note -> note.toStatus() } } + } else { + TODO() + } + } + + override suspend fun relationships( + myself: Account, + other: Account + ): MultiMResult { + if (myself is MisskeyAccount && other is MisskeyAccount) { + return misskeyApis.users.relation(UsersRelationRequest(other.id)) + .map { it.toRelation(myself, other) } + } + return TODO() + } + + override suspend fun requestCancel(account: Account): MultiMResult { + if (account is MisskeyAccount) { + misskeyApis.following.Requests().cancel(FollowingRequestsCancelRequest(account.id)) + return Ok(Unit) + } + return TODO() + } + + override suspend fun requestAccept(account: Account): MultiMResult { + return if (account is MisskeyAccount) { + misskeyApis.following.Requests().accept(FollowingRequestsAcceptRequest(account.id)) + Ok(Unit) + } else { + TODO() + } + } + + override suspend fun requestReject(account: Account): MultiMResult { + return if (account is MisskeyAccount) { + misskeyApis.following.Requests().reject(FollowingRequestsRejectRequest(account.id)) + Ok(Unit) + } else { + TODO() + } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyApiClient.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyApiClient.kt new file mode 100644 index 0000000..bb7e5a1 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyApiClient.kt @@ -0,0 +1,133 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import dev.usbharu.multim.Logger +import dev.usbharu.multim.MultiM.json +import dev.usbharu.multim.api.ApiClient +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.model.SingleTokenAuth +import io.ktor.client.* +import io.ktor.client.plugins.api.* +import io.ktor.client.plugins.websocket.* +import io.ktor.http.* +import io.ktor.serialization.kotlinx.* +import io.ktor.websocket.* +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.consumeEach +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.serialization.encodeToString + +class MisskeyApiClient(var auth: SingleTokenAuth, baseUrl: String, client: HttpClient) : + ApiClient(baseUrl, client.config { + expectSuccess = true + install(WebSockets) { + pingInterval = 20_000 + contentConverter = KotlinxWebsocketSerializationConverter(json) + } + install(createClientPlugin("MisskeyAuthPlugin") { + onRequest { request, content -> + Logger.trace("Misskey Auth Plugin","request type is :${content::class}") + if (content is MisskeyNeedAuth) { + Logger.trace("Misskey Auth Plugin","Injection token") + content.i = auth.token + } + request.headers.append( + "Content-Type", ContentType.Application.Json + ) + } + }) + }) { + + internal val streaming = Streaming() + + internal inner class Streaming(context: CoroutineDispatcher = Dispatchers.IO) { + + val callbackMutex = Mutex() + val callbackList = mutableMapOf() + + val coroutineScope = CoroutineScope(context) + + var commands = MutableStateFlow("a") + fun connect() { + val launch = coroutineScope.launch { + client.wss("ws" + baseUrl.replaceFirst("http", "") + "streaming?i=${auth.token}") { + awaitAll( + coroutineScope.async { + commands.onEach { + Logger.debug("Api Client Streaming", "Sending :$it") + outgoing.send(Frame.Text(it)) + } + .launchIn(coroutineScope) + }, + coroutineScope.async { + incoming.consumeEach { + callbackMutex.withLock { + callbackList.forEach { mutableEntry -> + mutableEntry.value.invoke(it) + } + } + } + } + ) + } + Logger.debug("Api Client Streaming","Connected") + + } +// launch.join() + } + + suspend fun disconnect() { + coroutineScope.launch { +// webSocketSession?.close() + }.cancelAndJoin() + } + + inline fun send(data: T) { + coroutineScope.launch { + val value = json.encodeToString(data) + commands.emit(value) + } + } + + fun send(data: String) { + coroutineScope.launch { + commands.emit(data) + } + } + + fun listen(id: String, callback: Callback) { + coroutineScope.launch { + callbackMutex.withLock { + callbackList[id] = callback + } + } + } + + fun unlisted(id: String) { + coroutineScope.launch { + callbackMutex.withLock { + callbackList.remove(id) + if (callbackList.isEmpty()) { + disconnect() + } + } + } + } + + fun clearCallback() { + coroutineScope.launch { + + callbackMutex.withLock { + callbackList.clear() + disconnect() + } + } + } + + } +} + +typealias Callback = (Frame) -> Unit diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyEmojiApi.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyEmojiApi.kt new file mode 100644 index 0000000..c377ad3 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyEmojiApi.kt @@ -0,0 +1,42 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.map +import dev.usbharu.multim.api.EmojiApi +import dev.usbharu.multim.error.ErrorType +import dev.usbharu.multim.error.MultiMError +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.common.MisskeyEmoji +import dev.usbharu.multim.misskey.v13.model.MetaRequest +import dev.usbharu.multim.model.Emoji +import dev.usbharu.multim.misskey.v13.model.components.Emoji as MisskeyModelEmoji + +class MisskeyEmojiApi(val misskeyApis: MisskeyApis) : EmojiApi { + override suspend fun get(name: String): MultiMResult { +// return misskeyApis.meta.meta(MetaRequest()) +// .flatMap { +// it.emojis.find { emoji: MisskeyModelEmoji -> emoji.name.equals(name, true) } +// .toResultOr { +// MultiMError( +// "Emoji $name not Found", +// null, +// ErrorType.ILLEGAL_ARGUMENT +// ) +// } +// }.map { MisskeyEmoji(it.name, it.url) } + return Err(MultiMError("Not Impl",null,ErrorType.NOT_IMPL)) + } + + override suspend fun findByName(name: String): MultiMResult> { +// return misskeyApis.meta.meta(MetaRequest()) +// .map { +// it.emojis.filter { emoji: MisskeyModelEmoji -> +// emoji.name.startsWith(name, true).or(emoji.name.endsWith(name, true)) +// } +// }.map { +// it.map { emoji -> MisskeyEmoji(emoji.name, emoji.url) } +// } + return Err(MultiMError("Not Impl",null,ErrorType.NOT_IMPL)) + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyIApi.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyIApi.kt new file mode 100644 index 0000000..ee84e88 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyIApi.kt @@ -0,0 +1,24 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import com.github.michaelbull.result.flatMap +import com.github.michaelbull.result.map +import dev.usbharu.multim.api.IApi +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.NoteConverter.toStatus +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.UsersConverter.toProfile +import dev.usbharu.multim.misskey.v13.model.UsersNotesRequest +import dev.usbharu.multim.model.Profile +import dev.usbharu.multim.model.Status + +class MisskeyIApi(val misskeyApis: MisskeyApis) : IApi { + override suspend fun profile(): MultiMResult { + return misskeyApis.i.i().map { it.toProfile() } + } + + override suspend fun statuses(): MultiMResult> { + return misskeyApis.i.i().map { it.id } + .flatMap { misskeyApis.users.notes(UsersNotesRequest(it)) } + .map { it.map { note -> note.toStatus() } } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyStatusApi.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyStatusApi.kt new file mode 100644 index 0000000..801d0a2 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyStatusApi.kt @@ -0,0 +1,183 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.flatMap +import com.github.michaelbull.result.map +import dev.usbharu.multim.api.StatusApi +import dev.usbharu.multim.error.ErrorType +import dev.usbharu.multim.error.MultiMError +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.error.TODO +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.common.MisskeyReaction +import dev.usbharu.multim.misskey.v13.common.MisskeyStatusId +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.NoteConverter.toStatus +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.ReactionConverter.toReactions +import dev.usbharu.multim.misskey.v13.model.ApShowRequest +import dev.usbharu.multim.misskey.v13.model.ApShowResponse +import dev.usbharu.multim.misskey.v13.model.MetaRequest +import dev.usbharu.multim.misskey.v13.model.NotesChildrenRequest +import dev.usbharu.multim.misskey.v13.model.NotesCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesFavoritesCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesFavoritesDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesReactionCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesReactionDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesShowRequest +import dev.usbharu.multim.misskey.v13.model.NotesUnrenoteRequest +import dev.usbharu.multim.model.* +import dev.usbharu.multim.util.EmojiUtils + + +/** + * Misskey status api + * 現在の実装だと、マルチアカウントには対応していません。 + * @property misskeyApis + * @constructor Create empty Misskey status api + */ +class MisskeyStatusApi(private val misskeyApis: MisskeyApis) : StatusApi { + override suspend fun post(status: StatusForPost): MultiMResult { + + return misskeyApis.notes.create(NotesCreateRequest(text = status.content.text)) + .map { it.createdNote.toStatus() } + + } + + override suspend fun delete(id: StatusId): MultiMResult { + if (id is MisskeyStatusId) { + misskeyApis.notes.delete(NotesDeleteRequest(id.id)) + return Ok(Unit) + } + return TODO() + } + + override suspend fun findById(id: StatusId): MultiMResult { + return id.fetchId() + .flatMap { misskeyApis.notes.show(NotesShowRequest(it.id)) } + .map { it.toStatus() } + } + + override suspend fun addReaction(id: StatusId, reaction: Reaction): MultiMResult { + if (reaction is MisskeyReaction && id is MisskeyStatusId) { + misskeyApis.notes.Reaction().create( + NotesReactionCreateRequest( + noteId = id.id, reaction = reaction.toLocal().name + ) + ) + return Ok(Unit) + } + return TODO() + } + + /** + * Remove reaction + * + * @param id + * @param reaction 無視される + * @return + */ + override suspend fun removeReaction( + id: StatusId, + reaction: Reaction? + ): MultiMResult { + return if (id is MisskeyStatusId) { + misskeyApis.notes.Reaction().delete(NotesReactionDeleteRequest(id.id)) + Ok(Unit) + } else { + //サーバーが認知していない投稿のリアクションを消せるわけないので何もしない + Err(MultiMError("id is Not misskey id", null, ErrorType.API)) + } + } + + override suspend fun reactions(id: StatusId): MultiMResult> { + return id.fetchId().flatMap { misskeyApis.notes.show(NotesShowRequest(it.id)) } + .map { it.reactions.toReactions(it) } + } + + override suspend fun repost(id: StatusId): MultiMResult { + return id.fetchId() + .flatMap { misskeyApis.notes.create(NotesCreateRequest(renoteId = it.id)) } + .map { it.createdNote.toStatus() } + } + + override suspend fun unRepost(id: StatusId): MultiMResult { + return if (id is MisskeyStatusId) { + misskeyApis.notes.unrenote(NotesUnrenoteRequest(id.id)) + Ok(Unit) + } else { + //サーバーが認知していない投稿の再投稿を消せるわけないので何もしない + Err(MultiMError("id is Not Misskey id", null, ErrorType.API)) + } + } + + override suspend fun replyTo(id: StatusId, status: StatusForPost): MultiMResult { + return id.fetchId().flatMap { + misskeyApis.notes.create( + NotesCreateRequest( + replyId = it.id, + text = status.content.text + ) + ) + }.map { it.createdNote.toStatus() } + } + + override suspend fun addToBookmarks(id: StatusId): MultiMResult { + return id.fetchId() + .flatMap { misskeyApis.notes.Favorites().create(NotesFavoritesCreateRequest(it.id)) } + } + + override suspend fun removeFromBookmarks(id: StatusId): MultiMResult { + return if (id is MisskeyStatusId) { + misskeyApis.notes.Favorites().delete(NotesFavoritesDeleteRequest(id.id)) + Ok(Unit) + } else { + // サーバーが認知していない投稿のブックマークを消せるわけないので何もしない + Err(MultiMError("id is Not Misskey id", null, ErrorType.API)) + } + } + + override suspend fun getPreviousAndNext(id: StatusId): MultiMResult { + return TODO() //よくわからんのでとりあえず未実装 多分user-timelineからリノートを取り除いたらできる + } + + override suspend fun replies(id: StatusId): MultiMResult> { + return id.fetchId().flatMap { misskeyApis.notes.children(NotesChildrenRequest(it.id)) } + .map { it.map { note -> note.toStatus() } } + } + + override suspend fun availableReactions(): MultiMResult> { + return misskeyApis.meta.meta(MetaRequest()) +// .map { metaResponse -> +// metaResponse.emojis +// } + .map { + val mutableListOf = mutableListOf() + mutableListOf.addAll( + EmojiUtils.getAllEmoji().map { unicodeEmoji -> MisskeyReaction(unicodeEmoji.string, null) }) +// mutableListOf.addAll(it.map { emoji -> MisskeyReaction(emoji.name, emoji.url) }) + mutableListOf + } + } + + private suspend fun StatusId.fetchId(): MultiMResult { + if (this is MisskeyStatusId) { + return Ok(this) + } + return misskeyApis.ap.show(ApShowRequest(getUrl())).flatMap { + if (it is ApShowResponse.TypeNote) { + Ok(it.note.toStatus().id) + } else { + Err( + MultiMError( + "The format of the Id($this ${this.getUrl()}) is different.", + null, + ErrorType.API + ) + ) + } + } + } + + +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyTimelineApi.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyTimelineApi.kt new file mode 100644 index 0000000..25d66e1 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyTimelineApi.kt @@ -0,0 +1,80 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import dev.usbharu.multim.api.TimelineApi +import dev.usbharu.multim.error.MultiMError +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.common.MisskeyTimeline +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.NoteConverter.toStatus +import dev.usbharu.multim.misskey.v13.model.StreamRequest.ConnectRequest +import dev.usbharu.multim.misskey.v13.model.StreamRequest.ConnectRequest.Body +import dev.usbharu.multim.misskey.v13.model.StreamRequest.DisconnectRequest +import dev.usbharu.multim.misskey.v13.model.StreamRequest.DisconnectRequest.* +import dev.usbharu.multim.misskey.v13.model.StreamResponse.ChannelResponse.ChannelBody.NoteBody +import dev.usbharu.multim.model.Status +import dev.usbharu.multim.model.Timeline +import java.util.* + +class MisskeyTimelineApi(private val misskeyApis: MisskeyApis) : TimelineApi { + override suspend fun availableTimelines(): Result, MultiMError> { + fun uuid() = UUID.randomUUID().toString() + + return Ok( + listOf( + MisskeyTimeline(uuid(), "homeTimeline", Body.Channel.HOME_TIMELINE), + MisskeyTimeline(uuid(), "hybridTimeline", Body.Channel.HYBRID_TIMELINE), + MisskeyTimeline(uuid(), "localTimeline", Body.Channel.LOCAL_TIMELINE), + MisskeyTimeline(uuid(), "globalTimeline", Body.Channel.GLOBAL_TIMELINE) + ) + ) + } + + override suspend fun listen( + timeline: Timeline, + callback: (List) -> Unit + ): Result { + if (timeline is MisskeyTimeline) { + misskeyApis.timeline.connectChannel( + ConnectRequest( + Body( + timeline.id, + timeline.channel + ) + ) + ) { channelBody -> + if (channelBody is NoteBody) { + callback.invoke(listOf(channelBody.body.toStatus())) + } + } + } + return Ok(Unit) + } + + override suspend fun connect(timeline: Timeline): Result { + if (timeline is MisskeyTimeline) { + misskeyApis.timeline.connectChannel( + ConnectRequest( + Body( + timeline.id, + timeline.channel + ) + ) + ) + } + return Ok(Unit) + } + + override suspend fun disconnect(timeline: Timeline, force: Boolean): Result { + if (timeline is MisskeyTimeline) { + misskeyApis.timeline.disconnectChannel( + DisconnectRequest( + Body( + timeline.id + ) + ) + ) + } + return Ok(Unit) + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/NoteConverter.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/NoteConverter.kt new file mode 100644 index 0000000..478613e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/NoteConverter.kt @@ -0,0 +1,54 @@ +package dev.usbharu.multim.misskey.v13.converter.misskey.v12 + +import dev.usbharu.multim.misskey.v13.common.MisskeyAccount +import dev.usbharu.multim.misskey.v13.common.MisskeyAvatar +import dev.usbharu.multim.misskey.v13.common.MisskeyContent +import dev.usbharu.multim.misskey.v13.common.MisskeyFile +import dev.usbharu.multim.misskey.v13.common.MisskeyFiles +import dev.usbharu.multim.misskey.v13.common.MisskeyStatus +import dev.usbharu.multim.misskey.v13.converter.misskey.v12.ReactionConverter.toReactions +import dev.usbharu.multim.misskey.v13.common.MisskeyStatusId +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.misskey.v13.model.components.UserLite +import dev.usbharu.multim.model.Status + +object NoteConverter { + fun Note.toStatus(): MisskeyStatus { + return MisskeyStatus( + id = MisskeyStatusId(id, url.orEmpty()), + account = MisskeyAccount( + id = user.id, + screenName = user.name ?: user.username, + accountName = user.username, + isBot = user.isBot, + avatar = MisskeyAvatar(avatarUrl = user.avatarUrl.orEmpty()) + ), + content = MisskeyContent(text.orEmpty()), + files = files?.map { MisskeyFile(byteArrayOf(), it.type, it.url.orEmpty()) } + ?.let { MisskeyFiles(it) }, + reactions = reactions.toReactions(this), + repostCount = renoteCount, + repliesCount = repliesCount, + reposted = false, + createdAt = createdAt + ) + } + + fun Note.Companion.fromStatus(status: Status): Note { + if (status is MisskeyStatus) { + return Note( + id = status.id.id, + text = status.content.text, + createdAt = status.createdAt, + userId = status.account.id, + user = UserLite( + id = status.account.id, + name = status.account.screenName, + username = status.account.accountName + ) + ) + } else { + TODO() + } + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/ReactionConverter.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/ReactionConverter.kt new file mode 100644 index 0000000..14f061a --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/ReactionConverter.kt @@ -0,0 +1,43 @@ +package dev.usbharu.multim.misskey.v13.converter.misskey.v12 + +import com.github.michaelbull.result.getOrElse +import com.github.michaelbull.result.map +import dev.usbharu.multim.api.EmojiApi +import dev.usbharu.multim.misskey.v13.common.MisskeyReaction +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.misskey.v13.model.components.NoteReaction +import dev.usbharu.multim.misskey.v13.model.components.Reactions +import dev.usbharu.multim.model.Emoji +import dev.usbharu.multim.model.Reaction + +object ReactionConverter { + fun NoteReaction.toReaction(note: Note): Reaction { + val split = type.replace(":", "").split("@") + return MisskeyReaction( + split[0], + note.emojis.entries.find { emojiLite -> emojiLite.key == type }?.value + ) + } + + fun Reactions.toReactions(note: Note): Map { + return map { + MisskeyReaction( + it.key, + note.emojis.entries.find { emojiLite -> emojiLite.key == it.key }?.value + ) to it.value + }.toMap() + } + + suspend fun Reactions.toReactions(emojiApi: EmojiApi): Map { + return map { entries -> + emojiApi.get(entries.key) + .map { emoji: Emoji -> + MisskeyReaction(emoji.name, emoji.url) + }.map { misskeyReaction -> + misskeyReaction to entries.value + } + }.map { + it.getOrElse { null } + }.filterNotNull().toMap() + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/UsersConverter.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/UsersConverter.kt new file mode 100644 index 0000000..4b181f2 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/converter/misskey/v12/UsersConverter.kt @@ -0,0 +1,78 @@ +package dev.usbharu.multim.misskey.v13.converter.misskey.v12 + +import dev.usbharu.multim.misskey.v13.model.UsersRelationResponse +import dev.usbharu.multim.misskey.v13.common.MisskeyAccount +import dev.usbharu.multim.misskey.v13.common.MisskeyAvatar +import dev.usbharu.multim.misskey.v13.common.MisskeyContent +import dev.usbharu.multim.misskey.v13.common.MisskeyField +import dev.usbharu.multim.misskey.v13.common.MisskeyProfile +import dev.usbharu.multim.misskey.v13.common.MisskeyRelation +import dev.usbharu.multim.misskey.v13.model.components.Field +import dev.usbharu.multim.misskey.v13.model.components.MeDetailed +import dev.usbharu.multim.misskey.v13.model.components.User +import dev.usbharu.multim.misskey.v13.model.components.UserDetailedNotMe +import dev.usbharu.multim.misskey.v13.model.components.UserLite + +object UsersConverter { + fun UsersRelationResponse.toRelation( + myself: MisskeyAccount, + other: MisskeyAccount + ): MisskeyRelation { + + return MisskeyRelation(myself, other, isFollowing, isFollowed, isMuted, isBlocked) + } + + fun User.toProfile(): MisskeyProfile { + return when (this) { + is MeDetailed -> { + MisskeyProfile( + MisskeyAccount( + this.id, + this.name ?: "null", + this.username, + this.isBot, + MisskeyAvatar(this.avatarUrl ?: "null") + ), + this.isBot, + MisskeyContent(this.description ?: "null"), + this.followingCount, + this.followersCount, + this.fields.map { it.toField() } + ) + } + + is UserDetailedNotMe -> { + MisskeyProfile( + MisskeyAccount( + this.id, + this.name ?: "null", + this.username, + this.isBot, + MisskeyAvatar(this.avatarUrl ?: "null") + ), + this.isBot, + MisskeyContent(this.description ?: "null"), + this.followingCount, + this.followersCount, + this.fields.map { it.toField() } + ) + } + + is UserLite -> { + MisskeyProfile( + MisskeyAccount( + this.id, + this.name ?: "null", + this.username, + this.isBot, + MisskeyAvatar(this.avatarUrl ?: "null") + ), this.isBot ?: false, MisskeyContent("ERROR NO INFO") + ) + } + } + } + + fun Field.toField(): MisskeyField { + return MisskeyField(this.name, this.value) + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/ApShow.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/ApShow.kt new file mode 100644 index 0000000..30e78f5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/ApShow.kt @@ -0,0 +1,28 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.misskey.v13.model.components.UserDetailedNotMe +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ApShowRequest( + val uri: String +) : MisskeyNeedAuth() + + +@Serializable +sealed class ApShowResponse { + @SerialName("User") + @Serializable + data class TypeUser( + @SerialName("object") val user: UserDetailedNotMe + ) : ApShowResponse() + + @SerialName("Note") + @Serializable + data class TypeNote( + @SerialName("object") val note: Note + ) : ApShowResponse() +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/Drive.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/Drive.kt new file mode 100644 index 0000000..2dde38e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/Drive.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class DriveResponse( + val capacity: Long, + val usage: Long +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFiles.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFiles.kt new file mode 100644 index 0000000..857e1d7 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFiles.kt @@ -0,0 +1,16 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesRequest( + val limit: Int = 10, + val sinceId: String, + val untilId: String, + val folderId: String? = null, + val type: String? = null +) : MisskeyNeedAuth() + +typealias DriveFilesResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesAttachedNotes.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesAttachedNotes.kt new file mode 100644 index 0000000..a35fdac --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesAttachedNotes.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesAttachedNotesRequest( + val fileId: String +) : MisskeyNeedAuth() + +typealias DriveFilesAttachedNotesResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesCheckExistence.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesCheckExistence.kt new file mode 100644 index 0000000..770820f --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesCheckExistence.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesCheckExistenceRequest( + val md5: String +) : MisskeyNeedAuth() + +typealias DriveFilesCheckExistenceResponse = Boolean diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesCreate.kt new file mode 100644 index 0000000..a1e29f1 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesCreate.kt @@ -0,0 +1,17 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesCreateRequest( + val folderId: String? = null, + val name: String? = null, + val comment: String? = null, + val isSensitive: Boolean = false, + val force: Boolean = false, + val file: ByteArray +) : MisskeyNeedAuth() + +typealias DriveFilesCreateResponse = DriveFile diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesDelete.kt new file mode 100644 index 0000000..16e9978 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesDelete.kt @@ -0,0 +1,8 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesDeleteRequest( + val fileId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesFind.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesFind.kt new file mode 100644 index 0000000..a55d8b8 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesFind.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesFindRequest( + val name: String, + val folderId: String? = null +) : MisskeyNeedAuth() + +typealias DriveFilesFindResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesFindByHash.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesFindByHash.kt new file mode 100644 index 0000000..5cb9d0b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesFindByHash.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesFindByHashRequest( + val md5: String +) + +typealias DriveFilesFindByHashResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesShow.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesShow.kt new file mode 100644 index 0000000..63f9b7b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesShow.kt @@ -0,0 +1,16 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesShowRequestByFileId( + val fileId: String +) + +@Serializable +data class DriveFilesShowRequestByUrl( + val url: String +) + +typealias DriveFilesShowResponse = DriveFile diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesUpdate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesUpdate.kt new file mode 100644 index 0000000..3f0f82c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesUpdate.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesUpdateRequest( + val fileId: String, + val folderId: String? = null, + val name: String, + val isSensitive: Boolean, + val comment: String? = null +) + +typealias DriveFilesUpdateResponse = DriveFile diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesUploadFromUrl.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesUploadFromUrl.kt new file mode 100644 index 0000000..2fba217 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFilesUploadFromUrl.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFilesUploadFromUrlRequest( + val url: String, + val folderId: String? = null, + val isSensitive: Boolean = false, + val comment: String? = null, + val marker: String? = null, + val force: Boolean = false +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFolders.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFolders.kt new file mode 100644 index 0000000..af740d5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFolders.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFolder +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFoldersRequest( + val limit: Int, + val sinceId: String, + val untilId: String, + val folderId: String? = null +) + +typealias DriveFoldersResponse = DriveFolder diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersCreate.kt new file mode 100644 index 0000000..01b7531 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersCreate.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFolder +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFoldersCreateRequest( + val name: String = "Untitled", + val parentId: String? = null +) + +typealias DriveFoldersCreateResponse = DriveFolder diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersDelete.kt new file mode 100644 index 0000000..c61e3ee --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersDelete.kt @@ -0,0 +1,8 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFoldersDeleteRequest( + val folderId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersFind.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersFind.kt new file mode 100644 index 0000000..bfd73d5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersFind.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFolder +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFoldersFindRequest( + val name: String, + val parentId: String? = null +) + +typealias DriveFoldersFindResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersShow.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersShow.kt new file mode 100644 index 0000000..dd111c3 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersShow.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFolder +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFoldersShowRequest( + val folderId: String +) + +typealias DriveFoldersShowResponse = DriveFolder diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersUpdate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersUpdate.kt new file mode 100644 index 0000000..3b166c6 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveFoldersUpdate.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFolder +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFoldersUpdateRequest( + val folderId: String, + val name: String, + val parentId: String? = null +) + +typealias DriveFoldersUpdateResponse = DriveFolder diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveStream.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveStream.kt new file mode 100644 index 0000000..a1104a0 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/DriveStream.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.DriveFile +import kotlinx.serialization.Serializable + +@Serializable +data class DriveStreamRequest( + val limit: Int = 10, + val sinceId: String, + val untilId: String, + val type: String +) + +typealias DriveStreamResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingCreate.kt new file mode 100644 index 0000000..9f60449 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingCreate.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.UserLite + +@kotlinx.serialization.Serializable +data class FollowingCreateRequest( + val userId: String +) : MisskeyNeedAuth() + +typealias FollowingCreateResponse = UserLite diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingDelete.kt new file mode 100644 index 0000000..716ca47 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingDelete.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.UserLite + +@kotlinx.serialization.Serializable +data class FollowingDeleteRequest( + val userId: String +) : MisskeyNeedAuth() + +typealias FollowingDeleteResponse = UserLite diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingInvalidate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingInvalidate.kt new file mode 100644 index 0000000..258962f --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingInvalidate.kt @@ -0,0 +1,10 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.UserLite + +@kotlinx.serialization.Serializable +data class FollowingInvalidateRequest( + val userId: String +) + +typealias FollowingInvalidateResponse = UserLite diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsAccept.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsAccept.kt new file mode 100644 index 0000000..e175d75 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsAccept.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.model + +@kotlinx.serialization.Serializable +data class FollowingRequestsAcceptRequest( + val userId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsCancel.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsCancel.kt new file mode 100644 index 0000000..e1fcf94 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsCancel.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.model + +@kotlinx.serialization.Serializable +data class FollowingRequestsCancelRequest( + val userId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsList.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsList.kt new file mode 100644 index 0000000..8d58385 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsList.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.UserLite + +typealias FollowingRequestsListResponse = List + + +// todo なんか変なので治す +@kotlinx.serialization.Serializable +data class FollowingRequestsList( + val id: String, + val follower: UserLite, + val followee: UserLite +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsReject.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsReject.kt new file mode 100644 index 0000000..583f64c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/FollowingRequestsReject.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.model + +@kotlinx.serialization.Serializable +data class FollowingRequestsRejectRequest( + val userId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/II.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/II.kt new file mode 100644 index 0000000..e8e6ad0 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/II.kt @@ -0,0 +1,10 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MeDetailed +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +class IIRequest : MisskeyNeedAuth() + +typealias IIResponse = MeDetailed diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/Meta.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/Meta.kt new file mode 100644 index 0000000..e4f87a6 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/Meta.kt @@ -0,0 +1,66 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Emoji +import kotlinx.serialization.Serializable + +@Serializable +data class MetaRequest(val detail: Boolean = true) + +@Serializable +data class MetaResponse( + val maintainerName: String? = null, + val maintainerEmail: String? = null, + val version: String, + val name: String? = null, + val uri: String, + val description: String? = null, + val langs: List = listOf(), + val tosUrl: String? = null, + val repositoryUrl: String = "https://github.com/misskey-dev/misskey", + val feedbackUrl: String = "https://github.com/misskey-dev/misskey/issues/new", + val defaultDarkTheme: String? = null, + val defaultLightTheme: String? = null, + val disableRegistration: Boolean, + val cacheRemoteFiles: Boolean, + val emailRequiredForSignup: Boolean, + val enableHcaptcha: Boolean, + val hcaptchaSiteKey: String? = null, + val enableRecaptcha: Boolean, + val recaptchaSiteKey: String? = null, + val swPublickey: String? = null, + val mascotImageUrl: String = "/assets/ai.png", + val bannerUrl: String? = null, + val errorImageUrl: String = "https://xn--p31a.moe/aiart/yubitun.png", + val iconUrl: String? = null, + val maxNoteTextLength: Long, + val ads: List = listOf(), + val requireSetup: Boolean, + val enableEmail: Boolean, + val enableServiceWorker: Boolean, + val translatorAvailable: Boolean, + val proxyAccountName: String? = null, + val policies: Policies +) { + @Serializable + data class Ad(val place: String, val url: String, val imageUrl: String) + + @Serializable + data class Policies( + val gtlAvailable: Boolean = true, + val ltlAvailable: Boolean = true, + val canPublicNote: Boolean = true, + val canInvite: Boolean = true, + val canManageCustomEmojis: Boolean = false, + val canHideAds: Boolean = false, + val driveCapacityMb: Long = 100, + val pinLimit: Long = 5, + val antennaLimit: Long = 5, + val wordMuteLimit: Long = 200, + val webhookLimit:Long = 3, + val clipLimit:Long = 10, + val noteEachClipsLimit:Long = 200, + val userListLimit:Long = 10, + val userEachUserListsLimit:Long = 50, + val rateLimitFactor:Double = 1.0 + ) +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/MiauthCheck.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/MiauthCheck.kt new file mode 100644 index 0000000..412fb08 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/MiauthCheck.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.User +import kotlinx.serialization.Serializable + +@Serializable +data class MiauthCheckResponse( + val ok: Boolean, + val token: String? = null, + val user: User? = null +) + +data class MiauthCheckRequest( + val sessionId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesChildren.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesChildren.kt new file mode 100644 index 0000000..70d6977 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesChildren.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesChildrenRequest( + val noteId: String, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null +) + +typealias NotesChildrenResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesConversation.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesConversation.kt new file mode 100644 index 0000000..cf8ae7e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesConversation.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesConversationRequest( + val noteId: String, + val limit: Int = 10, + val offset: Int = 0 +) + +typealias NotesConversationResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesCreate.kt new file mode 100644 index 0000000..7bc2765 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesCreate.kt @@ -0,0 +1,75 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Notes create request + * + * 組み合わせに対して、安全ではないです。 + * + * @property visibility + * @property visibleUserIds + * @property text + * @property cw + * @property localOnly + * @property noExtractMentions + * @property noExtractHashTag + * @property noExtractEmojis + * @property fileIds + * @property mediaIds + * @property replyId + * @property renoteId + * @property channelId + * @property poll + * @constructor Create empty Notes create request + */ +@Serializable +data class NotesCreateRequest( + val visibility: Visibility = Visibility.PUBLIC, + val visibleUserIds: Set = setOf(), + val text: String? = null, + val cw: String? = null, + val localOnly: Boolean = false, + val noExtractMentions: Boolean = false, + val noExtractHashTag: Boolean = false, + val noExtractEmojis: Boolean = false, + val fileIds: Set? = null, + @Deprecated("Use fileIds instead. If both are specified, this property is discarded.") + val mediaIds: Set? = null, + val replyId: String? = null, + val renoteId: String? = null, + val channelId: String? = null, + val poll: Poll? = null, + + ) : MisskeyNeedAuth() { + @Serializable + enum class Visibility { + @SerialName("public") + PUBLIC, + + @SerialName("home") + HOME, + + @SerialName("followers") + FOLLOWERS, + + @SerialName("specified") + SPECIFIED + } + + @Serializable + data class Poll( + val choices: Set, + val multiple: Boolean = false, + val expiresAt: Long? = null, + val expiredAfter: Long? = null + ) +} + +@Serializable +data class NotesCreateResponse( + val createdNote: Note +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesDelete.kt new file mode 100644 index 0000000..60e1b71 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesDelete.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesDeleteRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFavoritesCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFavoritesCreate.kt new file mode 100644 index 0000000..5ddfbff --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFavoritesCreate.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesFavoritesCreateRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFavoritesDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFavoritesDelete.kt new file mode 100644 index 0000000..a5e6e61 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFavoritesDelete.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesFavoritesDeleteRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFeatured.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFeatured.kt new file mode 100644 index 0000000..414643b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesFeatured.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesFeaturedRequest( + val limit: Int = 10, + val offset: Int = 0 +) + +typealias NotesFeaturedResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesGlobalTimeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesGlobalTimeline.kt new file mode 100644 index 0000000..b011847 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesGlobalTimeline.kt @@ -0,0 +1,16 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesGlobalTimelineRequest( + val withFiles: Boolean = false, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val sinceDate: Long? = null, + val untilDate: Long? = null +) + +typealias NotesGlobalTimelineResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesHybridTimeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesHybridTimeline.kt new file mode 100644 index 0000000..975960a --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesHybridTimeline.kt @@ -0,0 +1,59 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +@Serializable +data class NotesHybridTimelineRequest( + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val sinceDate: Long? = null, + val untilDate: Long? = null, + val includeMyRenotes: Boolean = true, + val includeRenotedMyNotes: Boolean = true, + val includeLocalRenotes: Boolean = true, + val withFiles: Boolean = false +) : MisskeyNeedAuth() + + +@Serializable(with = NotesHybridTimelineResponseSerializer::class) +data class NotesHybridTimelineResponse(private val content: List) : List by content { + override fun equals(other: Any?): Boolean = content == other + override fun hashCode(): Int = content.hashCode() + override fun toString() = content.joinToString(prefix = "[", postfix = "]", separator = ",") +} + +@Serializer(forClass = NotesHybridTimelineResponse::class) +object NotesHybridTimelineResponseSerializer : KSerializer { + + private object NotesHybridTimelineResponseDescriptor : + SerialDescriptor by ListSerializer(Note.serializer()).descriptor { + override val serialName: String = + "dev.usbharu.multim.model.misskey.v12.NotesHybridTimeLineResponse" + } + + override val descriptor: SerialDescriptor = + NotesHybridTimelineResponseDescriptor + + + override fun deserialize(decoder: Decoder): NotesHybridTimelineResponse { + return NotesHybridTimelineResponse( + ListSerializer(Note.serializer()).deserialize( + decoder + ) + ) + } + + override fun serialize(encoder: Encoder, value: NotesHybridTimelineResponse) { + ListSerializer(Note.serializer()).serialize(encoder, value) + } + +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesLocalTimeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesLocalTimeline.kt new file mode 100644 index 0000000..e69c6f5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesLocalTimeline.kt @@ -0,0 +1,18 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesLocalTimelineRequest( + val withFiles: Boolean = false, + val fileType: List = emptyList(), + val excludeNsfw: Boolean? = false, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val sinceDate: Long? = null, + val untilDate: Long? = null +) + +typealias NotesLocalTimelineResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesMentions.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesMentions.kt new file mode 100644 index 0000000..cd65bf4 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesMentions.kt @@ -0,0 +1,16 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesMentionsRequest( + val following: Boolean = false, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val visibility: String? = null +) : MisskeyNeedAuth() + +typealias NotesMentionsResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesNotes.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesNotes.kt new file mode 100644 index 0000000..aeb19c7 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesNotes.kt @@ -0,0 +1,19 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + + +@Serializable +data class NotesNotesRequest( + val local: Boolean = false, + val reply: Boolean? = null, + val renote: Boolean? = null, + val withFiles: Boolean? = null, + val poll: Boolean? = null, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null +) + +typealias NotesNotesResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesPollsRecommendation.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesPollsRecommendation.kt new file mode 100644 index 0000000..8711faf --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesPollsRecommendation.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class PollsRecommendationRequest( + val limit: Int = 10, + val offset: Int = 0 +) + +typealias PollsRecommendationResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesPollsVote.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesPollsVote.kt new file mode 100644 index 0000000..8f77db9 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesPollsVote.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class NotesPollsVoteRequest( + val noteId: String, + val choice: Int +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactionCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactionCreate.kt new file mode 100644 index 0000000..5c17b2c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactionCreate.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class NotesReactionCreateRequest( + val noteId: String, + val reaction: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactionDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactionDelete.kt new file mode 100644 index 0000000..9513301 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactionDelete.kt @@ -0,0 +1,8 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class NotesReactionDeleteRequest( + val noteId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactions.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactions.kt new file mode 100644 index 0000000..7edeea5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReactions.kt @@ -0,0 +1,16 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.NoteReaction +import kotlinx.serialization.Serializable + +@Serializable +data class NotesReactionsRequest( + val noteId: String, + val type: String? = null, + val limit: Int = 10, + val offset: Int = 0, + val sinceId: String? = null, + val untilId: String? = null +) + +typealias NotesReactionsResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesRenote.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesRenote.kt new file mode 100644 index 0000000..76383d4 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesRenote.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesRenoteRequest( + val noteId: String, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null +) + +typealias NotesRenoteResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReplies.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReplies.kt new file mode 100644 index 0000000..b07f338 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesReplies.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesRepliesRequest( + val noteId: String, + val sinceId: String? = null, + val untilId: String? = null, + val limit: Int = 10 +) + +typealias NotesRepliesResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesSearch.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesSearch.kt new file mode 100644 index 0000000..14de614 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesSearch.kt @@ -0,0 +1,19 @@ +package dev.usbharu.multim.misskey.v13.model + + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesSearchRequest( + val query: String, + val sinceId: String? = null, + val untilId: String? = null, + val limit: Int = 10, + val offset: Int = 0, + val host: String? = null, + val userId: String? = null, + val channelId: String? = null +) + +typealias NotesSearchResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesSearchByTag.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesSearchByTag.kt new file mode 100644 index 0000000..a771d2f --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesSearchByTag.kt @@ -0,0 +1,24 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +/** + * Notes search by tag request + * + * @property tag No Empty + * @constructor Create empty Notes search by tag request + */ +@Serializable +data class NotesSearchByTagRequest( + val tag: String, + val reply: Boolean? = null, + val renote: Boolean? = null, + val withFiles: Boolean = false, + val poll: Boolean? = null, + val sinceId: String? = null, + val untilId: String? = null, + val limit: Int = 10 +) + +typealias NotesSearchByTagResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesShow.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesShow.kt new file mode 100644 index 0000000..0fd7295 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesShow.kt @@ -0,0 +1,11 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesShowRequest( + val noteId: String +) + +typealias NotesShowResponse = Note diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesState.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesState.kt new file mode 100644 index 0000000..0086a5e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesState.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesStateRequest( + val noteId: String, +) : MisskeyNeedAuth() + +@Serializable +data class NotesStateResponse( + val isFavorited: Boolean, + val isMutedThread: Boolean +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesThreadMutingCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesThreadMutingCreate.kt new file mode 100644 index 0000000..7b42de1 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesThreadMutingCreate.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesThreadMutingCreateRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesThreadMutingDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesThreadMutingDelete.kt new file mode 100644 index 0000000..a5e0e8f --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesThreadMutingDelete.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesThreadMutingDeleteRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesTimeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesTimeline.kt new file mode 100644 index 0000000..bc806c7 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesTimeline.kt @@ -0,0 +1,53 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +@Serializable +data class NotesTimelineRequest( + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val sinceDate: Long? = null, + val untilDate: Long? = null, + val includeMyRenotes: Boolean? = true, + val includeRenoteMyNotes: Boolean? = true, + val includeLocalRenotes: Boolean? = true, + val withFiles: Boolean? = false +) : MisskeyNeedAuth() + +@Serializable(with = NotesTimelineResponseSerializer::class) +data class NotesTimelineResponse(private val content: List) : List by content { + override fun equals(other: Any?): Boolean = content == other + override fun hashCode(): Int = content.hashCode() + override fun toString() = content.joinToString(prefix = "[", postfix = "]", separator = ",") +} + +@Serializer(forClass = NotesTimelineResponse::class) +object NotesTimelineResponseSerializer : KSerializer { + + private object NotesTimelineResponseDescriptor : + SerialDescriptor by ListSerializer(Note.serializer()).descriptor { + override val serialName: String = + "dev.usbharu.multim.model.misskey.v12.NotesTimeLineResponse" + } + + override val descriptor: SerialDescriptor = NotesTimelineResponseDescriptor + + + override fun deserialize(decoder: Decoder): NotesTimelineResponse { + return NotesTimelineResponse(ListSerializer(Note.serializer()).deserialize(decoder)) + } + + override fun serialize(encoder: Encoder, value: NotesTimelineResponse) { + ListSerializer(Note.serializer()).serialize(encoder, value) + } + +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesTranslate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesTranslate.kt new file mode 100644 index 0000000..5677e46 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesTranslate.kt @@ -0,0 +1,25 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.Serializable + +@Serializable +data class NotesTranslateRequest( + val noteId: String, + val targetLang: String +) + + +/** + * Notes translate response + * + * 試せないので合ってるかわかりません + * + * @property sourceLang + * @property text + * @constructor Create empty Notes translate response + */ +@Serializable +data class NotesTranslateResponse( + val sourceLang: String? = null, + val text: String? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesUnrenote.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesUnrenote.kt new file mode 100644 index 0000000..60403d6 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesUnrenote.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesUnrenoteRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesUserListTimeline.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesUserListTimeline.kt new file mode 100644 index 0000000..21504a6 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesUserListTimeline.kt @@ -0,0 +1,21 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class NotesUserListTimelineRequest( + val listId: String, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val sinceDate: Long? = null, + val untilDate: Long? = null, + val includeMyRenotes: Boolean = true, + val includeRenotedMyNotes: Boolean = true, + val includeLocalRenoted: Boolean = true, + val withFiles: Boolean = false +) : MisskeyNeedAuth() + +typealias NotesUserListTimelineResponse = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesWatchingCreate.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesWatchingCreate.kt new file mode 100644 index 0000000..bd2c7a5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesWatchingCreate.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesWatchingCreateRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesWatchingDelete.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesWatchingDelete.kt new file mode 100644 index 0000000..ba924a0 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/NotesWatchingDelete.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import kotlinx.serialization.Serializable + +@Serializable +data class NotesWatchingDeleteRequest( + val noteId: String +) : MisskeyNeedAuth() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/StreamRequest.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/StreamRequest.kt new file mode 100644 index 0000000..ccfe5f5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/StreamRequest.kt @@ -0,0 +1,63 @@ +package dev.usbharu.multim.misskey.v13.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +sealed class StreamRequest { + + @SerialName("connect") + @Serializable + data class ConnectRequest( + val body: Body + ) : StreamRequest() { + @Serializable + data class Body( + val id: String, + val channel: Channel + ) { + @Serializable + enum class Channel { + @SerialName("globalTimeline") + GLOBAL_TIMELINE, + + @SerialName("homeTimeline") + HOME_TIMELINE, + + @SerialName("hybridTimeline") + HYBRID_TIMELINE, + + @SerialName("localTimeline") + LOCAL_TIMELINE, + + @SerialName("main") + MAIN + } + } + + } + + @SerialName("channel") + @Serializable + data class ChannelRequest( + val body: Body + ) : StreamRequest() { + @Serializable + sealed class Body( + val id: String + ) { + // todo 送るメッセージ + } + } + + @SerialName("disconnect") + @Serializable + data class DisconnectRequest( + val body: Body + ) : StreamRequest() { + @Serializable + data class Body( + val id: String + ) + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/StreamResponse.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/StreamResponse.kt new file mode 100644 index 0000000..b697a0d --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/StreamResponse.kt @@ -0,0 +1,176 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MessagingMessage +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.misskey.v13.model.components.Notification +import dev.usbharu.multim.misskey.v13.model.components.User +import kotlinx.datetime.Instant +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +sealed class StreamResponse { + @SerialName("channel") + @Serializable + data class ChannelResponse( + val body: ChannelBody + ) : StreamResponse() { + @Serializable + sealed class ChannelBody { + abstract val id: String + + @SerialName("note") + @Serializable + data class NoteBody( + override val id: String, + val body: Note + ) : ChannelBody() + + @SerialName("notification") + @Serializable + data class NotificationBody( + override val id: String, + val body: Notification + ) : ChannelBody() + + @SerialName("mention") + @Serializable + data class MentionBody( + override val id: String, + val body: Note + ) : ChannelBody() + + @SerialName("reply") + @Serializable + data class ReplyBody( + override val id: String, + val body: Note + ) : ChannelBody() + + @SerialName("renote") + @Serializable + data class RenoteBody( + override val id: String, + val body: Note + ) : ChannelBody() + + @SerialName("follow") + @Serializable + data class FollowBody( + override val id: String, + val body: User + ) : ChannelBody() + + @SerialName("followed") + @Serializable + data class FollowedBody( + override val id: String, + val body: User + ) : ChannelBody() + + @SerialName("unfollow") + @Serializable + data class UnfollowBody( + override val id: String, + val body: User + ) : ChannelBody() + + @SerialName("messagingMessage") + @Serializable + data class MessagingMessageBody( + override val id: String, + val body: MessagingMessage + ) : ChannelBody() + + @SerialName("readAllNotifications") + @Serializable + data class ReadAllNotificationsBody( + override val id: String + ) : ChannelBody() + + @SerialName("unreadNotification") + @Serializable + data class UnreadNotification( + override val id: String + ) : ChannelBody() + + @SerialName("unreadMention") + @Serializable + data class UnreadMentionBody( + override val id: String + ) : ChannelBody() + + @SerialName("readAllUnreadMentions") + @Serializable + data class ReadAllUnreadMentionsBody( + override val id: String + ) : ChannelBody() + + @SerialName("unreadSpecifiedNote") + @Serializable + data class UnreadSpecifiedNoteBody( + override val id: String + ) : ChannelBody() + + @SerialName("readAllUnreadSpecifiedNotes") + @Serializable + data class ReadAllUnreadSpecifiedNotesBody( + override val id: String + ) : ChannelBody() + + @SerialName("unreadMessagingMessage") + @Serializable + data class UnreadMessagingMessageBody( + override val id: String + ) : ChannelBody() + + @SerialName("readAllMessagingMessage") + @Serializable + data class ReadAllMessagingMessageBody( + override val id: String + ) : ChannelBody() + } + } + + @SerialName("noteUpdated") + @Serializable + data class NoteUpdatedResponse( + val body: NoteUpdatedBody + ) { + @Serializable + sealed class NoteUpdatedBody { + @SerialName("reacted") + @Serializable + data class Reacted( + val id: String, + val body: ReactedBody + ) : NoteUpdatedBody() { + @Serializable + data class ReactedBody( + val reaction: String, + val userId: String + ) + } + + @SerialName("pollVoted") + @Serializable + data class PollVoted( + val id: String, + val body: PollVotedBody + ) : NoteUpdatedBody() { + @Serializable + data class PollVotedBody( + val choice: Int, + val userId: String + ) + } + + @SerialName("deleted") + @Serializable + data class Deleted( + val deletedAt: Instant + ) + } + + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersNotes.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersNotes.kt new file mode 100644 index 0000000..ad8bf6e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersNotes.kt @@ -0,0 +1,23 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth +import dev.usbharu.multim.misskey.v13.model.components.Note +import kotlinx.serialization.Serializable + +@Serializable +data class UsersNotesRequest( + val userId: String, + val includeReplies: Boolean = true, + val limit: Int = 10, + val sinceId: String? = null, + val untilId: String? = null, + val sinceDate: Long? = null, + val untilDate: Long? = null, + val includeMyRenotes: Boolean? = null, + val withFile: Boolean? = false, + val fileType: List = emptyList(), + val excludeNsfw: Boolean = false +) : MisskeyNeedAuth() + + +typealias UsersNotesResponseV13 = List diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersRelation.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersRelation.kt new file mode 100644 index 0000000..b5a8e39 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersRelation.kt @@ -0,0 +1,18 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.MisskeyNeedAuth + +@kotlinx.serialization.Serializable +data class UsersRelationRequest(val userId: String) : MisskeyNeedAuth() + +@kotlinx.serialization.Serializable +data class UsersRelationResponse( + val id: String, + val isFollowing: Boolean, + val isFollowed: Boolean, + val hasPendingFollowRequestFromYou: Boolean, + val hasPendingFollowRequestToYou: Boolean, + val isBlocking: Boolean, + val isBlocked: Boolean, + val isMuted: Boolean +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersShow.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersShow.kt new file mode 100644 index 0000000..69b372c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/UsersShow.kt @@ -0,0 +1,9 @@ +package dev.usbharu.multim.misskey.v13.model + +import dev.usbharu.multim.misskey.v13.model.components.User + +@kotlinx.serialization.Serializable +data class UsersShowRequest( + val userId: String +) +typealias UsersShowResponseV13 = User diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Antenna.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Antenna.kt new file mode 100644 index 0000000..37a8570 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Antenna.kt @@ -0,0 +1,30 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Antenna( + val id: String, + val createdAt: Instant, + val name: String, + val keywords: List>, + val excludeKeywords: List>, + val src: Src, + val userListId: String?, + val userGroupId: String?, + val users: List, + val caseSensitive: Boolean = false, + val notify: Boolean, + val withReplies: Boolean, + val withFile: Boolean, + val hasUnreadNote: Boolean = false +) { + enum class Src(val string: String) { + HOME("home"), + ALL("all"), + USERS("users"), + LIST("list"), + GROUP("group") + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/App.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/App.kt new file mode 100644 index 0000000..979765a --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/App.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +data class App( + val id: String, + val name: String, + val callbackUrl: String?, + val permission: List, + val secret: String? = null, + val isAuthorized: Boolean? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Blocking.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Blocking.kt new file mode 100644 index 0000000..811c9fa --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Blocking.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Blocking( + val id: String, + val createdAt: Instant, + val blockeeId: String, + val blockee: UserDetailed +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Channel.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Channel.kt new file mode 100644 index 0000000..889df15 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Channel.kt @@ -0,0 +1,18 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Channel( + val id: String, + val createdAt: Instant, + val lastNotedAt: Instant, + val name: String, + val description: String?, + val bannerUrl: String, + val notesCount: Int, + val usersCount: Int, + val isFollowing: Boolean, + val userId: String? +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Clip.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Clip.kt new file mode 100644 index 0000000..c0a8d34 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Clip.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Clip( + val id: String, + val createdAt: Instant, + val userId: String, + val user: UserLite, + val name: String, + val description: String?, + val isPublic: Boolean +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/DriveFile.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/DriveFile.kt new file mode 100644 index 0000000..ef560ce --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/DriveFile.kt @@ -0,0 +1,32 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFile( + val id: String, + val createdAt: Instant, + val name: String, + val type: String, + val md5: String, + val size: Int, + val isSensitive: Boolean, + val blurhash: String?, + val properties: Properties, + val url: String?, + val thumbnailUrl: String?, + val comment: String?, + val folderId: String?, + val folder: DriveFolder? = null, + val userId: String?, + val user: UserLite? +) + +@Serializable +data class Properties( + val width: Int? = null, + val height: Int? = null, + val orientation: Int? = null, + val avgColor: String? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/DriveFolder.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/DriveFolder.kt new file mode 100644 index 0000000..5544fe8 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/DriveFolder.kt @@ -0,0 +1,15 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class DriveFolder( + val id: String, + val createdAt: Instant, + val name: String, + val foldersCount: Int? = null, + val filesCount: Int? = null, + val parentId: String?, + val parent: DriveFolder? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Emoji.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Emoji.kt new file mode 100644 index 0000000..9126b36 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Emoji.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +data class Emoji( + val id: String, + val aliases: List, + val name: String, + val category: String?, + val host: String?, + val url: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/EmojiLite.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/EmojiLite.kt new file mode 100644 index 0000000..588e1b9 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/EmojiLite.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +data class EmojiLite(val name: String, val url: String) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Error.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Error.kt new file mode 100644 index 0000000..bfb430b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Error.kt @@ -0,0 +1,3 @@ +package dev.usbharu.multim.misskey.v13.model.components + +data class Error(val code: String, val message: String, val id: String) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/FederationInstance.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/FederationInstance.kt new file mode 100644 index 0000000..23500ea --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/FederationInstance.kt @@ -0,0 +1,31 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class FederationInstance( + val id: String, + val caughtAt: Instant, + val host: String, + val usersCount: Int, + val noteCount: Int, + val followingCount: Int, + val followersCount: Int, + val latestRequestSentAt: Instant?, + val lastCommunicatedAt: Instant, + val isNotResponding: Boolean, + val isSuspended: Boolean, + val isBlocked: Boolean, + val softwareName: String?, + val softwareVersion: String?, + val openRegistrations: Boolean?, + val name: String?, + val description: String?, + val maintainerName: String?, + val maintainerEmail: String?, + val iconUrl: String?, + val faviconUrl: String?, + val themeColor: String?, + val infoUpdatedAt: Instant? +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Field.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Field.kt new file mode 100644 index 0000000..e8dc97d --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Field.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +data class Field(val name: String, val value: String) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Following.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Following.kt new file mode 100644 index 0000000..fd5d1c0 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Following.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Following( + val id: String, + val createdAt: Instant, + val followeeId: String, + val followee: UserDetailed? = null, + val followerId: String, + val follower: UserDetailed? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/GalleryPost.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/GalleryPost.kt new file mode 100644 index 0000000..0afb32c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/GalleryPost.kt @@ -0,0 +1,19 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class GalleryPost( + val id: String, + val createdAt: Instant, + val updatedAt: Instant, + val title: String, + val description: String?, + val userId: Boolean, + val user: UserLite, + val fileIds: List? = listOf(), + val files: List? = listOf(), + val tags: List? = listOf(), + val isSensitive: Boolean +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Hashtag.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Hashtag.kt new file mode 100644 index 0000000..5310dba --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Hashtag.kt @@ -0,0 +1,14 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +data class Hashtag( + val tag: String, + val mentionedUsersCount: Int, + val mentionedLocalUsersCount: Int, + val mentionedRemoteUserCount: Int, + val attachedUsersCount: Int, + val attachedLocalUsersCount: Int, + val attachedRemoteUsersCount: Int +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MeDetailed.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MeDetailed.kt new file mode 100644 index 0000000..b7b2447 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MeDetailed.kt @@ -0,0 +1,83 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable +@Suppress("LongParameterList") +@Serializable +class MeDetailed( + val id: String, + val name: String?, + val username: String, + val host: String? = null, + val avatarUrl: String? = null, + val avatarBlurhash: String? = null, + val avatarColor: String? = null, + val isAdmin: Boolean = false, + val isModerator: Boolean = false, + val isBot: Boolean, + val isCat: Boolean, + val emojis: Map, + val onlineStatus: OnlineStatus, + val url: String? = null, + val uri: String? = null, + val createdAt: Instant, + val updatedAt: Instant? = null, + val lastFetchedAt: Instant? = null, + val bannerUrl: String? = null, + val bannerBlurhash: String? = null, + val bannerColor: String? = null, + val isLocked: Boolean, + val isSilenced: Boolean, + val isSuspended: Boolean, + val description: String? = null, + val location: String? = null, + val birthday: String? = null, + val lang: String? = null, + val fields: List, + val followersCount: Int, + val followingCount: Int, + val notesCount: Int, + val pinnedNoteIds: List, + val pinnedNotes: List, + val pinnedPageId: String? = null, + val pinnedPage: Page? = null, + val publicReactions: Boolean, + val twoFactorEnabled: Boolean = false, + val usePasswordLessLogin: Boolean = false, + val securityKeys: Boolean = false, + val isFollowing: Boolean? = null, + val isFollowed: Boolean? = null, + val hasPendingFollowRequestFromYou: Boolean? = null, + val hasPendingFollowRequestToYou: Boolean? = null, + val isBlocking: Boolean? = null, + val isBlocked: Boolean? = null, + val isMuted: Boolean? = null, + val avatarId: String?, + val bannerId: String?, + val injectFeaturedNote: Boolean? = null, + val receiveAnnouncementEmail: Boolean? = null, + val alwaysMarkNsfw: Boolean?, + val autoSensitive: Boolean?, + val carefulBot: Boolean?, + val autoAcceptFollowed: Boolean?, + val noCrawle: Boolean?, + val isExplorable: Boolean, + val isDeleted: Boolean, + val hideOnlineStatus: Boolean, + val hasUnreadSpecifiedNotes: Boolean, + val hasUnreadMentions: Boolean, + val hasUnreadAnnouncement: Boolean, + val hasUnreadAntenna: Boolean, + val hasUnreadChannel: Boolean, + val hasUnreadMessagingMessage: Boolean, + val hasUnreadNotification: Boolean, + val hasPendingReceivedFollowRequest: Boolean, + val mutedWords: List>, + val mutedInstances: List, + val mutingNotificationTypes: List, + val emailNotificationTypes: List, + val email: String? = null, + val emailVerified: Boolean? = null, + val securityKeysList: List = emptyList(), + + ) : UserDetailed() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MeDetailedOnly.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MeDetailedOnly.kt new file mode 100644 index 0000000..03a640c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MeDetailedOnly.kt @@ -0,0 +1,41 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +class Integrations + +@Serializable +class SecurityKey + +@Serializable +data class MeDetailedOnly( + val avatarId: String?, + val bannerId: String?, + val injectFeaturedNote: Boolean? = null, + val receiveAnnouncementEmail: Boolean? = null, + val alwaysMarkNsfw: Boolean?, + val autoSensitive: Boolean?, + val carefulBot: Boolean?, + val autoAcceptFollowed: Boolean?, + val noCrawle: Boolean?, + val isExplorable: Boolean, + val isDeleted: Boolean, + val hideOnlineStatus: Boolean, + val hasUnreadSpecifiedNotes: Boolean, + val hasUnreadMentions: Boolean, + val hasUnreadAnnouncement: Boolean, + val hasUnreadAntenna: Boolean, + val hasUnreadChannel: Boolean, + val hasUnreadMessagingMessage: Boolean, + val hasUnreadNotification: Boolean, + val hasPendingReceivedFollowRequest: Boolean, + val integrations: Integrations, + val mutedWords: List>, + val mutedInstances: List, + val mutingNotificationTypes: List, + val emailNotificationTypes: List, + val email: String? = null, + val emailVerified: Boolean? = null, + val securityKeysList: List +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MessagingMessage.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MessagingMessage.kt new file mode 100644 index 0000000..3f56318 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MessagingMessage.kt @@ -0,0 +1,20 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class MessagingMessage( + val id: String, + val createdAt: Instant, + val userId: String, + val text: String?, + val fileId: String, + val file: DriveFile? = null, + val recipientId: String?, + val recipient: UserLite? = null, + val groupId: String?, + val group: UserGroup? = null, + val isRead: Boolean?, + val reads: List? +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MisskeyNeedAuth.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MisskeyNeedAuth.kt new file mode 100644 index 0000000..3158327 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/MisskeyNeedAuth.kt @@ -0,0 +1,6 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +open class MisskeyNeedAuth(internal var i: String = "") diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Muting.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Muting.kt new file mode 100644 index 0000000..1524f91 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Muting.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Muting( + val id: String, + val createdAt: Instant, + val expiresAt: Instant?, + val muteeId: String, + val mutee: UserDetailed +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Note.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Note.kt new file mode 100644 index 0000000..5ba093d --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Note.kt @@ -0,0 +1,62 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient + +@Serializable +data class Note( + val id: String, + val createdAt: Instant, + val text: String? = null, + val cw: String? = null, + val userId: String, + val user: UserLite, + val replyId: String? = null, + val renoteId: String? = null, + @Transient + val reply: Note? = null, + @Transient + val renote: Note? = null, + val isHidden: Boolean? = null, + val visibility: String = "public", + val mentions: List? = listOf(), + val visibleUserIds: List? = listOf(), + val fileIds: List? = listOf(), + val files: List? = listOf(), + val tags: List? = listOf(), + val poll: Poll? = null, + val channelId: String? = null, + val channel: Channel? = null, + val localOnly: Boolean? = null, + val emojis: Map = emptyMap(), + val reactions: Reactions = mapOf(), + val renoteCount: Int = 0, + val repliesCount: Int = 0, + val uri: String? = null, + val url: String? = null, + val myReaction: MyReaction? = null +) { + @Serializable + data class Channel(val id: String, val name: String?) + + @Serializable + class MyReaction + + @Serializable + data class Poll( + val multiple: Boolean, + val expiresAt: Instant? = null, + val expiredAfter: Long? = null, + val choices: Set? = setOf() + ) { + @Serializable + data class Choice( + val text: String, + val votes: Int = 0, + val isVoted: Boolean = false + ) + } +} + +typealias Reactions = Map diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/NoteFavorite.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/NoteFavorite.kt new file mode 100644 index 0000000..660565c --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/NoteFavorite.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class NoteFavorite( + val id: String, + val createdAt: Instant, + val note: Note, + val noteId: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/NoteReaction.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/NoteReaction.kt new file mode 100644 index 0000000..e48c822 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/NoteReaction.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class NoteReaction( + val id: String, + val createdAt: Instant, + val user: UserLite, + val type: String +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Notification.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Notification.kt new file mode 100644 index 0000000..b02c79e --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Notification.kt @@ -0,0 +1,40 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class Notification( + val id: String, + val createdAt: Instant, + val isRead: Boolean, + val type: NotificationType, + val userLite: UserLite? = null, + val userId: String, + val note: Note? = null, + val reaction: String? = null, + val choice: Int? = null, + val invitation: Invitation? = null, + val body: String? = null, + val header: String? = null, + val icon: String? = null +) + +@Serializable +class Invitation + + +enum class NotificationType(val string: String) { + FOLLOW("follow"), + MENTION("mention"), + REPLY("reply"), + RENOTE("renote"), + QUOTE("quote"), + REACTION("reaction"), + POLL_VOTE("pollVote"), + POLL_ENDED("pollEnded"), + RECEIVE_FOLLOW_REQUEST("receiveFollowRequest"), + FOLLOW_REQUEST_ACCEPTED("followRequestAccepted"), + GROUP_INVITED("groupInvited"), + APP("app") +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Page.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Page.kt new file mode 100644 index 0000000..4d3b0fc --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/Page.kt @@ -0,0 +1,25 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Suppress("LongParameterList") +@Serializable +class Page( + val id: String, + val createdAt: Instant, + val updatedAt: Instant, + val title: String, + val name: String, + val summary: String?, + val content: List, + val variables: List, + val userId: String, + val user: UserLite +) + +@Serializable +class Variable + +@Serializable +class Content diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/QueueCount.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/QueueCount.kt new file mode 100644 index 0000000..5309c12 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/QueueCount.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.Serializable + +@Serializable +data class QueueCount( + val waiting: Int, + val active: Int, + val completed: Int, + val failed: Int, + val delayed: Int +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/User.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/User.kt new file mode 100644 index 0000000..5409190 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/User.kt @@ -0,0 +1,18 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonContentPolymorphicSerializer +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.jsonObject + +@Serializable(with = UserSerializer::class) +sealed class User + +object UserSerializer : JsonContentPolymorphicSerializer(User::class) { + override fun selectDeserializer(element: JsonElement): DeserializationStrategy = + when { + "url" in element.jsonObject -> UserDetailed.serializer() + else -> UserLite.serializer() + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailed.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailed.kt new file mode 100644 index 0000000..d695995 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailed.kt @@ -0,0 +1,19 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonContentPolymorphicSerializer +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.jsonObject + +@Serializable(with = UserDetailedSerializer::class) +sealed class UserDetailed : User() + +object UserDetailedSerializer : + JsonContentPolymorphicSerializer(UserDetailed::class) { + override fun selectDeserializer(element: JsonElement): DeserializationStrategy = + when { + "avatarId" in element.jsonObject -> MeDetailed.serializer() + else -> UserDetailedNotMe.serializer() + } +} diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailedNotMe.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailedNotMe.kt new file mode 100644 index 0000000..fc3e57d --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailedNotMe.kt @@ -0,0 +1,84 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class UserDetailedNotMe( + val id: String, + val name: String?, + val username: String, + val host: String? = null, + val avatarUrl: String? = null, + val avatarBlurhash: String? = null, + val avatarColor: String? = null, + val isAdmin: Boolean = false, + val isModerator: Boolean = false, + val isBot: Boolean = false, + val isCat: Boolean = false, + val emojis: Map = emptyMap(), + val onlineStatus: String, + val url: String? = null, + val uri: String? = null, + val createdAt: Instant, + val updatedAt: Instant? = null, + val lastFetchedAt: Instant? = null, + val bannerUrl: String? = null, + val bannerBlurhash: String? = null, + val bannerColor: String? = null, + val isLocked: Boolean = false, + val isSilenced: Boolean = false, + val isSuspended: Boolean = false, + val description: String? = null, + val location: String? = null, + val birthday: String? = null, + val lang: String? = null, + val fields: List = emptyList(), + val followersCount: Int = 0, + val followingCount: Int = 0, + val notesCount: Int = 0, + val pinnedNoteIds: List = emptyList(), + val pinnedNotes: List = emptyList(), + val pinnedPageId: String? = null, + val pinnedPage: Page? = null, + val publicReactions: Boolean, + val twoFactorEnabled: Boolean = false, + val usePasswordLessLogin: Boolean = false, + val securityKeys: Boolean = false, + val isFollowing: Boolean? = null, + val isFollowed: Boolean? = null, + val hasPendingFollowRequestFromYou: Boolean? = null, + val hasPendingFollowRequestToYou: Boolean? = null, + val isBlocking: Boolean? = null, + val isBlocked: Boolean? = null, + val isMuted: Boolean? = null +// val onlineStatus: OnlineStatus, +// val avatarId: String?, +// val bannerId: String?, +// val injectFeaturedNote: Boolean? = null, +// val receiveAnnouncementEmail: Boolean? = null, +// val alwaysMarkNsfw: Boolean?, +// val autoSensitive: Boolean?, +// val carefulBot: Boolean?, +// val autoAcceptFollowed: Boolean?, +// val noCrawle: Boolean?, +// val isExplorable: Boolean, +// val isDeleted: Boolean, +// val hideOnlineStatus: Boolean, +// val hasUnreadSpecifiedNotes: Boolean, +// val hasUnreadMentions: Boolean, +// val hasUnreadAnnouncement: Boolean, +// val hasUnreadAntenna: Boolean, +// val hasUnreadChannel: Boolean, +// val hasUnreadMessagingMessage: Boolean, +// val hasUnreadNotification: Boolean, +// val hasPendingReceivedFollowRequest: Boolean, +// val integrations: Integrations, +// val mutedWords: List>, +// val mutedInstances: List, +// val mutingNotificationTypes: List, +// val emailNotificationTypes: List, +// val email: String? = null, +// val emailVerified: Boolean? = null, +// val securityKeysList: List +) : UserDetailed() diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailedNotMeOnly.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailedNotMeOnly.kt new file mode 100644 index 0000000..8966fc6 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserDetailedNotMeOnly.kt @@ -0,0 +1,42 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class UserDetailedNotMeOnly( + val url: String? = null, + val uri: String? = null, + val createdAt: Instant, + val updatedAt: Instant? = null, + val lastFetchedAt: Instant? = null, + val bannerUrl: String? = null, + val bannerBlurhash: String? = null, + val bannerColor: String? = null, + val isLocked: Boolean, + val isSilenced: Boolean, + val isSuspended: Boolean, + val description: String? = null, + val location: String? = null, + val birthday: String? = null, + val lang: String? = null, + val fields: List, + val followersCount: Int, + val followingCount: Int, + val notesCount: Int, + val pinnedNoteIds: List, + val pinnedNotes: List, + val pinnedPageId: String? = null, + val pinnedPage: Page? = null, + val publicReactions: Boolean, + val twoFactorEnabled: Boolean = false, + val usePasswordLessLogin: Boolean = false, + val securityKeys: Boolean = false, + val isFollowing: Boolean? = null, + val isFollowed: Boolean? = null, + val hasPendingFollowRequestFromYou: Boolean? = null, + val hasPendingFollowRequestToYou: Boolean? = null, + val isBlocking: Boolean? = null, + val isBlocked: Boolean? = null, + val isMuted: Boolean? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserGroup.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserGroup.kt new file mode 100644 index 0000000..828a8f5 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserGroup.kt @@ -0,0 +1,13 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class UserGroup( + val id: String, + val createdAt: Instant, + val name: String, + val ownerId: String, + val userIds: List? = null +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserList.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserList.kt new file mode 100644 index 0000000..1984e1b --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserList.kt @@ -0,0 +1,12 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +data class UserList( + val id: String, + val createdAt: Instant, + val name: String, + val userIds: List? +) diff --git a/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserLite.kt b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserLite.kt new file mode 100644 index 0000000..e504b34 --- /dev/null +++ b/impl/misskeyv13/src/main/kotlin/dev/usbharu/multim/misskey/v13/model/components/UserLite.kt @@ -0,0 +1,33 @@ +package dev.usbharu.multim.misskey.v13.model.components + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserLite( + val id: String, + val name: String?, + val username: String, + val host: String? = null, + val avatarUrl: String? = null, + val avatarBlurhash: String? = null, + val avatarColor: String? = null, + val isAdmin: Boolean = false, + val isModerator: Boolean = false, + val isBot: Boolean? = null, + val isCat: Boolean? = null, + val emojis: Map = emptyMap(), + val onlineStatus: String = "online" +// val onlineStatus: OnlineStatus +) : User() + +enum class OnlineStatus(val string: String) { + @SerialName("unknown") + UNKNOWN("unknown"), + @SerialName("online") + ONLINE("online"), + @SerialName("active") + ACTIVE("active"), + @SerialName("offline") + OFFLINE("offline") +} diff --git a/impl/misskeyv13/src/test/kotlin/MisskeyTestUtil.kt b/impl/misskeyv13/src/test/kotlin/MisskeyTestUtil.kt new file mode 100644 index 0000000..9056b92 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/MisskeyTestUtil.kt @@ -0,0 +1,140 @@ +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import com.github.michaelbull.result.getError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.misskey.v13.model.components.UserLite +import dev.usbharu.multim.model.SingleTokenAuth +import io.ktor.client.* +import io.ktor.client.engine.mock.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.request.* +import io.ktor.http.* +import io.ktor.serialization.kotlinx.json.* +import io.mockk.InternalPlatformDsl.toStr +import kotlinx.datetime.Clock +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject +import org.assertj.core.api.Fail +import org.junit.jupiter.api.Assertions + +@Suppress("EmptyIfBlock") +object MisskeyTestUtil { + + val json = Json { ignoreUnknownKeys = true;isLenient = true } + + const val baseUrl = "https://localhsot/" + + internal fun apiClient(httpClient: HttpClient): MisskeyApiClient { + return MisskeyApiClient(SingleTokenAuth("cdgj2h71"), baseUrl, httpClient) + } + + inline fun createMockHttpClient( + content: T, + checkAuth: Boolean, + url: String? = null, + serializer:SerializationStrategy, + statusCode: HttpStatusCode = HttpStatusCode.OK, + ): HttpClient { + return HttpClient(MockEngine { + if (!checkAuth || "i" in json.parseToJsonElement(it.body.toByteArray().decodeToString()).jsonObject) { + //ok + } else { + Fail.fail("No auth.") + } + if (url == null || it.url.toStr() == url) { + //ok + }else { + Fail.fail("Illegal URL expected: $url actual: ${it.url.toStr()}") + } + + respond( + content = json.encodeToString(serializer,content), + status = statusCode, + headers = headersOf(HttpHeaders.ContentType, "application/json") + ) + }) { + install(ContentNegotiation) { + json(json) + } + } + } + + fun createMockHttpClient( + content: String = "", + contentType: String = "application/json", + statusCode: HttpStatusCode = HttpStatusCode.OK, + checkAuth: Boolean = true, + respond: suspend MockRequestHandleScope.(HttpRequestData) -> HttpResponseData = { + if (checkAuth) { + if ("i" in json.parseToJsonElement( + it.body.toByteArray().decodeToString() + ).jsonObject + ) { + + } else { + Fail.fail("No auth") + } + } + respond( + content = content, + status = statusCode, + headers = headersOf(HttpHeaders.ContentType, contentType) + ) + } + ): HttpClient { + return HttpClient(MockEngine(respond)) { + + install(ContentNegotiation) { + json(json) + } + } + } + + fun checkAuth( + respond: String, + status: HttpStatusCode = HttpStatusCode.OK, + headers: Headers = headersOf() + ): suspend MockRequestHandleScope.(HttpRequestData) -> HttpResponseData { + return { httpRequestData: HttpRequestData -> + val decodeToString = httpRequestData.body.toByteArray().decodeToString() + if ("i" in json.parseToJsonElement(decodeToString).jsonObject) { + respond(respond, status, headers) + } else { + Fail.fail("Not authed") + respondBadRequest() + } + } + } + + fun createFakeNote(id: String, userId: String, username: String, text: String?): Note { + return Note( + id = id, + userId = userId, + user = UserLite(id = userId, name = username, username = username), + text = text, + createdAt = Clock.System.now() + ) + } + + fun createFakeNoteToString( + id: String, + userId: String, + username: String, + text: String? + ): String { + return json.encodeToString(createFakeNote(id, userId, username, text)) + } + + fun assertIsOk(result: Result<*, *>) { + Assertions.assertInstanceOf(Ok::class.java, result, "resultの型がOkではない") + } + + inline fun assertIsErr(result: Result<*, T>) { + Assertions.assertInstanceOf(Err::class.java, result, "resultの型がErrではない") + Assertions.assertInstanceOf(R::class.java, result.getError(), "Errorの型が違う") + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/api/MisskeyApiClientTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/api/MisskeyApiClientTest.kt new file mode 100644 index 0000000..9fc1dc4 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/api/MisskeyApiClientTest.kt @@ -0,0 +1,93 @@ +package dev.usbharu.multim.api + +import MisskeyTestUtil +import dev.usbharu.multim.Logger +import io.ktor.client.* +import io.ktor.client.engine.mock.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.request.* +import io.ktor.http.* +import io.ktor.serialization.kotlinx.json.* +import kotlinx.serialization.encodeToString + +class MisskeyApiClientTest : ApiClientTest() { + override val apiClient: ApiClient + get() { + return MisskeyTestUtil.apiClient(HttpClient(MockEngine { + when (it.url.encodedPath.replaceFirst("/", "")) { + postEmpty_emptyRequest_returnOk -> { + respond(PostEmptyData("data")) + } + + postEmpty_illegalRequest_returnErr -> { + respondBadRequest() + } + + postEmpty_serverError_returnErr -> { + respondError(HttpStatusCode.NotImplemented) + } + + post_request_returnOkWithEchoBody -> { + respond( + it.body.toByteArray().decodeToString(), + HttpStatusCode.OK, + headersOf(HttpHeaders.ContentType, "application/json") + ) + } + + post_IllegalRequest_returnErr -> { + respondBadRequest() + } + + post_serverError_returnErr -> { + respondError(HttpStatusCode.NotImplemented) + } + + postWithoutResponse_request_returnOk -> { + respondOk() + } + + postWithoutResponse_IllegalRequest_returnErr -> { + respondBadRequest() + } + + postWithoutResponse_serverError_returnErr -> { + respondError(HttpStatusCode.NotImplemented) + } + + get_request_returnOk -> { + respond(PostEmptyData("43c56ee1-ad7a-418e-9411-2fcb61b34cf9")) + } + + get_IllegalRequest_returnErr -> { + respondBadRequest() + } + + get_serverError_returnErr -> { + respondError(HttpStatusCode.NotImplemented) + } + + else -> { + Logger.error("不明なエンドポイント ${it.url.encodedPath}") + respondBadRequest() + } + } + }) { + install(ContentNegotiation) { + json(MisskeyTestUtil.json, ContentType.Any) + } + }) + } + + private fun PostEmptyData.toJson(): String { + return DefaultJson.encodeToString(this) + } + + private fun MockRequestHandleScope.respond( + postEmptyData: PostEmptyData, + statusCode: HttpStatusCode = HttpStatusCode.OK, + headers: Headers = headersOf(HttpHeaders.ContentType, "application/json") + ): HttpResponseData { + return respond(postEmptyData.toJson(), statusCode, headers) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ApTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ApTest.kt new file mode 100644 index 0000000..0383827 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ApTest.kt @@ -0,0 +1,197 @@ +@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalCoroutinesApi::class) + +package dev.usbharu.multim.misskey.v13.api + +import MisskeyTestUtil.createFakeNoteToString +import MisskeyTestUtil.createMockHttpClient +import MisskeyTestUtil.json +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.ApShowRequest +import dev.usbharu.multim.misskey.v13.model.ApShowResponse +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.misskey.v13.model.components.UserDetailedNotMe +import dev.usbharu.multim.misskey.v13.model.components.UserLite +import dev.usbharu.multim.model.SingleTokenAuth +import io.ktor.client.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import kotlinx.datetime.Instant +import kotlinx.serialization.decodeFromString +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + + +@OptIn(ExperimentalCoroutinesApi::class) +class ApTest { + val baseUrl = "https://localhost/" + + @Test + fun show_showUserMockRequest_respondTypeUser() = runTest { + //language=JSON + val typeUser = """{ + "type": "User", + "object": { + "id": "54e9d", + "name": "Pvf4U", + "username": "e1zfG7u", + "onlineStatus": "online", + "createdAt": "2023-01-22T12:40:43.000Z", + "publicReactions": false + } +}""" + + val misskeyApiClient = MisskeyApiClient( + SingleTokenAuth("aaaaaaaa"), "https://localhost", createMockHttpClient(typeUser) + ) + val show = Ap(misskeyApiClient).show(ApShowRequest("https://localhost/test/IN7OFhht")) + .failOnError() + assertEquals(json.decodeFromString(typeUser), show) + } + + + @Suppress("LongMethod") + @Test + fun show_userUrl_returnUser() = runTest { + val userDetailedNotMe = UserDetailedNotMe( + id = "Xqxv", + name = "fakeUser", + username = "fakeUserName", + host = "example.com", + avatarUrl = "https://example.com", + avatarBlurhash = "jvwxIWI", + avatarColor = null, + isAdmin = false, + isModerator = false, + isBot = false, + isCat = false, + emojis = emptyMap(), + onlineStatus = "unknown", + url = "https://example.com", + uri = "https://example.com", + createdAt = Instant.parse("2023-03-07T20:33:58.868Z"), + updatedAt = Instant.parse("2023-03-07T20:33:58.868Z"), + lastFetchedAt = Instant.parse("2023-03-07T20:33:58.868Z"), + bannerUrl = null, + bannerBlurhash = null, + bannerColor = null, + isLocked = false, + isSilenced = false, + isSuspended = false, + description = "fake user deskription", + location = null, + birthday = null, + lang = null, + fields = emptyList(), + followersCount = 1, + followingCount = 1, + notesCount = 10, + pinnedNoteIds = emptyList(), + pinnedNotes = emptyList(), + pinnedPageId = null, + pinnedPage = null, + publicReactions = false, + twoFactorEnabled = false, + usePasswordLessLogin = false, + securityKeys = false, + isFollowing = true, + isFollowed = true, + hasPendingFollowRequestFromYou = false, + hasPendingFollowRequestToYou = false, + isBlocking = false, + isBlocked = false, + isMuted = false + ) + val typeUser = ApShowResponse.TypeUser(userDetailedNotMe) + + val apShowResponse = Ap( + apiClient( + createMockHttpClient( + typeUser, + false, + baseUrl + "api/ap/show", ApShowResponse.serializer() + ) + ) + ).show(ApShowRequest("https://example.com")).failOnError() + assertEquals(typeUser, apShowResponse) + } + + @Test + fun show_showNoteRequestMock_respondTypeNote() = runTest { + val typeNote = """ + { + "type": "Note", + "object": ${createFakeNoteToString("gK74q", "us3", "76c", "ioVg")} + } + """.trimIndent() + + val misskeyApiClient = MisskeyApiClient( + SingleTokenAuth("W7Xw8F"), "https://localhost", createMockHttpClient(typeNote) + ) + val show = + Ap(misskeyApiClient).show(ApShowRequest("https://localhost/test/C56WI")).failOnError() + assertEquals(json.decodeFromString(typeNote), show) + } + + @Test + fun show_noteUrl_returnNote() = runTest { + val note = Note( + id = "rKiw2x4", + createdAt = Instant.parse("2023-03-07T20:33:58.868Z"), + text = "fake note", + cw = null, + userId = "A7pFuM", + user = UserLite( + id = "A7pFuM", + name = "fakeUser", + username = "fakeUsername", + host = "example.com", + avatarUrl = "https://exapmple.com", + avatarBlurhash = "CpIBR1B", + avatarColor = null, + isAdmin = false, + isModerator = false, + isBot = false, + isCat = false, + emojis = emptyMap(), + onlineStatus = "online" + ), + replyId = null, + renoteId = null, + reply = null, + renote = null, + isHidden = false, + visibility = "public", + mentions = emptyList(), + visibleUserIds = emptyList(), + fileIds = emptyList(), + files = emptyList(), + tags = emptyList(), + poll = null, + channelId = null, + channel = null, + localOnly = false, + emojis = emptyMap(), + reactions = emptyMap(), + renoteCount = 0, repliesCount = 0, uri = "https://example.com/asjfl" + ) + val typeNote = ApShowResponse.TypeNote(note) + val apShowResponse = + Ap( + apiClient( + createMockHttpClient( + typeNote, + true, + baseUrl + "api/ap/show", + ApShowResponse.serializer() + ) + ) + ).show(ApShowRequest("https://example.com/test/afasfa")).failOnError() + + assertEquals(typeNote, apShowResponse) + } + + private fun apiClient(httpClient: HttpClient): MisskeyApiClient { + return MisskeyApiClient(SingleTokenAuth("cdgj2h71"), baseUrl, httpClient) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ApTestE2E.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ApTestE2E.kt new file mode 100644 index 0000000..4f94da4 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ApTestE2E.kt @@ -0,0 +1,53 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.ApShowRequest +import dev.usbharu.multim.misskey.v13.model.ApShowResponse +import dev.usbharu.multim.misskey.v13.model.NotesNotesRequest +import dev.usbharu.multim.model.SingleTokenAuth +import io.github.artsok.RepeatedIfExceptionsTest +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Assertions + +class ApTestE2E { + + val misskeyApiClient = MisskeyApiClient( + SingleTokenAuth(System.getProperty("multim_misskeyv13_token")), + System.getProperty("multim_misskeyv13_instance"), + MultiM.httpClientWithJson.config {} + ) + + @RepeatedIfExceptionsTest(repeats = 4) +// @Test + fun show_showUserRequest_respondTypeUser() = runBlocking { + val show = + Ap(misskeyApiClient).show( + ApShowRequest( + System.getProperty("multim_misskeyv13_instance") + "@" + I( + misskeyApiClient + ).i().failOnError().username + ) + ) + .failOnError() + delay(1000) + Assertions.assertInstanceOf(ApShowResponse.TypeUser::class.java, show) + } + + @RepeatedIfExceptionsTest(repeats = 4) +// @Test + fun show_showNoteRequest_respondTypeNote() = runBlocking { + val show = + Ap(misskeyApiClient).show( + ApShowRequest( + Notes(misskeyApiClient).notes(NotesNotesRequest()).failOnError().first().uri + ?: Assertions.fail() + ) + ) + .failOnError() + delay(1000) + Assertions.assertInstanceOf(ApShowResponse.TypeNote::class.java, show) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ITestE2E.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ITestE2E.kt new file mode 100644 index 0000000..63c90e0 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/ITestE2E.kt @@ -0,0 +1,23 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.model.SingleTokenAuth +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class ITestE2E { + + val misskeyApiClient = MisskeyApiClient( + SingleTokenAuth(System.getProperty("multim_misskeyv13_token")), + System.getProperty("multim_misskeyv13_instance"), + MultiM.httpClientWithJson.config {} + ) + + @Test + fun iTest() = runTest { + val failOnError = I(misskeyApiClient).i().failOnError() + println(failOnError) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MetaTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MetaTest.kt new file mode 100644 index 0000000..98647bd --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MetaTest.kt @@ -0,0 +1,68 @@ +package dev.usbharu.multim.misskey.v13.api + +import MisskeyTestUtil.apiClient +import MisskeyTestUtil.baseUrl +import MisskeyTestUtil.createMockHttpClient +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.model.MetaRequest +import dev.usbharu.multim.misskey.v13.model.MetaResponse +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class MetaTest { + + @Test + fun meta_detailTrue_returnMeta() = runTest { + val metaResponse = MetaResponse( + maintainerName = "maintainerName", + maintainerEmail = "maintainer@example.com", + version = "12.119.2", + name = "misskey", + uri = "https://example.com", + description = "test instance", + langs = emptyList(), + tosUrl = null, + repositoryUrl = "https://example.com", + feedbackUrl = "https://example.com", + defaultDarkTheme = "darkTheme", + defaultLightTheme = "lightTheme", + disableRegistration = false, + cacheRemoteFiles = true, + emailRequiredForSignup = false, + enableHcaptcha = false, + hcaptchaSiteKey = null, + enableRecaptcha = false, + recaptchaSiteKey = null, + swPublickey = null, + mascotImageUrl = "/assets/ai.png", + bannerUrl = null, + errorImageUrl = "https://example.com", + iconUrl = null, + maxNoteTextLength = 3000, + ads = emptyList(), + requireSetup = false, + enableEmail = false, + enableServiceWorker = false, + translatorAvailable = false, + proxyAccountName = "proxy", + policies = MetaResponse.Policies() + ) + + val response = Meta( + apiClient( + createMockHttpClient( + metaResponse, + false, + baseUrl + "api/meta", + MetaResponse.serializer() + ) + ) + ).meta( + MetaRequest() + ).failOnError() + assertEquals(metaResponse,response) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MetaTestE2E.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MetaTestE2E.kt new file mode 100644 index 0000000..cd06465 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MetaTestE2E.kt @@ -0,0 +1,25 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.MetaRequest +import dev.usbharu.multim.model.SingleTokenAuth +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class MetaTestE2E { + + private val misskeyApiClient = MisskeyApiClient( + SingleTokenAuth(System.getProperty("multim_misskeyv13_token")), + System.getProperty("multim_misskeyv13_instance"), + MultiM.httpClientWithJson.config {} + ) + + @Test + fun meta() = runTest { + Meta(misskeyApiClient).meta(MetaRequest()).failOnError() + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MiauthTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MiauthTest.kt new file mode 100644 index 0000000..c924d71 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/MiauthTest.kt @@ -0,0 +1,21 @@ +package dev.usbharu.multim.misskey.v13.api + +import kotlinx.coroutines.* +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class MiauthTest { + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + @Disabled + fun auth() = runTest { + } + + @Test + @Disabled + fun check() = runTest { + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/NotesTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/NotesTest.kt new file mode 100644 index 0000000..2cd5c3a --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/NotesTest.kt @@ -0,0 +1,188 @@ +@file:OptIn(ExperimentalCoroutinesApi::class) +@file:Suppress("SpellCheckingInspection") + +package dev.usbharu.multim.misskey.v13.api + +import MisskeyTestUtil.createFakeNote +import MisskeyTestUtil.createMockHttpClient +import MisskeyTestUtil.json +import com.github.michaelbull.result.* +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.NotesCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesCreateResponse +import dev.usbharu.multim.misskey.v13.model.NotesDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesGlobalTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesHybridTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesLocalTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesShowRequest +import dev.usbharu.multim.model.SingleTokenAuth +import io.ktor.client.* +import io.ktor.client.engine.mock.* +import io.ktor.client.plugins.* +import io.ktor.http.* +import io.ktor.utils.io.* +import kotlinx.coroutines.* +import kotlinx.coroutines.test.runTest +import kotlinx.datetime.Instant +import kotlinx.serialization.encodeToString +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import java.util.* + +@OptIn(ExperimentalCoroutinesApi::class) +class NotesTest { + + @Test + fun globalTimelineTest() = runTest { + val notes = Notes( + MisskeyApiClient( + SingleTokenAuth("aaaa"), + "", + createMockHttpClient( + checkAuth = false, + content = json.encodeToString(expectNoteArray) + ) + ) + ) + val globalTimeline = + notes.globalTimeline(globalTimelineRequest = NotesGlobalTimelineRequest()).failOnError() + assertEquals(expectNoteArray, globalTimeline) + } + + @Test + fun hybridTimelineTest() = runTest { + val notes = Notes( + MisskeyApiClient( + SingleTokenAuth("aaaa"), + "", + createMockHttpClient(content = json.encodeToString(expectNoteArray)) + ) + ) + val hybridTimeline = notes.hybridTimeline(NotesHybridTimelineRequest()).failOnError() + assertEquals(expectNoteArray, hybridTimeline) + } + + @Test + fun localTimelineTest() = runTest { + val notes = Notes( + MisskeyApiClient( + SingleTokenAuth("aaa"), + "", + createMockHttpClient( + checkAuth = false, + content = json.encodeToString(expectNoteArray) + ) + ) + ) + val localTimeline = notes.localTimeline(NotesLocalTimelineRequest()).failOnError() + assertEquals(expectNoteArray, localTimeline) + } + + @Test + fun showTest() = runTest { + val expectedNote = createFakeNote("mLyakn", "7j1VB0L", "Ymhq", "8V7QrxD6") + val notes = Notes( + MisskeyApiClient( + SingleTokenAuth("aaa"), + "", + createMockHttpClient( + checkAuth = false, + content = json.encodeToString(expectedNote) + ) + ) + ) + val note = notes.show(NotesShowRequest("mLvakn")).failOnError() + assertEquals(expectedNote, note) + } + + @Test + fun createTest() = runTest { + val note = createFakeNote("aT9o", "o00672o", "W2kwto", "gold") + val notes = Notes( + MisskeyApiClient( + SingleTokenAuth("aaa"), + "", + createMockHttpClient(content = json.encodeToString(NotesCreateResponse(note))) + ) + ) + val create = notes.create(NotesCreateRequest(text = "gold")).failOnError() + assertEquals(note, create.createdNote) + } + + @Test + fun deleteTest() = runTest { + val notes = + Notes(MisskeyApiClient(SingleTokenAuth("aaa"), "", createMockHttpClient(content = ""))) + notes.delete(NotesDeleteRequest("Rw4g2CH")) + } + + @Test + fun ldttest() { + Instant.parse("2023-01-17T06:58:08.000Z") + } + +@Suppress("MaxLineLength") + private val expectNoteArray = listOf( + createFakeNote( + "4wT4lSP", + "p9hdK", + "oYDd", + "Lorem ipsum dolor sit amet illum lorem ut magna elit dolore amet consectetuer est odio sadipscing lobortis stet sea. Consetetur consetetur stet ut aliquyam aliquyam ut nam congue gubergren gubergren kasd lorem tempor amet kasd consetetur ipsum. Dolor iriure sit dolore erat sit diam adipiscing odio ipsum ullamcorper erat et. Duis gubergren est." + ), + createFakeNote( + "bFe7t9M", + "v9C", + "T470fU", + "Lorem ipsum dolor sit amet at amet rebum vel dolor amet erat invidunt sed duo sit facilisis magna. Sed gubergren et sed amet minim diam tempor diam facilisi amet ipsum justo eirmod gubergren aliquyam." + ), + createFakeNote( + "0P5Kd4LD", + "t9KO12Q", + "kcK", + "Lorem ipsum dolor sit amet et eirmod justo et ut sadipscing tempor labore amet hendrerit vero. Tincidunt lobortis esse kasd in amet erat aliquyam nonumy takimata adipiscing sit at tation stet ex duo justo tempor." + ), + createFakeNote( + "dy3055V7", + "e1swe9O7", + "9AtX", + "Lorem ipsum dolor sit amet et. Dolores dolore vero at tempor wisi ipsum delenit tempor gubergren et dignissim." + ), + createFakeNote( + "vEv9", + "4xTvOwh", + "T2ES2jYV", + "Lorem ipsum dolor sit amet duis feugait erat sanctus luptatum consetetur nonumy sed at ea." + ), + createFakeNote( + "427AW", + "638oy", + "JEAgxoD", + "Lorem ipsum dolor sit amet nam rebum aliquyam nonumy lorem eos clita. Diam ea zzril at eos dolor gubergren et placerat et gubergren lorem eirmod amet sea dolor." + ), + createFakeNote( + "tfkV4j", + "2bu", + "UxN1", + "Lorem ipsum dolor sit amet et sit accusam gubergren dolor amet magna vel at vero. Iusto gubergren ut euismod feugiat et laoreet aliquyam autem." + ), + createFakeNote( + "ty67", + "5o9JgtBR", + "c99Zv", + "Lorem ipsum dolor sit amet sanctus dolore sit. Augue dolor et ipsum ipsum clita labore diam sanctus no ipsum est sed ex elitr ut." + ), + createFakeNote( + "JOm2U2ci", + "198ZRz8", + "P29WMF9", + "Lorem ipsum dolor sit amet nonumy elitr ipsum facilisis vel euismod gubergren consequat consetetur volutpat vel labore. Dolores dolor stet tempor." + ), + createFakeNote( + "2Nv8RU7W", + "6yv5", + "dHT06", + "Lorem ipsum dolor sit amet at ipsum vero. Et et eirmod tempor diam et sit duo sed dolores." + ) + ) +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/NotesTestE2E.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/NotesTestE2E.kt new file mode 100644 index 0000000..f8ea9fa --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/NotesTestE2E.kt @@ -0,0 +1,398 @@ +package dev.usbharu.multim.misskey.v13.api + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.DriveFilesCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesChildrenRequest +import dev.usbharu.multim.misskey.v13.model.NotesConversationRequest +import dev.usbharu.multim.misskey.v13.model.NotesCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesFavoritesCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesFavoritesDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesGlobalTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesHybridTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesLocalTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesMentionsRequest +import dev.usbharu.multim.misskey.v13.model.NotesNotesRequest +import dev.usbharu.multim.misskey.v13.model.NotesReactionsRequest +import dev.usbharu.multim.misskey.v13.model.NotesRenoteRequest +import dev.usbharu.multim.misskey.v13.model.NotesRepliesRequest +import dev.usbharu.multim.misskey.v13.model.NotesSearchByTagRequest +import dev.usbharu.multim.misskey.v13.model.NotesShowRequest +import dev.usbharu.multim.misskey.v13.model.NotesStateRequest +import dev.usbharu.multim.misskey.v13.model.NotesThreadMutingCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesThreadMutingDeleteRequest +import dev.usbharu.multim.misskey.v13.model.NotesTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesUnrenoteRequest +import dev.usbharu.multim.misskey.v13.model.NotesUserListTimelineRequest +import dev.usbharu.multim.misskey.v13.model.NotesWatchingCreateRequest +import dev.usbharu.multim.misskey.v13.model.NotesWatchingDeleteRequest +import dev.usbharu.multim.model.SingleTokenAuth +import io.github.artsok.RepeatedIfExceptionsTest +import io.ktor.client.plugins.* +import kotlinx.coroutines.* +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.util.* + +@OptIn(ExperimentalCoroutinesApi::class) +class NotesTestE2E { + + private val client = MisskeyApiClient(SingleTokenAuth(System.getProperty("multim_misskeyv13_token")), + System.getProperty("multim_misskeyv13_instance"), + MultiM.httpClientWithJson.config {}) + private val notes = Notes(client) + private val drive = Drive(client) + + @Test + fun globalTimeline() = runTest { + notes.globalTimeline(NotesGlobalTimelineRequest()).failOnError() + } + + @Test + fun hybridTimeline() = runTest { + notes.hybridTimeline(NotesHybridTimelineRequest()).failOnError() + } + + @Test + fun localTimeline() = runTest { + notes.localTimeline(NotesLocalTimelineRequest()).failOnError() + } + + @Test + fun show() = runTest { + notes.show(NotesShowRequest(notes.notes(NotesNotesRequest()).failOnError().first().id)).failOnError() + + } + + @Test + fun create() = runTest { + notes.create( + NotesCreateRequest( + visibility = NotesCreateRequest.Visibility.HOME, + text = "このノートはMultim のテストで作成されました。${this@NotesTestE2E::class} create Test" + ) + ).failOnError() + } + + @Test + fun createFollowOnly() = runTest { + val notesCreateResponse = notes.create( + NotesCreateRequest( + visibility = NotesCreateRequest.Visibility.FOLLOWERS, + text = "このノートはMultiMのテストで作成され、公開範囲 フォロワーのみ のテストに使用されます。" + + " ${this@NotesTestE2E::class} create note with followers only" + ) + ).failOnError() + Assertions.assertEquals("followers", notesCreateResponse.createdNote.visibility) + } + + @Test + fun createWithFile() = runTest { + val encode: ByteArray = withContext(Dispatchers.IO) { + NotesTestE2E::class.java.classLoader.getResourceAsStream("notes/create/files/note_with_file_test.jpg")!! + .readBytes() + } + + val driveFile = drive.Files().create(DriveFilesCreateRequest(file = encode)) + val createdNote = notes.create( + NotesCreateRequest( + text = "このノートはMultiMのテストで作成され、ファイル添付のテストで使用されます。", fileIds = setOf(driveFile.id) + ) + ).failOnError() + + Assertions.assertEquals(driveFile, createdNote.createdNote.files?.firstOrNull()) + } + + @Test + fun createWithPoll() = runTest { + val poll = NotesCreateRequest.Poll(choices = setOf("a", "b", "c")) + val create = notes.create( + NotesCreateRequest( + text = "このノートはMultiMのテストで作成され、投票付きノートの作成で使用されます。 ${this@NotesTestE2E::class} create note with poll", + poll = poll + ) + ).failOnError() + Assertions.assertEquals(poll.choices.map { it }, create.createdNote.poll?.choices?.map { it.text }) + } + + @Test + fun delete() = runTest { + val create = notes.create( + NotesCreateRequest( + visibility = NotesCreateRequest.Visibility.HOME, + text = "このノートはMultim のテストで作成され、削除される予定です。 ${this@NotesTestE2E::class} delete Test" + ) + ) + val deleteNote = when (create) { + is Ok -> create.value.createdNote.id + is Err -> Assertions.fail(create.error.message, create.error._throwable) + } + notes.delete(NotesDeleteRequest(deleteNote)) + Assertions.assertInstanceOf(Err::class.java, notes.show(NotesShowRequest(deleteNote))) + //消せていたら失敗する + + } + + @Test + fun featured() = runTest { + notes.featured().failOnError() + } + + @Test + fun children() = runTest { + val create = notes.create( + NotesCreateRequest( + text = "このノートはMultiMのテストで作成され、" + + "子ノート取得のテストで使用されます。${this@NotesTestE2E::class} children", + ) + ) + val id = create.failOnError().createdNote.id + notes.children(NotesChildrenRequest(id)).failOnError() + } + + @Test + fun conversation() = runTest { + val create = notes.create( + NotesCreateRequest( + text = "このノートはMultiMのテストで作成され、" + + "関連ノート取得のテストで使用されます。 ${this@NotesTestE2E::class} conversation" + ) + ).failOnError() + notes.conversation(NotesConversationRequest(create.createdNote.id)).failOnError() + } + + @Test + fun state() = runTest { + val create = notes.create( + NotesCreateRequest( + text = "このノートはMultiMのテストで作成され、" + + "ノートの状態を取得するテストで使用されます。 ${this@NotesTestE2E::class} state" + ) + ).failOnError() + notes.state(NotesStateRequest(create.createdNote.id)).failOnError() + } + + @Test + fun favoritesCreate() = runTest { + val create = notes.create( + NotesCreateRequest( + text = "このノートはMultim のテストで作成され、" + + "お気に入り登録のテストで使用されます。 ${this@NotesTestE2E::class} favorites create test" + ) + ).failOnError() + NotesFavoritesCreateRequest(create.createdNote.id).let { notes.Favorites().create(it) } + Assertions.assertTrue(NotesStateRequest(create.createdNote.id).let { + notes.state(it).failOnError().isFavorited + }) +//todo ネストがやばいことになってるのでnullが返ってきた時点で失敗にする + } + + @Test + fun favoritesDelete() = runTest { + val result = + notes.create( + NotesCreateRequest( + text = "このノートはMultim のテストで作成され、" + + "お気に入り削除のテストで使用されます。 ${this@NotesTestE2E::class} favorites delete test" + ) + ) + val create = when (result) { + is Ok -> result.value + is Err -> Assertions.fail(result.error.message, result.error._throwable) + } + notes.Favorites().create(NotesFavoritesCreateRequest(create.createdNote.id)) + Assertions.assertTrue(notes.state(NotesStateRequest(create.createdNote.id)).failOnError().isFavorited) + notes.Favorites().delete(NotesFavoritesDeleteRequest(create.createdNote.id)) + Assertions.assertFalse( + notes.state(NotesStateRequest(create.createdNote.id)).failOnError().isFavorited + ) + } + + @Test + fun mentions() = runTest { + val mentions = notes.mentions(NotesMentionsRequest()).failOnError() + } + + @Test + fun reactions() = runTest { + val create = + notes.create( + NotesCreateRequest( + text = "このノートはMultiMのテストで作成され、" + + "リアクション取得のテストで使用されます。 ${this@NotesTestE2E::class} reactions" + ) + ) + .failOnError() + val reactions = notes.reactions(NotesReactionsRequest(create.createdNote.id)) + } + + @Test + fun renotes() = runTest { + val create = + notes.create( + NotesCreateRequest( + text = "このノートはMultim のテストで作成され、" + + "リノートのテストで使用されます。 ${this@NotesTestE2E::class} renotes test" + ) + ) + .failOnError() + val notesCreateResponse = notes.create(NotesCreateRequest(renoteId = create.createdNote.id)).failOnError() + val renotes = NotesRenoteRequest(create.createdNote.id).let { notes.renotes(it) }.failOnError() + Assertions.assertEquals(listOf(notesCreateResponse.createdNote), renotes) + } + + @Test + fun replies() = runTest { + val root = + notes.create( + NotesCreateRequest( + text = "このノートはMultim のテストで作成され、" + + "返信取得のテストで使用されます。 ${this@NotesTestE2E::class} replies test" + ) + ) + .failOnError() + val reply1 = notes.create( + NotesCreateRequest( + text = "返信1 このノートはMultimのテストで作成され、返信取得のテストで使用されます。" + + " ${this@NotesTestE2E::class} replies test", + replyId = root.createdNote.id + ) + ).failOnError() + val reply2 = notes.create( + NotesCreateRequest( + text = "返信2 このノートはMultimのテストで作成され、返信取得のテストで使用されます。 ${this@NotesTestE2E::class} replies test", + replyId = root.createdNote.id + ) + ).failOnError() + val replies = root.createdNote.id.let { NotesRepliesRequest(it) }.let { notes.replies(it) }.failOnError() + Assertions.assertEquals(listOf(reply1.createdNote, reply2.createdNote).sortedBy { note -> note.id }, + replies.sortedBy { note -> note.id }) + } + + @Test + fun searchByTag() = runTest { + val tag = UUID.randomUUID().toString() + val tagedNote = + notes.create( + NotesCreateRequest( + text = "#$tag このノートはMultimのテストで作成され、" + + "タグ検索のテストで使用されます。 ${this@NotesTestE2E::class} search by tag test" + ) + ) + .failOnError() + val searchByTag = notes.searchByTag(NotesSearchByTagRequest(tag)).failOnError() + org.assertj.core.api.Assertions.assertThat(searchByTag)?.isNotEmpty + Assertions.assertTrue(searchByTag.contains(tagedNote.createdNote)) + } + + @Test + fun threadMutingCreate() = runTest { + val create = + notes.create( + NotesCreateRequest( + text = "このノートはMultimのテストで作成され、スレッドミュートのテストで使用されます。 " + + "${this@NotesTestE2E::class} thread mute create test" + ) + ) + .failOnError() + Assertions.assertFalse(NotesStateRequest(create.createdNote.id).let { + notes.state(it).failOnError().isMutedThread + }) + NotesThreadMutingCreateRequest(create.createdNote.id).let { notes.ThreadMuting().create(it) } + Assertions.assertTrue(NotesStateRequest(create.createdNote.id).let { + notes.state(it).failOnError().isMutedThread + }) + } + + @Test + fun threadMutingDelete() = runTest { + val create = + notes.create( + NotesCreateRequest( + text = "このノートはMultimのテストで作成され、スレッドミュート解除のテストで使用されます。 " + + "${this@NotesTestE2E::class} thread mute delete test" + ) + ) + .failOnError() + Assertions.assertFalse( + notes.state(NotesStateRequest(create.createdNote.id)).failOnError().isMutedThread + ) + NotesThreadMutingCreateRequest(create.createdNote.id).let { notes.ThreadMuting().create(it) } + Assertions.assertTrue(NotesStateRequest(create.createdNote.id).let { + notes.state(it).failOnError().isMutedThread + }) + NotesThreadMutingDeleteRequest(create.createdNote.id).let { notes.ThreadMuting().delete(it) } + Assertions.assertFalse(NotesStateRequest(create.createdNote.id).let { + notes.state(it).failOnError().isMutedThread + }) + } + + @Test + fun timeline() = runTest { + val timeline = notes.timeline(NotesTimelineRequest()).failOnError() + } + + @RepeatedIfExceptionsTest(repeats = 4) +// @Test + fun unrenote() = runBlocking { + val create = + notes.create( + NotesCreateRequest( + text = "このノートはMultimのテストで作成され、リノート取り消しのテストで使用されます。" + + " ${this@NotesTestE2E::class} unrenote test" + ) + ) + .failOnError() + delay(1000) + val renoted = notes.create(NotesCreateRequest(renoteId = create.createdNote.id)).failOnError() + delay(1000) + NotesUnrenoteRequest(create.createdNote.id).let { notes.unrenote(it) } + delay(1000) + assertThrows { + NotesShowRequest( + renoted.createdNote.id + ).let { notes.show(it) } + } + + } + + @Test + @Disabled("リスト操作系のAPIが未実装なため無効化") + // TODO: リスト操作系のAPI追加後、リストを取得してテストするように + fun userListTimeline() = runTest { + val userListTimeline = notes.userListTimeline(NotesUserListTimelineRequest("9ady10e6z5")) + } + + @Test + @Disabled("自分以外ということが確定しているノートを取得できない為無効化") + // TODO: 自分以外のノートを取得できるようになってからテストを追加 + fun watchingCreate() = runTest { +// +// val noteId = "9bk3hn1qd0" +// val state = notes.state(NotesStateRequest(noteId)).failOnError() +// if (state.isWatching) { +// notes.Watching().delete(NotesWatchingDeleteRequest(noteId)) +// } +// notes.Watching().create(NotesWatchingCreateRequest(noteId)).failOnError() +// Assertions.assertTrue(notes.state(NotesStateRequest(noteId)).failOnError().isWatching) + } + + @Test + @Disabled("自分以外ということが確定しているノートを取得できない為無効化") + fun watchingDelete() = runTest { +// val noteId = "9bk3hn1qd0" +// val state = notes.state(NotesStateRequest(noteId)).failOnError() +// if (!state.isWatching) { +// notes.Watching().create(NotesWatchingCreateRequest(noteId)) +// } +// notes.Watching().delete(NotesWatchingDeleteRequest(noteId)) +// Assertions.assertFalse(notes.state(NotesStateRequest(noteId)).failOnError().isWatching) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/TimelineTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/TimelineTest.kt new file mode 100644 index 0000000..9632da4 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/api/TimelineTest.kt @@ -0,0 +1,89 @@ +package dev.usbharu.multim.misskey.v13.api + +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.common.api.MisskeyApiClient +import dev.usbharu.multim.misskey.v13.model.NotesCreateRequest +import dev.usbharu.multim.misskey.v13.model.StreamRequest.ConnectRequest +import dev.usbharu.multim.misskey.v13.model.StreamRequest.ConnectRequest.Body +import dev.usbharu.multim.misskey.v13.model.StreamRequest.ConnectRequest.Body.Channel.GLOBAL_TIMELINE +import dev.usbharu.multim.misskey.v13.model.StreamRequest.DisconnectRequest +import dev.usbharu.multim.misskey.v13.model.StreamResponse.ChannelResponse.ChannelBody.NoteBody +import dev.usbharu.multim.misskey.v13.model.components.Note +import dev.usbharu.multim.model.SingleTokenAuth +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import java.util.* +@Suppress("EmptyFunctionBlock") +class TimelineTestE2E { + + + val client = MisskeyApiClient( + SingleTokenAuth(System.getProperty("multim_misskeyv13_token")), + System.getProperty("multim_misskeyv13_instance"), + MultiM.httpClientWithJson.config {} + ) + val timeline = Timeline(client) + val notes = Notes(client) + + val coroutineScope = CoroutineScope(Dispatchers.IO) + + @Test + fun connectChannelTest() = runBlocking { + + val streamNotes = mutableListOf() + val createdNotes = mutableListOf() + client.streaming.connect() + delay(1000) + val uuid = UUID.randomUUID().toString() + timeline.connectChannel(ConnectRequest(Body(uuid, GLOBAL_TIMELINE))) { channelBody -> + if (channelBody is NoteBody) { + if (channelBody.body.tags?.contains(uuid) == true) { + streamNotes.add(channelBody.body) + } + } + } + delay(1000) + repeat(10) { + notes.create(NotesCreateRequest(text = "このノートはMultiMのテストで作成され、Streaming APIのテストで使用されます。#$uuid ")) + .failOnError().createdNote.let { it1 -> + createdNotes.add( + it1 + ) + } + } + delay(2000) + timeline.disconnectChannel(DisconnectRequest(DisconnectRequest.Body(uuid))) + assertEquals( + createdNotes.sortedBy { note -> note.createdAt }, + streamNotes.sortedBy { note -> note.createdAt }) + + } + + + @Test + fun connectChannelCoroutineTest() = runBlocking { + client.streaming.connect() + delay(1000) + timeline.connectChannel(ConnectRequest(Body("aaa", GLOBAL_TIMELINE))) + delay(1000) + timeline.disconnectChannel(DisconnectRequest(DisconnectRequest.Body("aaa"))) + } + + @Test + fun sendToChannelTest() { + + } + + @Test + fun disconnectChannelTest() { + } + + @Test + fun getClientTest() { + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyAccountApiTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyAccountApiTest.kt new file mode 100644 index 0000000..29b3130 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyAccountApiTest.kt @@ -0,0 +1,279 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import com.github.michaelbull.result.get +import com.github.michaelbull.result.getError +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess +import dev.usbharu.multim.Logger +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.api.AccountApi +import dev.usbharu.multim.api.AccountApiTest +import dev.usbharu.multim.error.MultiMHttpError +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.common.MisskeyAccount +import dev.usbharu.multim.misskey.v13.common.MisskeyAvatar +import dev.usbharu.multim.model.SingleTokenAuth +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail +@Suppress("EmptyIfBlock") +@OptIn(ExperimentalCoroutinesApi::class) +class MisskeyAccountApiTest : AccountApiTest() { + override val accountApi: AccountApi + get() = MisskeyAccountApi( + MisskeyApis( + MisskeyApiClient( + SingleTokenAuth(System.getProperty("multim_misskeyv13_token")), + System.getProperty("multim_misskeyv13_instance"), + MultiM.httpClientWithJson + ) + ) + ) + + @Test + override fun userTimeline() = runTest { + accountApi.userTimeline( + MisskeyAccount( + "9cfye6ns6b", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + ).failOnError() + } + + @Test + override fun follow() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val account = MisskeyAccount( + "9cfye6ns6b", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v13.usbharu.dev/identicon/9bk3hbcjcy") + ) + if (accountApi.relationships(myself, account).failOnError().following) { + Logger.warn("すでにフォローされているのでフォローをいったん解除します。") + accountApi.unfollow(account) + } + accountApi.follow(account).failOnError() + assertTrue(accountApi.relationships(myself, account).failOnError().following, "フォローされていない") + accountApi.unfollow(account).failOnError() + assertFalse(accountApi.relationships(myself, account).failOnError().following, "フォローしたまま") + } + + @Test + override fun follow_illegalAccount_returnErr() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val illegalAccount = MisskeyAccount( + "Obrg", + "beard", + "leg", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/TrT") + ) + val follow = accountApi.follow(illegalAccount) + follow.onSuccess { + fail("成功してはいけない") + } + follow.onFailure { + if (it is MultiMHttpError) { + + } else { + Logger.error("Account Api Test", "想定されたエラーではない", it) + fail("想定されたエラーではない") + } + } + } + + @Test + override fun unfollow() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v13.usbharu.dev/identicon/9bg1zu54y7") + ) + val account = MisskeyAccount( + "9cfye6ns6b", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v13.usbharu.dev/identicon/9bk3hbcjcy") + ) + if (!accountApi.relationships(myself, account).failOnError().following) { + Logger.warn("まだにフォローされているのでフォローをいったんします。") + accountApi.follow(account) + } + accountApi.unfollow(account).failOnError() + assertFalse(accountApi.relationships(myself, account).failOnError().following, "フォローされていない") + } + + @Test + override fun unfollow_illegalAccount_returnErr() = runTest { + val illegalAccount = MisskeyAccount( + "I37", + "1Q8I", + "U72oM", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/TFOTXjvs") + ) + val unfollow = accountApi.unfollow(illegalAccount) + unfollow.onSuccess { + fail("成功してはいけない") + } + unfollow.onFailure { + if (it is MultiMHttpError) { + + } else { + Logger.error("Account Api Test", "想定されたエラーではない", it) + fail("想定されたエラーではない") + } + } + } + + @Test + override fun profile() = runTest { + val myself = MisskeyAccount( + "9cfye6ns6b", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v13.usbharu.dev/identicon/9bg1zu54y7") + ) + val profile = accountApi.profile(myself).failOnError() + assertEquals(myself, profile.account) + } + + @Test + override fun profile_illegalAccount_returnErr() = runTest { + val illegalAccount = MisskeyAccount( + "x0Z3N", + "R8kOy", + "2bQfw", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/BPk") + ) + val profile = accountApi.profile(illegalAccount) + profile.onSuccess { + fail("成功してはいけない") + } + profile.onFailure { + if (it is MultiMHttpError) { + + } else { + fail("想定されたエラーではない") + } + } + } + + override fun statuses() { + TODO("Not yet implemented") + } + + override fun statusesWithIncludeRepost() { + TODO("Not yet implemented") + } + + override fun statuses_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + @Test + override fun relationships() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val account = MisskeyAccount( + "9bk3hbcjcy", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bk3hbcjcy") + ) + accountApi.relationships(myself, account).failOnError() + } + + @Test + override fun relationships_illegalAccount_returnErr() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val illegalAccount = MisskeyAccount( + "Obrg", + "beard", + "leg", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/TrT") + ) + val relationships = accountApi.relationships(myself, illegalAccount) + relationships.onSuccess { + + } + relationships.onFailure { + if (it is MultiMHttpError) { + fail("Misskey実装ではエラーが出ない") + } else { + fail("想定されたエラーではない") + } + } + } + + override fun requestCancel() { + TODO("Not yet implemented") + } + + override fun requestCancel_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + override fun requestAccept() { + TODO("Not yet implemented") + } + + override fun requestAccept_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + override fun requestReject() { + TODO("Not yet implemented") + } + + override fun requestReject_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + fun MultiMResult.failOnError(): T { + val get = this.get() + if (get != null) { + return get + } + val error = this.getError()!! + fail("Return Error ${error.message}", error.throwable) + } +} diff --git a/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyStatusApiTest.kt b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyStatusApiTest.kt new file mode 100644 index 0000000..80e5bc2 --- /dev/null +++ b/impl/misskeyv13/src/test/kotlin/dev/usbharu/multim/misskey/v13/common/api/MisskeyStatusApiTest.kt @@ -0,0 +1,58 @@ +package dev.usbharu.multim.misskey.v13.common.api + +import MisskeyTestUtil +import dev.usbharu.multim.TestUtil.failOnError +import dev.usbharu.multim.misskey.v13.api.MisskeyApis +import dev.usbharu.multim.misskey.v13.common.MisskeyStatusId +import dev.usbharu.multim.model.SingleTokenAuth +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import org.junit.jupiter.api.Test + +class MisskeyStatusApiTest { + + val misskeyStatusApi = MisskeyStatusApi( + MisskeyApis( + MisskeyApiClient( + SingleTokenAuth(""), + "http://localhost/", + MisskeyTestUtil.createMockHttpClient( + checkAuth = false, content = + Json.encodeToString( + MisskeyTestUtil.createFakeNote( + "Fx0Z", + "D93", + "brqNq4v", + "earn" + ) + ) + ) + ) + ) + ) + + @Suppress("JSON_FORMAT_REDUNDANT") + @Test + fun serializationTest() { + + @Serializable + data class Hoge(val a: String, val b: String) + + //language=JSON + Json(Json.Default) { + isLenient = true;ignoreUnknownKeys = true + }.decodeFromString("""{"a": "aaaa","b": "bbbb"}""") + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun findByIdTest() = runTest { + val findById = + misskeyStatusApi.findById(MisskeyStatusId("9a65528e5z", "https://lcalhost")).failOnError() + + } +} diff --git a/impl/misskeyv13/src/test/resources/notes/create/files/note_with_file_test.jpg b/impl/misskeyv13/src/test/resources/notes/create/files/note_with_file_test.jpg new file mode 100644 index 0000000..33a1f17 Binary files /dev/null and b/impl/misskeyv13/src/test/resources/notes/create/files/note_with_file_test.jpg differ diff --git a/settings.gradle.kts b/settings.gradle.kts index 232aca3..6b11bf7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,2 @@ rootProject.name = "multim" -include(":core", ":impl:misskey", ":impl:mastodon") +include(":core", ":impl:misskey", ":impl:mastodon",":impl:misskeyv13")