├── .editorconfig
├── .github
├── dependabot.yml
└── workflows
│ ├── codeql-analysis.yml
│ └── gradle.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.gradle
├── docs
├── -kotlin-inside
│ ├── be.zvz.kotlininside.api.article
│ │ ├── -article-delete
│ │ │ ├── -article-delete.html
│ │ │ ├── -delete-result
│ │ │ │ ├── -delete-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ ├── message.html
│ │ │ │ ├── result.html
│ │ │ │ └── status.html
│ │ │ ├── delete.html
│ │ │ └── index.html
│ │ ├── -article-hit-upvote
│ │ │ ├── -article-hit-upvote.html
│ │ │ ├── -hit-upvote-result
│ │ │ │ ├── -hit-upvote-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── index.html
│ │ │ └── upvote.html
│ │ ├── -article-list
│ │ │ ├── -article-list.html
│ │ │ ├── -gall-info
│ │ │ │ ├── -gall-info.html
│ │ │ │ ├── captcha.html
│ │ │ │ ├── category.html
│ │ │ │ ├── code-count.html
│ │ │ │ ├── file-count.html
│ │ │ │ ├── file-size.html
│ │ │ │ ├── head-text.html
│ │ │ │ ├── index.html
│ │ │ │ ├── is-manager.html
│ │ │ │ ├── is-mini.html
│ │ │ │ ├── is-minor.html
│ │ │ │ ├── member-join.html
│ │ │ │ ├── membership.html
│ │ │ │ ├── no-write.html
│ │ │ │ ├── notify-recent.html
│ │ │ │ ├── profile-image.html
│ │ │ │ ├── relation-gall.html
│ │ │ │ ├── title.html
│ │ │ │ ├── total-member.html
│ │ │ │ ├── use-auto-delete.html
│ │ │ │ └── use-list-fix.html
│ │ │ ├── -gall-list
│ │ │ │ ├── -gall-list.html
│ │ │ │ ├── best-check.html
│ │ │ │ ├── date-time.html
│ │ │ │ ├── galler-con.html
│ │ │ │ ├── head-text.html
│ │ │ │ ├── identifier.html
│ │ │ │ ├── image-icon.html
│ │ │ │ ├── index.html
│ │ │ │ ├── ip.html
│ │ │ │ ├── level.html
│ │ │ │ ├── member-icon.html
│ │ │ │ ├── name.html
│ │ │ │ ├── subject.html
│ │ │ │ ├── total-comment.html
│ │ │ │ ├── total-voice.html
│ │ │ │ ├── upvote-icon.html
│ │ │ │ ├── upvote.html
│ │ │ │ ├── user-id.html
│ │ │ │ ├── views.html
│ │ │ │ ├── voice-icon.html
│ │ │ │ └── winnerta-icon.html
│ │ │ ├── -search-type
│ │ │ │ ├── -a-l-l
│ │ │ │ │ └── index.html
│ │ │ │ ├── -c-o-n-t-e-n-t
│ │ │ │ │ └── index.html
│ │ │ │ ├── -n-a-m-e
│ │ │ │ │ └── index.html
│ │ │ │ ├── -s-u-b-j-e-c-t
│ │ │ │ │ └── index.html
│ │ │ │ ├── -s-u-b-j-e-c-t_-a-n-d_-c-o-n-t-e-n-t
│ │ │ │ │ └── index.html
│ │ │ │ ├── entries.html
│ │ │ │ ├── index.html
│ │ │ │ ├── type.html
│ │ │ │ ├── value-of.html
│ │ │ │ └── values.html
│ │ │ ├── get-gall-info.html
│ │ │ ├── get-gall-list.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -article-modify
│ │ │ ├── -article-modify.html
│ │ │ ├── -file-data
│ │ │ │ ├── -file-data.html
│ │ │ │ ├── block.html
│ │ │ │ ├── file-size.html
│ │ │ │ └── index.html
│ │ │ ├── -modify-result
│ │ │ │ ├── -modify-result.html
│ │ │ │ ├── article-id.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── content.html
│ │ │ │ ├── current-head-text.html
│ │ │ │ ├── file-count.html
│ │ │ │ ├── file-size.html
│ │ │ │ ├── file.html
│ │ │ │ ├── gall-id.html
│ │ │ │ ├── head-text.html
│ │ │ │ ├── index.html
│ │ │ │ ├── result.html
│ │ │ │ └── subject.html
│ │ │ ├── index.html
│ │ │ ├── modify-info.html
│ │ │ └── modify.html
│ │ ├── -article-read
│ │ │ ├── -article-read.html
│ │ │ ├── -view-info
│ │ │ │ ├── -view-info.html
│ │ │ │ ├── best-check.html
│ │ │ │ ├── category.html
│ │ │ │ ├── comment-delete-scope.html
│ │ │ │ ├── date-time.html
│ │ │ │ ├── gall-title.html
│ │ │ │ ├── galler-con.html
│ │ │ │ ├── head-text.html
│ │ │ │ ├── head-title.html
│ │ │ │ ├── identifier.html
│ │ │ │ ├── image-check.html
│ │ │ │ ├── index.html
│ │ │ │ ├── ip.html
│ │ │ │ ├── is-mini.html
│ │ │ │ ├── is-minor.html
│ │ │ │ ├── is-notice.html
│ │ │ │ ├── level.html
│ │ │ │ ├── member-grant.html
│ │ │ │ ├── member-icon.html
│ │ │ │ ├── membership.html
│ │ │ │ ├── name.html
│ │ │ │ ├── next-link.html
│ │ │ │ ├── next-subject.html
│ │ │ │ ├── previous-link.html
│ │ │ │ ├── previous-subject.html
│ │ │ │ ├── recommend-check.html
│ │ │ │ ├── subject.html
│ │ │ │ ├── total-comment.html
│ │ │ │ ├── use-auto-delete.html
│ │ │ │ ├── use-list-fix.html
│ │ │ │ ├── user-id.html
│ │ │ │ ├── views.html
│ │ │ │ ├── voice-check.html
│ │ │ │ ├── winnerta-check.html
│ │ │ │ └── write-type.html
│ │ │ ├── -view-main
│ │ │ │ ├── -view-main.html
│ │ │ │ ├── content.html
│ │ │ │ ├── downvote.html
│ │ │ │ ├── index.html
│ │ │ │ ├── is-manager.html
│ │ │ │ ├── upvote-member.html
│ │ │ │ └── upvote.html
│ │ │ ├── get-view-info.html
│ │ │ ├── get-view-main.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -article-report
│ │ │ ├── -article-report.html
│ │ │ ├── get-link.html
│ │ │ └── index.html
│ │ ├── -article-vote
│ │ │ ├── -article-vote.html
│ │ │ ├── -vote-result
│ │ │ │ ├── -vote-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ ├── member.html
│ │ │ │ └── result.html
│ │ │ ├── downvote.html
│ │ │ ├── index.html
│ │ │ └── upvote.html
│ │ ├── -article-write
│ │ │ ├── -article-write.html
│ │ │ ├── -write-result
│ │ │ │ ├── -write-result.html
│ │ │ │ ├── article-id.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── id.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── index.html
│ │ │ └── write.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.article
│ │ ├── -async-article-delete
│ │ │ ├── -async-article-delete.html
│ │ │ ├── delete-async.html
│ │ │ └── index.html
│ │ ├── -async-article-hit-upvote
│ │ │ ├── -async-article-hit-upvote.html
│ │ │ ├── index.html
│ │ │ └── upvote-async.html
│ │ ├── -async-article-list
│ │ │ ├── -async-article-list.html
│ │ │ ├── get-gall-info-async.html
│ │ │ ├── get-gall-list-async.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-article-modify
│ │ │ ├── -async-article-modify.html
│ │ │ ├── index.html
│ │ │ ├── modify-async.html
│ │ │ └── modify-info-async.html
│ │ ├── -async-article-read
│ │ │ ├── -async-article-read.html
│ │ │ ├── get-view-info-async.html
│ │ │ ├── get-view-main-async.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-article-report
│ │ │ ├── -async-article-report.html
│ │ │ ├── get-link-async.html
│ │ │ └── index.html
│ │ ├── -async-article-vote
│ │ │ ├── -async-article-vote.html
│ │ │ ├── downvote-async.html
│ │ │ ├── index.html
│ │ │ └── upvote-async.html
│ │ ├── -async-article-write
│ │ │ ├── -async-article-write.html
│ │ │ ├── index.html
│ │ │ └── write-async.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.comment
│ │ ├── -async-comment-delete
│ │ │ ├── -async-comment-delete.html
│ │ │ ├── delete-async.html
│ │ │ └── index.html
│ │ ├── -async-comment-read
│ │ │ ├── -async-comment-read.html
│ │ │ ├── get-async.html
│ │ │ └── index.html
│ │ ├── -async-comment-write
│ │ │ ├── -async-comment-write.html
│ │ │ ├── index.html
│ │ │ ├── reply-async.html
│ │ │ └── write-async.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.dccon
│ │ ├── -async-d-c-con-buy
│ │ │ ├── -async-d-c-con-buy.html
│ │ │ ├── buy-async.html
│ │ │ └── index.html
│ │ ├── -async-d-c-con-detail
│ │ │ ├── -async-d-c-con-detail.html
│ │ │ ├── get-async.html
│ │ │ └── index.html
│ │ ├── -async-d-c-con-list
│ │ │ ├── -async-d-c-con-list.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.generic.minigallery
│ │ ├── -async-join-mini-gallery
│ │ │ ├── -async-join-mini-gallery.html
│ │ │ ├── index.html
│ │ │ ├── join-async.html
│ │ │ ├── request-member-join-async.html
│ │ │ └── request-member-join-ok-async.html
│ │ ├── -async-quit-mini-gallery
│ │ │ ├── -async-quit-mini-gallery.html
│ │ │ ├── index.html
│ │ │ └── quit-async.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.generic.userinfo
│ │ ├── -async-check-joined-mini-gallery
│ │ │ ├── -async-check-joined-mini-gallery.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-check-managed-gallery
│ │ │ ├── -async-check-managed-gallery.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-modify-my-gall
│ │ │ ├── -async-modify-my-gall.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-my-gall
│ │ │ ├── -async-my-gall.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.generic
│ │ ├── -async-gallery-ranking
│ │ │ ├── -async-gallery-ranking.html
│ │ │ ├── get-async.html
│ │ │ └── index.html
│ │ ├── -async-gallery-search
│ │ │ ├── -async-gallery-search.html
│ │ │ ├── index.html
│ │ │ └── search-async.html
│ │ ├── -async-main-page
│ │ │ ├── -async-main-page.html
│ │ │ ├── get-best-async.html
│ │ │ ├── get-hit-async.html
│ │ │ ├── get-issue-zoom-async.html
│ │ │ ├── get-new-gallery-async.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-mini-gallery-ranking
│ │ │ ├── -async-mini-gallery-ranking.html
│ │ │ ├── get-async.html
│ │ │ └── index.html
│ │ ├── -async-minor-gallery-info
│ │ │ ├── -async-minor-gallery-info.html
│ │ │ ├── get-async.html
│ │ │ └── index.html
│ │ ├── -async-minor-gallery-ranking
│ │ │ ├── -async-minor-gallery-ranking.html
│ │ │ ├── get-async.html
│ │ │ └── index.html
│ │ ├── -async-total-search
│ │ │ ├── -async-total-search.html
│ │ │ ├── index.html
│ │ │ └── search-async.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.async.management
│ │ ├── -async-change-head-text
│ │ │ ├── -async-change-head-text.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-gallery-setting
│ │ │ ├── -async-gallery-setting.html
│ │ │ ├── get-link-async.html
│ │ │ └── index.html
│ │ ├── -async-no-member-block
│ │ │ ├── -async-no-member-block.html
│ │ │ ├── block-async.html
│ │ │ └── index.html
│ │ ├── -async-notice
│ │ │ ├── -async-notice.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-recommend
│ │ │ ├── -async-recommend.html
│ │ │ ├── index.html
│ │ │ └── request-async.html
│ │ ├── -async-user-block
│ │ │ ├── -async-user-block.html
│ │ │ ├── block-async.html
│ │ │ ├── get-link-async.html
│ │ │ └── index.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.comment
│ │ ├── -comment-delete
│ │ │ ├── -comment-delete.html
│ │ │ ├── -delete-result
│ │ │ │ ├── -delete-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── delete.html
│ │ │ └── index.html
│ │ ├── -comment-read
│ │ │ ├── -comment-data
│ │ │ │ ├── -comment-data.html
│ │ │ │ ├── content.html
│ │ │ │ ├── date-time.html
│ │ │ │ ├── galler-con.html
│ │ │ │ ├── identifier.html
│ │ │ │ ├── index.html
│ │ │ │ ├── ip-data.html
│ │ │ │ ├── is-delete-flag.html
│ │ │ │ ├── is-reply.html
│ │ │ │ ├── member-icon.html
│ │ │ │ ├── name.html
│ │ │ │ └── user-id.html
│ │ │ ├── -comment-read.html
│ │ │ ├── -read-result
│ │ │ │ ├── -read-result.html
│ │ │ │ ├── comment-list.html
│ │ │ │ ├── index.html
│ │ │ │ ├── re-page.html
│ │ │ │ ├── total-comment.html
│ │ │ │ └── total-page.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -comment-write
│ │ │ ├── -comment-write.html
│ │ │ ├── -write-result
│ │ │ │ ├── -write-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── data.html
│ │ │ │ ├── index.html
│ │ │ │ ├── result.html
│ │ │ │ └── word.html
│ │ │ ├── index.html
│ │ │ ├── reply.html
│ │ │ └── write.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.dccon
│ │ ├── -d-c-con-buy
│ │ │ ├── -buy-result
│ │ │ │ ├── -buy-result.html
│ │ │ │ ├── index.html
│ │ │ │ ├── msg.html
│ │ │ │ └── result.html
│ │ │ ├── -d-c-con-buy.html
│ │ │ ├── buy.html
│ │ │ └── index.html
│ │ ├── -d-c-con-detail
│ │ │ ├── -d-c-con-detail.html
│ │ │ ├── -d-c-con-info
│ │ │ │ ├── -d-c-con-info.html
│ │ │ │ ├── description.html
│ │ │ │ ├── get-state.html
│ │ │ │ ├── index.html
│ │ │ │ ├── main-img.html
│ │ │ │ ├── mandu.html
│ │ │ │ ├── package-index.html
│ │ │ │ └── title.html
│ │ │ ├── -detail-result
│ │ │ │ ├── -detail-result.html
│ │ │ │ ├── detail.html
│ │ │ │ ├── index.html
│ │ │ │ └── info.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -d-c-con-insert
│ │ │ ├── -d-c-con-insert.html
│ │ │ ├── -insert-result
│ │ │ │ ├── -insert-result.html
│ │ │ │ ├── alternative-text.html
│ │ │ │ ├── image-source.html
│ │ │ │ ├── image-tag.html
│ │ │ │ ├── index.html
│ │ │ │ ├── new-list.html
│ │ │ │ └── result.html
│ │ │ ├── dc-con.html
│ │ │ ├── index.html
│ │ │ ├── request.html
│ │ │ └── session.html
│ │ ├── -d-c-con-list
│ │ │ ├── -d-c-con-list.html
│ │ │ ├── -list-result
│ │ │ │ ├── -list-result.html
│ │ │ │ ├── index.html
│ │ │ │ ├── list.html
│ │ │ │ └── tab.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.generic.minigallery
│ │ ├── -join-mini-gallery
│ │ │ ├── -join-mini-gallery.html
│ │ │ ├── -member-join-ok-result
│ │ │ │ ├── -member-join-ok-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ ├── result.html
│ │ │ │ └── status.html
│ │ │ ├── -member-join-result
│ │ │ │ ├── -member-join-result.html
│ │ │ │ ├── index.html
│ │ │ │ ├── join-question.html
│ │ │ │ └── result.html
│ │ │ ├── index.html
│ │ │ ├── join.html
│ │ │ ├── request-member-join-ok.html
│ │ │ └── request-member-join.html
│ │ ├── -quit-mini-gallery
│ │ │ ├── -member-quit-result
│ │ │ │ ├── -member-quit-result.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── -quit-mini-gallery.html
│ │ │ ├── index.html
│ │ │ └── quit.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.generic.userinfo
│ │ ├── -check-joined-mini-gallery
│ │ │ ├── -check-joined-mini-gallery.html
│ │ │ ├── -check-result
│ │ │ │ ├── -check-result.html
│ │ │ │ ├── index.html
│ │ │ │ ├── my-join-mini-hold.html
│ │ │ │ ├── my-join-mini-in.html
│ │ │ │ └── my-join-mini-out.html
│ │ │ ├── -gallery
│ │ │ │ ├── -gallery.html
│ │ │ │ ├── hide.html
│ │ │ │ ├── id.html
│ │ │ │ ├── index.html
│ │ │ │ └── title.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -check-managed-gallery
│ │ │ ├── -check-managed-gallery.html
│ │ │ ├── -check-result
│ │ │ │ ├── -check-result.html
│ │ │ │ ├── index.html
│ │ │ │ └── my-manage-list.html
│ │ │ ├── -gallery
│ │ │ │ ├── -gallery.html
│ │ │ │ ├── hide.html
│ │ │ │ ├── id.html
│ │ │ │ ├── index.html
│ │ │ │ ├── manager-type.html
│ │ │ │ ├── title.html
│ │ │ │ └── type.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -modify-my-gall
│ │ │ ├── -modify-my-gall-result
│ │ │ │ ├── -modify-my-gall-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── -modify-my-gall.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -my-gall
│ │ │ ├── -my-gall-result
│ │ │ │ ├── -my-gall-result.html
│ │ │ │ ├── favorite.html
│ │ │ │ ├── index.html
│ │ │ │ └── my-gall.html
│ │ │ ├── -my-gall.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.generic
│ │ ├── -gallery-ranking
│ │ │ ├── -gallery-ranking.html
│ │ │ ├── -rank-type
│ │ │ │ ├── -d-o-w-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -s-t-o-p
│ │ │ │ │ └── index.html
│ │ │ │ ├── -u-n-k-n-o-w-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -u-p
│ │ │ │ │ └── index.html
│ │ │ │ ├── entries.html
│ │ │ │ ├── index.html
│ │ │ │ ├── value-of.html
│ │ │ │ └── values.html
│ │ │ ├── -ranking-item
│ │ │ │ ├── -ranking-item.html
│ │ │ │ ├── gall-id.html
│ │ │ │ ├── gall-link.html
│ │ │ │ ├── gall-name.html
│ │ │ │ ├── index.html
│ │ │ │ ├── rank-type.html
│ │ │ │ ├── rank-updown.html
│ │ │ │ └── rank.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -gallery-search
│ │ │ ├── -gallery-search-result
│ │ │ │ ├── -gallery-search-result.html
│ │ │ │ ├── index.html
│ │ │ │ ├── main-gallery.html
│ │ │ │ ├── main-recommend-gallery.html
│ │ │ │ ├── minor-gallery.html
│ │ │ │ └── minor-recommend-gallery.html
│ │ │ ├── -gallery-search.html
│ │ │ ├── index.html
│ │ │ └── search.html
│ │ ├── -main-page
│ │ │ ├── -article
│ │ │ │ ├── -article.html
│ │ │ │ ├── article-id.html
│ │ │ │ ├── gall-id.html
│ │ │ │ ├── gall-name.html
│ │ │ │ ├── index.html
│ │ │ │ ├── thumbnail.html
│ │ │ │ └── title.html
│ │ │ ├── -main-page.html
│ │ │ ├── -new-gallery
│ │ │ │ ├── -new-gallery.html
│ │ │ │ ├── id.html
│ │ │ │ ├── index.html
│ │ │ │ └── title.html
│ │ │ ├── get-best.html
│ │ │ ├── get-hit.html
│ │ │ ├── get-issue-zoom.html
│ │ │ ├── get-new-gallery.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -mini-gallery-ranking
│ │ │ ├── -mini-gallery-ranking.html
│ │ │ ├── -rank-type
│ │ │ │ ├── -d-o-w-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -s-t-o-p
│ │ │ │ │ └── index.html
│ │ │ │ ├── -u-n-k-n-o-w-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -u-p
│ │ │ │ │ └── index.html
│ │ │ │ ├── entries.html
│ │ │ │ ├── index.html
│ │ │ │ ├── value-of.html
│ │ │ │ └── values.html
│ │ │ ├── -ranking-item
│ │ │ │ ├── -ranking-item.html
│ │ │ │ ├── gall-id.html
│ │ │ │ ├── gall-link.html
│ │ │ │ ├── gall-name.html
│ │ │ │ ├── index.html
│ │ │ │ ├── rank-type.html
│ │ │ │ ├── rank-updown.html
│ │ │ │ └── rank.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -minor-gallery-info
│ │ │ ├── -info-result
│ │ │ │ ├── -info-result.html
│ │ │ │ ├── category-name.html
│ │ │ │ ├── create-date.html
│ │ │ │ ├── description.html
│ │ │ │ ├── hot-state.html
│ │ │ │ ├── id.html
│ │ │ │ ├── image.html
│ │ │ │ ├── index.html
│ │ │ │ ├── ko-name.html
│ │ │ │ ├── manager.html
│ │ │ │ ├── mini.html
│ │ │ │ ├── new.html
│ │ │ │ ├── sub-manager.html
│ │ │ │ └── total-count.html
│ │ │ ├── -manager
│ │ │ │ ├── -manager.html
│ │ │ │ ├── id.html
│ │ │ │ ├── index.html
│ │ │ │ ├── is-master.html
│ │ │ │ └── name.html
│ │ │ ├── -mini-gallery-info
│ │ │ │ ├── -mini-gallery-info.html
│ │ │ │ ├── hide.html
│ │ │ │ ├── index.html
│ │ │ │ ├── is-member.html
│ │ │ │ ├── member-limit.html
│ │ │ │ └── total-member.html
│ │ │ ├── -minor-gallery-info.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -minor-gallery-ranking
│ │ │ ├── -minor-gallery-ranking.html
│ │ │ ├── -rank-type
│ │ │ │ ├── -d-o-w-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -s-t-o-p
│ │ │ │ │ └── index.html
│ │ │ │ ├── -u-n-k-n-o-w-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -u-p
│ │ │ │ │ └── index.html
│ │ │ │ ├── entries.html
│ │ │ │ ├── index.html
│ │ │ │ ├── value-of.html
│ │ │ │ └── values.html
│ │ │ ├── -ranking-item
│ │ │ │ ├── -ranking-item.html
│ │ │ │ ├── gall-id.html
│ │ │ │ ├── gall-link.html
│ │ │ │ ├── gall-name.html
│ │ │ │ ├── index.html
│ │ │ │ ├── rank-type.html
│ │ │ │ ├── rank-updown.html
│ │ │ │ └── rank.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -movie-upload
│ │ │ ├── -check-result
│ │ │ │ ├── -check-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── -movie-upload.html
│ │ │ ├── -upload-exception
│ │ │ │ ├── -upload-exception.html
│ │ │ │ ├── check-result.html
│ │ │ │ └── index.html
│ │ │ ├── -upload-result
│ │ │ │ ├── -upload-result.html
│ │ │ │ ├── file-id.html
│ │ │ │ ├── height.html
│ │ │ │ ├── index.html
│ │ │ │ ├── msg.html
│ │ │ │ ├── thumbnail-urls.html
│ │ │ │ └── width.html
│ │ │ ├── check-restriction.html
│ │ │ ├── content.html
│ │ │ ├── gall-id.html
│ │ │ ├── index.html
│ │ │ └── upload.html
│ │ ├── -total-search
│ │ │ ├── -real-time
│ │ │ │ ├── -real-time.html
│ │ │ │ ├── index.html
│ │ │ │ ├── rank.html
│ │ │ │ ├── title.html
│ │ │ │ └── url.html
│ │ │ ├── -searched-article
│ │ │ │ ├── -searched-article.html
│ │ │ │ ├── article-id.html
│ │ │ │ ├── content.html
│ │ │ │ ├── gall-id.html
│ │ │ │ ├── gall-name.html
│ │ │ │ ├── index.html
│ │ │ │ ├── reg-date.html
│ │ │ │ └── title.html
│ │ │ ├── -total-search-result
│ │ │ │ ├── -total-search-result.html
│ │ │ │ ├── board.html
│ │ │ │ ├── index.html
│ │ │ │ ├── main-gallery.html
│ │ │ │ ├── minor-gallery.html
│ │ │ │ ├── real-time.html
│ │ │ │ ├── today-issue.html
│ │ │ │ └── wiki.html
│ │ │ ├── -total-search.html
│ │ │ ├── -wiki
│ │ │ │ ├── -wiki.html
│ │ │ │ ├── gall-name.html
│ │ │ │ ├── index.html
│ │ │ │ ├── title.html
│ │ │ │ └── url.html
│ │ │ ├── index.html
│ │ │ └── search.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.management
│ │ ├── -change-head-text
│ │ │ ├── -change-head-text.html
│ │ │ ├── -change-result
│ │ │ │ ├── -change-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ ├── result.html
│ │ │ │ └── state.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -gallery-setting
│ │ │ ├── -gallery-setting.html
│ │ │ ├── get-link.html
│ │ │ ├── get-user-agent.html
│ │ │ └── index.html
│ │ ├── -no-member-block
│ │ │ ├── -block-option
│ │ │ │ ├── -block-option.html
│ │ │ │ ├── -image-restriction-option
│ │ │ │ │ ├── -image-restriction-option.html
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── time.html
│ │ │ │ │ └── type.html
│ │ │ │ ├── cellular.html
│ │ │ │ ├── image.html
│ │ │ │ ├── index.html
│ │ │ │ └── proxy.html
│ │ │ ├── -block-result
│ │ │ │ ├── -block-result.html
│ │ │ │ ├── index.html
│ │ │ │ ├── msg.html
│ │ │ │ └── result.html
│ │ │ ├── -image-status
│ │ │ │ ├── -a-n-o-n-y-m-o-u-s
│ │ │ │ │ └── index.html
│ │ │ │ ├── -c-e-l-l-u-l-a-r
│ │ │ │ │ └── index.html
│ │ │ │ ├── -n-o-n-e
│ │ │ │ │ └── index.html
│ │ │ │ ├── -p-r-o-x-y
│ │ │ │ │ └── index.html
│ │ │ │ ├── -p-r-o-x-y_-a-n-d_-c-e-l-l-u-l-a-r
│ │ │ │ │ └── index.html
│ │ │ │ ├── entries.html
│ │ │ │ ├── index.html
│ │ │ │ ├── value-of.html
│ │ │ │ ├── value.html
│ │ │ │ └── values.html
│ │ │ ├── -no-member-block.html
│ │ │ ├── block.html
│ │ │ └── index.html
│ │ ├── -notice
│ │ │ ├── -notice-result
│ │ │ │ ├── -notice-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ ├── result.html
│ │ │ │ └── state.html
│ │ │ ├── -notice.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -recommend
│ │ │ ├── -recommend-result
│ │ │ │ ├── -recommend-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ ├── result.html
│ │ │ │ └── state.html
│ │ │ ├── -recommend.html
│ │ │ ├── index.html
│ │ │ └── request.html
│ │ ├── -user-block
│ │ │ ├── -block-category
│ │ │ │ ├── -a-d-v-e-r-t-i-s-e-m-e-n-t
│ │ │ │ │ └── index.html
│ │ │ │ ├── -c-u-s-s_-w-o-r-d-s
│ │ │ │ │ └── index.html
│ │ │ │ ├── -c-u-s-t-o-m
│ │ │ │ │ └── index.html
│ │ │ │ ├── -d-e-f-a-m-a-t-i-o-n
│ │ │ │ │ └── index.html
│ │ │ │ ├── -o-b-s-c-e-n-e
│ │ │ │ │ └── index.html
│ │ │ │ ├── -p-i-r-a-c-y
│ │ │ │ │ └── index.html
│ │ │ │ ├── -s-p-a-m-m-i-n-g
│ │ │ │ │ └── index.html
│ │ │ │ ├── code.html
│ │ │ │ ├── entries.html
│ │ │ │ ├── index.html
│ │ │ │ ├── value-of.html
│ │ │ │ └── values.html
│ │ │ ├── -block-option
│ │ │ │ ├── -block-option.html
│ │ │ │ ├── block-category.html
│ │ │ │ ├── block-hour.html
│ │ │ │ ├── block-reason.html
│ │ │ │ ├── comment-id.html
│ │ │ │ └── index.html
│ │ │ ├── -block-result
│ │ │ │ ├── -block-result.html
│ │ │ │ ├── cause.html
│ │ │ │ ├── index.html
│ │ │ │ └── result.html
│ │ │ ├── -user-block.html
│ │ │ ├── block.html
│ │ │ ├── get-link.html
│ │ │ ├── get-user-agent.html
│ │ │ └── index.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.type.comment
│ │ ├── -comment
│ │ │ └── index.html
│ │ ├── -d-c-con-comment
│ │ │ ├── -d-c-con-comment.html
│ │ │ ├── dc-con.html
│ │ │ └── index.html
│ │ ├── -string-comment
│ │ │ ├── -string-comment.html
│ │ │ ├── index.html
│ │ │ └── memo.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.type.content
│ │ ├── -content
│ │ │ └── index.html
│ │ ├── -d-c-con-content
│ │ │ ├── -d-c-con-content.html
│ │ │ ├── dc-con-insert-result.html
│ │ │ ├── dc-con.html
│ │ │ └── index.html
│ │ ├── -html-content
│ │ │ ├── -html-content.html
│ │ │ ├── html-string.html
│ │ │ └── index.html
│ │ ├── -image-content
│ │ │ ├── -image-content.html
│ │ │ ├── close.html
│ │ │ ├── index.html
│ │ │ ├── mime-type.html
│ │ │ └── stream.html
│ │ ├── -markdown-content
│ │ │ ├── -markdown-content.html
│ │ │ ├── index.html
│ │ │ └── markdown-string.html
│ │ ├── -movie-content
│ │ │ ├── -movie-content.html
│ │ │ ├── -movie-info
│ │ │ │ ├── -movie-info.html
│ │ │ │ ├── allow-download.html
│ │ │ │ ├── description.html
│ │ │ │ ├── height.html
│ │ │ │ ├── index.html
│ │ │ │ ├── tag.html
│ │ │ │ ├── thumbnail-url.html
│ │ │ │ └── width.html
│ │ │ ├── close.html
│ │ │ ├── index.html
│ │ │ ├── info.html
│ │ │ ├── mime-type.html
│ │ │ └── stream.html
│ │ ├── -string-content
│ │ │ ├── -string-content.html
│ │ │ ├── index.html
│ │ │ └── string.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.api.type
│ │ ├── -article
│ │ │ ├── -article.html
│ │ │ ├── content.html
│ │ │ ├── head-text.html
│ │ │ ├── index.html
│ │ │ └── subject.html
│ │ ├── -d-c-con
│ │ │ ├── -d-c-con.html
│ │ │ ├── detail-index.html
│ │ │ ├── img-link.html
│ │ │ ├── index.html
│ │ │ ├── memo.html
│ │ │ ├── package-index.html
│ │ │ └── title.html
│ │ ├── -gallery
│ │ │ ├── -gallery.html
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── title.html
│ │ ├── -head-text
│ │ │ ├── -head-text.html
│ │ │ ├── identifier.html
│ │ │ ├── index.html
│ │ │ ├── level.html
│ │ │ ├── name.html
│ │ │ └── selected.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.exception
│ │ ├── -insufficient-permission-exception
│ │ │ ├── -insufficient-permission-exception.html
│ │ │ ├── cause-class.html
│ │ │ └── index.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.http
│ │ ├── -default-http-client
│ │ │ ├── -companion
│ │ │ │ ├── -d-e-f-a-u-l-t_-m-i-m-e_-t-y-p-e.html
│ │ │ │ └── index.html
│ │ │ ├── -default-http-client.html
│ │ │ ├── -proxy
│ │ │ │ ├── index.html
│ │ │ │ ├── ip.html
│ │ │ │ └── port.html
│ │ │ ├── delete.html
│ │ │ ├── get.html
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── patch.html
│ │ │ ├── post.html
│ │ │ ├── put.html
│ │ │ └── upload.html
│ │ ├── -http-exception
│ │ │ ├── -http-exception.html
│ │ │ ├── index.html
│ │ │ └── status-code.html
│ │ ├── -http-interface
│ │ │ ├── -option
│ │ │ │ ├── -file-info
│ │ │ │ │ ├── -file-info.html
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── mime-type.html
│ │ │ │ │ └── stream.html
│ │ │ │ ├── -option.html
│ │ │ │ ├── add-body-parameter.html
│ │ │ │ ├── add-header.html
│ │ │ │ ├── add-multipart-file-list.html
│ │ │ │ ├── add-multipart-file.html
│ │ │ │ ├── add-multipart-parameter.html
│ │ │ │ ├── add-path-parameter.html
│ │ │ │ ├── add-query-parameter.html
│ │ │ │ ├── body-parameter.html
│ │ │ │ ├── content-type.html
│ │ │ │ ├── get-body.html
│ │ │ │ ├── headers.html
│ │ │ │ ├── index.html
│ │ │ │ ├── multipart-content-type.html
│ │ │ │ ├── multipart-file-list.html
│ │ │ │ ├── multipart-file.html
│ │ │ │ ├── multipart-parameter.html
│ │ │ │ ├── path-parameter.html
│ │ │ │ ├── query-parameter.html
│ │ │ │ ├── set-content-type-and-body.html
│ │ │ │ └── user-agent.html
│ │ │ ├── delete.html
│ │ │ ├── get.html
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── patch.html
│ │ │ ├── post.html
│ │ │ ├── put.html
│ │ │ └── upload.html
│ │ ├── -request
│ │ │ ├── get-default-option.html
│ │ │ ├── index.html
│ │ │ └── redirect-url.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.json
│ │ ├── -json-browser
│ │ │ ├── --index--.html
│ │ │ ├── -n-u-l-l_-b-r-o-w-s-e-r.html
│ │ │ ├── as-boolean.html
│ │ │ ├── as-integer.html
│ │ │ ├── as-long.html
│ │ │ ├── as-nullable-boolean.html
│ │ │ ├── as-nullable-integer.html
│ │ │ ├── as-nullable-long.html
│ │ │ ├── as.html
│ │ │ ├── create.html
│ │ │ ├── format.html
│ │ │ ├── get.html
│ │ │ ├── index.html
│ │ │ ├── is-list.html
│ │ │ ├── is-map.html
│ │ │ ├── is-null.html
│ │ │ ├── mapper.html
│ │ │ ├── parse.html
│ │ │ ├── put.html
│ │ │ ├── safe-text.html
│ │ │ ├── stringify.html
│ │ │ ├── text.html
│ │ │ ├── to-map.html
│ │ │ ├── to-string.html
│ │ │ └── values.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.migbase64
│ │ ├── -base64-i-o
│ │ │ ├── -base64-i-o.html
│ │ │ ├── encode.html
│ │ │ └── index.html
│ │ ├── -base64
│ │ │ ├── -base64.html
│ │ │ ├── decode-fast.html
│ │ │ ├── decode.html
│ │ │ ├── encode-to-byte.html
│ │ │ ├── encode-to-char.html
│ │ │ ├── encode-to-string.html
│ │ │ └── index.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.security
│ │ ├── -app
│ │ │ ├── -app.html
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── token.html
│ │ ├── -auth
│ │ │ ├── -app-check
│ │ │ │ ├── -app-check.html
│ │ │ │ ├── date.html
│ │ │ │ ├── index.html
│ │ │ │ ├── notice-update.html
│ │ │ │ ├── notice.html
│ │ │ │ ├── result.html
│ │ │ │ └── version.html
│ │ │ ├── -auth.html
│ │ │ ├── fcm-token.html
│ │ │ ├── fetch-android-checkin.html
│ │ │ ├── fetch-app-id.html
│ │ │ ├── fetch-fcm-token.html
│ │ │ ├── fid.html
│ │ │ ├── generate-aid-login-from-checkin.html
│ │ │ ├── generate-hashed-app-key.html
│ │ │ ├── get-app-check.html
│ │ │ ├── get-app-id.html
│ │ │ ├── index.html
│ │ │ ├── login.html
│ │ │ └── refresh-token.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.session.user.named
│ │ ├── -duplicate-named
│ │ │ ├── -duplicate-named.html
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── password.html
│ │ ├── -named
│ │ │ ├── -named.html
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── password.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.session.user
│ │ ├── -anonymous
│ │ │ ├── -anonymous.html
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── password.html
│ │ ├── -login-user
│ │ │ ├── -login-user.html
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── password.html
│ │ ├── -user-type
│ │ │ ├── -a-n-o-n-y-m-o-u-s
│ │ │ │ └── index.html
│ │ │ ├── -d-u-p-l-i-c-a-t-e_-n-a-m-e-d
│ │ │ │ └── index.html
│ │ │ ├── -n-a-m-e-d
│ │ │ │ └── index.html
│ │ │ ├── entries.html
│ │ │ ├── index.html
│ │ │ ├── session-type.html
│ │ │ ├── value-of.html
│ │ │ └── values.html
│ │ ├── -user
│ │ │ ├── id.html
│ │ │ ├── index.html
│ │ │ └── password.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.session
│ │ ├── -session-detail
│ │ │ ├── -session-detail.html
│ │ │ ├── auth-change.html
│ │ │ ├── cause.html
│ │ │ ├── index.html
│ │ │ ├── is-adult.html
│ │ │ ├── is-dormancy.html
│ │ │ ├── is-gonick.html
│ │ │ ├── is-otp.html
│ │ │ ├── is-security-code.html
│ │ │ ├── mail-send.html
│ │ │ ├── name.html
│ │ │ ├── pw-campaign.html
│ │ │ ├── result.html
│ │ │ ├── session-type.html
│ │ │ ├── user-id.html
│ │ │ └── user-no.html
│ │ ├── -session
│ │ │ ├── -session.html
│ │ │ ├── detail.html
│ │ │ ├── index.html
│ │ │ └── user.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.utils
│ │ ├── -string-util
│ │ │ ├── index.html
│ │ │ ├── md-to-html.html
│ │ │ ├── ok-to-boolean.html
│ │ │ ├── to-html.html
│ │ │ └── yn-to-boolean.html
│ │ └── index.html
│ ├── be.zvz.kotlininside.value
│ │ ├── -api-url
│ │ │ ├── -a-p-p_-a-p-i.html
│ │ │ ├── -a-u-t-h_-a-p-i.html
│ │ │ ├── -article
│ │ │ │ ├── -d-e-l-e-t-e.html
│ │ │ │ ├── -d-o-w-n-v-o-t-e.html
│ │ │ │ ├── -h-i-t_-u-p-v-o-t-e.html
│ │ │ │ ├── -i-n-s-e-r-t_-m-o-v-i-e_-i-n-f-o.html
│ │ │ │ ├── -l-i-s-t.html
│ │ │ │ ├── -m-o-d-i-f-y.html
│ │ │ │ ├── -r-e-a-d.html
│ │ │ │ ├── -r-e-p-o-r-t.html
│ │ │ │ ├── -u-p-v-o-t-e.html
│ │ │ │ ├── -w-r-i-t-e.html
│ │ │ │ └── index.html
│ │ │ ├── -auth
│ │ │ │ ├── -a-p-p_-c-h-e-c-k.html
│ │ │ │ ├── -a-p-p_-i-d.html
│ │ │ │ ├── -l-o-g-i-n.html
│ │ │ │ └── index.html
│ │ │ ├── -comment
│ │ │ │ ├── -d-e-l-e-t-e.html
│ │ │ │ ├── -o-k.html
│ │ │ │ ├── -r-e-a-d.html
│ │ │ │ └── index.html
│ │ │ ├── -d-c-con
│ │ │ │ ├── -d-c-c-o-n.html
│ │ │ │ └── index.html
│ │ │ ├── -firebase
│ │ │ │ ├── -i-n-s-t-a-l-l-a-t-i-o-n-s.html
│ │ │ │ ├── -r-e-m-o-t-e_-c-o-n-f-i-g.html
│ │ │ │ └── index.html
│ │ │ ├── -gallery
│ │ │ │ ├── -m-i-n-o-r_-b-l-o-c-k_-a-d-d.html
│ │ │ │ ├── -m-i-n-o-r_-b-l-o-c-k_-w-e-b.html
│ │ │ │ ├── -m-i-n-o-r_-i-n-f-o.html
│ │ │ │ ├── -m-i-n-o-r_-m-a-n-a-g-e-m-e-n-t.html
│ │ │ │ ├── -m-i-n-o-r_-m-a-n-a-g-e-r_-r-e-q-u-e-s-t.html
│ │ │ │ ├── -m-i-n-o-r_-n-o-m-e-m-b-e-r.html
│ │ │ │ └── index.html
│ │ │ ├── -m-a-i-n_-a-p-i.html
│ │ │ ├── -m-o-b-i-l-e_-a-p-p.html
│ │ │ ├── -m-o-b-i-l-e_-w-e-b.html
│ │ │ ├── -m-o-b-i-l-e_-w-e-b_-h-t-t-p-s.html
│ │ │ ├── -m-o-v-i-e_-u-p-l-o-a-d.html
│ │ │ ├── -main-info
│ │ │ │ ├── -a-p-p_-m-a-i-n.html
│ │ │ │ ├── -g-a-l-l-e-r-y_-r-a-n-k-i-n-g.html
│ │ │ │ ├── -m-i-n-i_-g-a-l-l-e-r-y_-r-a-n-k-i-n-g.html
│ │ │ │ ├── -m-i-n-o-r_-g-a-l-l-e-r-y_-r-a-n-k-i-n-g.html
│ │ │ │ ├── -n-o-t-i-c-e.html
│ │ │ │ └── index.html
│ │ │ ├── -mini-gallery
│ │ │ │ ├── -j-o-i-n.html
│ │ │ │ ├── -j-o-i-n_-o-k.html
│ │ │ │ ├── -q-u-i-t.html
│ │ │ │ └── index.html
│ │ │ ├── -p-c_-w-e-b.html
│ │ │ ├── -play-service
│ │ │ │ ├── -a-n-d-r-o-i-d_-c-l-i-e-n-t.html
│ │ │ │ ├── -c-h-e-c-k-i-n.html
│ │ │ │ ├── -r-e-g-i-s-t-e-r3.html
│ │ │ │ └── index.html
│ │ │ ├── -r-e-d-i-r-e-c-t.html
│ │ │ ├── -search
│ │ │ │ ├── -s-e-a-r-c-h.html
│ │ │ │ └── index.html
│ │ │ ├── -u-p-l-o-a-d.html
│ │ │ ├── -upload
│ │ │ │ ├── -c-h-e-c-k_-u-p-l-o-a-d_-r-e-s-t-r-i-c-t-i-o-n.html
│ │ │ │ ├── -m-o-v-i-e.html
│ │ │ │ └── index.html
│ │ │ ├── -user
│ │ │ │ ├── -m-y_-g-a-l-l.html
│ │ │ │ ├── -m-y_-g-a-l-l_-m-o-d-i-f-y.html
│ │ │ │ ├── -m-y_-m-a-n-a-g-e_-g-a-l-l_-c-h-e-c-k.html
│ │ │ │ ├── -m-y_-m-i-n-i_-j-o-i-n_-c-h-e-c-k.html
│ │ │ │ └── index.html
│ │ │ └── index.html
│ │ ├── -const
│ │ │ ├── -d-c_-a-p-p_-p-a-c-k-a-g-e.html
│ │ │ ├── -d-c_-a-p-p_-s-i-g-n-a-t-u-r-e.html
│ │ │ ├── -d-c_-a-p-p_-t-a-r-g-e-t_-v-e-r-s-i-o-n.html
│ │ │ ├── -d-c_-a-p-p_-v-e-r-s-i-o-n_-c-o-d-e.html
│ │ │ ├── -d-c_-a-p-p_-v-e-r-s-i-o-n_-n-a-m-e.html
│ │ │ ├── -firebase
│ │ │ │ ├── -a-p-p_-i-d.html
│ │ │ │ ├── -a-u-t-h_-v-e-r-s-i-o-n.html
│ │ │ │ ├── -c-e-r-t.html
│ │ │ │ ├── -c-l-i-v.html
│ │ │ │ ├── -f-i-r-e-b-a-s-e_-c-l-i-e-n-t.html
│ │ │ │ ├── -g-c-m_-v-e-r-s-i-o-n.html
│ │ │ │ ├── -i-n-f-o.html
│ │ │ │ ├── -o-s_-v-e-r-s-i-o-n.html
│ │ │ │ ├── -r-e-m-o-t-e_-c-o-n-f-i-g_-s-d-k_-v-e-r-s-i-o-n.html
│ │ │ │ ├── -s-d-k_-v-e-r-s-i-o-n.html
│ │ │ │ ├── -t-a-r-g-e-t_-v-e-r.html
│ │ │ │ └── index.html
│ │ │ ├── -installations
│ │ │ │ ├── -x_-a-n-d-r-o-i-d_-c-e-r-t.html
│ │ │ │ ├── -x_-a-n-d-r-o-i-d_-p-a-c-k-a-g-e.html
│ │ │ │ ├── -x_-g-o-o-g_-a-p-i_-k-e-y.html
│ │ │ │ └── index.html
│ │ │ ├── -register3
│ │ │ │ ├── -a-p-p.html
│ │ │ │ ├── -c-e-r-t.html
│ │ │ │ ├── -g-c-m_-v-e-r-s-i-o-n.html
│ │ │ │ ├── -s-e-n-d-e-r.html
│ │ │ │ ├── -u-s-e-r_-a-g-e-n-t.html
│ │ │ │ ├── -x_-f-i-r-e-b-a-s-e_-a-p-p_-n-a-m-e_-h-a-s-h.html
│ │ │ │ ├── -x_-s-c-o-p-e_-a-l-l.html
│ │ │ │ ├── -x_-s-c-o-p-e_-r-e-f-r-e-s-h_-r-e-m-o-t-e_-c-o-n-f-i-g.html
│ │ │ │ ├── -x_-s-c-o-p-e_-s-h-o-w_-n-o-t-i-c-e_-m-e-s-s-a-g-e.html
│ │ │ │ └── index.html
│ │ │ ├── -u-s-e-r_-a-g-e-n-t.html
│ │ │ └── index.html
│ │ └── index.html
│ ├── be.zvz.kotlininside
│ │ ├── -kotlin-inside
│ │ │ ├── -companion
│ │ │ │ ├── create-instance.html
│ │ │ │ ├── get-instance.html
│ │ │ │ └── index.html
│ │ │ ├── app.html
│ │ │ ├── auth.html
│ │ │ ├── hashed-app-key.html
│ │ │ ├── http-interface.html
│ │ │ ├── index.html
│ │ │ ├── session.html
│ │ │ └── user.html
│ │ └── index.html
│ └── package-list
├── images
│ ├── anchor-copy-button.svg
│ ├── arrow_down.svg
│ ├── burger.svg
│ ├── copy-icon.svg
│ ├── copy-successful-icon.svg
│ ├── footer-go-to-link.svg
│ ├── go-to-top-icon.svg
│ ├── logo-icon.svg
│ ├── nav-icons
│ │ ├── abstract-class-kotlin.svg
│ │ ├── abstract-class.svg
│ │ ├── annotation-kotlin.svg
│ │ ├── annotation.svg
│ │ ├── class-kotlin.svg
│ │ ├── class.svg
│ │ ├── enum-kotlin.svg
│ │ ├── enum.svg
│ │ ├── exception-class.svg
│ │ ├── field-value.svg
│ │ ├── field-variable.svg
│ │ ├── function.svg
│ │ ├── interface-kotlin.svg
│ │ ├── interface.svg
│ │ ├── object.svg
│ │ └── typealias-kotlin.svg
│ └── theme-toggle.svg
├── index.html
├── navigation.html
├── scripts
│ ├── clipboard.js
│ ├── main.js
│ ├── navigation-loader.js
│ ├── pages.json
│ ├── platform-content-handler.js
│ ├── prism.js
│ ├── sourceset_dependencies.js
│ └── symbol-parameters-wrapper_deferred.js
└── styles
│ ├── font-jb-sans-auto.css
│ ├── jetbrains-mono.css
│ ├── logo-styles.css
│ ├── main.css
│ ├── prism.css
│ └── style.css
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── src
├── main
│ ├── java
│ │ └── be
│ │ │ └── zvz
│ │ │ └── kotlininside
│ │ │ ├── http
│ │ │ └── HttpInterface.java
│ │ │ ├── json
│ │ │ └── JsonBrowser.java
│ │ │ └── migbase64
│ │ │ ├── Base64.java
│ │ │ ├── Base64IO.java
│ │ │ └── Dictionary.java
│ ├── kotlin
│ │ └── be
│ │ │ └── zvz
│ │ │ └── kotlininside
│ │ │ ├── KotlinInside.kt
│ │ │ ├── api
│ │ │ ├── article
│ │ │ │ ├── ArticleDelete.kt
│ │ │ │ ├── ArticleHitUpvote.kt
│ │ │ │ ├── ArticleList.kt
│ │ │ │ ├── ArticleModify.kt
│ │ │ │ ├── ArticleRead.kt
│ │ │ │ ├── ArticleReport.kt
│ │ │ │ ├── ArticleVote.kt
│ │ │ │ └── ArticleWrite.kt
│ │ │ ├── async
│ │ │ │ ├── article
│ │ │ │ │ ├── AsyncArticleDelete.kt
│ │ │ │ │ ├── AsyncArticleHitUpvote.kt
│ │ │ │ │ ├── AsyncArticleList.kt
│ │ │ │ │ ├── AsyncArticleModify.kt
│ │ │ │ │ ├── AsyncArticleRead.kt
│ │ │ │ │ ├── AsyncArticleReport.kt
│ │ │ │ │ ├── AsyncArticleVote.kt
│ │ │ │ │ └── AsyncArticleWrite.kt
│ │ │ │ ├── comment
│ │ │ │ │ ├── AsyncCommentDelete.kt
│ │ │ │ │ ├── AsyncCommentRead.kt
│ │ │ │ │ └── AsyncCommentWrite.kt
│ │ │ │ ├── dccon
│ │ │ │ │ ├── AsyncDCConBuy.kt
│ │ │ │ │ ├── AsyncDCConDetail.kt
│ │ │ │ │ └── AsyncDCConList.kt
│ │ │ │ ├── generic
│ │ │ │ │ ├── AsyncGalleryRanking.kt
│ │ │ │ │ ├── AsyncGallerySearch.kt
│ │ │ │ │ ├── AsyncMainPage.kt
│ │ │ │ │ ├── AsyncMiniGalleryRanking.kt
│ │ │ │ │ ├── AsyncMinorGalleryInfo.kt
│ │ │ │ │ ├── AsyncMinorGalleryRanking.kt
│ │ │ │ │ ├── AsyncTotalSearch.kt
│ │ │ │ │ ├── minigallery
│ │ │ │ │ │ ├── AsyncJoinMiniGallery.kt
│ │ │ │ │ │ └── AsyncQuitMiniGallery.kt
│ │ │ │ │ └── userinfo
│ │ │ │ │ │ ├── AsyncCheckJoinedMiniGallery.kt
│ │ │ │ │ │ ├── AsyncCheckManagedGallery.kt
│ │ │ │ │ │ ├── AsyncModifyMyGall.kt
│ │ │ │ │ │ └── AsyncMyGall.kt
│ │ │ │ └── management
│ │ │ │ │ ├── AsyncChangeHeadText.kt
│ │ │ │ │ ├── AsyncGallerySetting.kt
│ │ │ │ │ ├── AsyncNoMemberBlock.kt
│ │ │ │ │ ├── AsyncNotice.kt
│ │ │ │ │ ├── AsyncRecommend.kt
│ │ │ │ │ └── AsyncUserBlock.kt
│ │ │ ├── comment
│ │ │ │ ├── CommentDelete.kt
│ │ │ │ ├── CommentRead.kt
│ │ │ │ └── CommentWrite.kt
│ │ │ ├── dccon
│ │ │ │ ├── DCConBuy.kt
│ │ │ │ ├── DCConDetail.kt
│ │ │ │ ├── DCConInsert.kt
│ │ │ │ └── DCConList.kt
│ │ │ ├── generic
│ │ │ │ ├── GalleryRanking.kt
│ │ │ │ ├── GallerySearch.kt
│ │ │ │ ├── MainPage.kt
│ │ │ │ ├── MiniGalleryRanking.kt
│ │ │ │ ├── MinorGalleryInfo.kt
│ │ │ │ ├── MinorGalleryRanking.kt
│ │ │ │ ├── MovieUpload.kt
│ │ │ │ ├── TotalSearch.kt
│ │ │ │ ├── minigallery
│ │ │ │ │ ├── JoinMiniGallery.kt
│ │ │ │ │ └── QuitMiniGallery.kt
│ │ │ │ └── userinfo
│ │ │ │ │ ├── CheckJoinedMiniGallery.kt
│ │ │ │ │ ├── CheckManagedGallery.kt
│ │ │ │ │ ├── ModifyMyGall.kt
│ │ │ │ │ └── MyGall.kt
│ │ │ ├── management
│ │ │ │ ├── ChangeHeadText.kt
│ │ │ │ ├── GallerySetting.kt
│ │ │ │ ├── NoMemberBlock.kt
│ │ │ │ ├── Notice.kt
│ │ │ │ ├── Recommend.kt
│ │ │ │ └── UserBlock.kt
│ │ │ └── type
│ │ │ │ ├── Article.kt
│ │ │ │ ├── DCCon.kt
│ │ │ │ ├── Gallery.kt
│ │ │ │ ├── HeadText.kt
│ │ │ │ ├── comment
│ │ │ │ ├── Comment.kt
│ │ │ │ ├── DCConComment.kt
│ │ │ │ └── StringComment.kt
│ │ │ │ └── content
│ │ │ │ ├── Content.kt
│ │ │ │ ├── DCConContent.kt
│ │ │ │ ├── HtmlContent.kt
│ │ │ │ ├── ImageContent.kt
│ │ │ │ ├── MarkdownContent.kt
│ │ │ │ ├── MovieContent.kt
│ │ │ │ └── StringContent.kt
│ │ │ ├── exception
│ │ │ └── InsufficientPermissionException.kt
│ │ │ ├── http
│ │ │ ├── DefaultHttpClient.kt
│ │ │ ├── HttpException.kt
│ │ │ └── Request.kt
│ │ │ ├── security
│ │ │ ├── App.kt
│ │ │ ├── Auth.kt
│ │ │ └── RandomFidGenerator.kt
│ │ │ ├── session
│ │ │ ├── Session.kt
│ │ │ ├── SessionDetail.kt
│ │ │ └── user
│ │ │ │ ├── Anonymous.kt
│ │ │ │ ├── LoginUser.kt
│ │ │ │ ├── User.kt
│ │ │ │ ├── UserType.kt
│ │ │ │ └── named
│ │ │ │ ├── DuplicateNamed.kt
│ │ │ │ └── Named.kt
│ │ │ ├── utils
│ │ │ └── StringUtil.kt
│ │ │ └── value
│ │ │ ├── ApiUrl.kt
│ │ │ └── Const.kt
│ └── proto
│ │ └── checkin.proto
└── test
│ └── kotlin
│ └── be
│ └── zvz
│ └── kotlininside
│ └── KotlinInsideTest.kt
└── 구현 TODO.md
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*{kt,kts}]
2 | disabled_rules = no-wildcard-imports
3 | max_line_length = 130
4 | ij_kotlin_allow_trailing_comma_on_call_site = false
5 | ij_kotlin_allow_trailing_comma = false
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: gradle
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
8 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | # The branches below must be a subset of the branches above
8 | branches: [master]
9 | schedule:
10 | - cron: '0 2 * * 0'
11 |
12 | jobs:
13 | analyze:
14 | name: Analyze
15 | runs-on: ubuntu-latest
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | # Override automatic language detection by changing the below list
21 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
22 | language: ['java']
23 | # Learn more...
24 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
25 |
26 | steps:
27 | - name: Checkout repository
28 | uses: actions/checkout@v2
29 | with:
30 | # We must fetch at least the immediate parents so that if this is
31 | # a pull request then we can checkout the head.
32 | fetch-depth: 2
33 |
34 | # If this run was triggered by a pull request event, then checkout
35 | # the head of the pull request instead of the merge commit.
36 | - run: git checkout HEAD^2
37 | if: ${{ github.event_name == 'pull_request' }}
38 |
39 | # Initializes the CodeQL tools for scanning.
40 | - name: Initialize CodeQL
41 | uses: github/codeql-action/init@v2
42 | with:
43 | languages: ${{ matrix.language }}
44 | # If you wish to specify custom queries, you can do so here or in a config file.
45 | # By default, queries listed here will override any specified in a config file.
46 | # Prefix the list here with "+" to use these queries and those in the config file.
47 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
48 |
49 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
50 | # If this step fails, then you should remove it and run the build manually (see below)
51 | - name: Autobuild
52 | uses: github/codeql-action/autobuild@v2
53 |
54 | # ℹ️ Command-line programs to run using the OS shell.
55 | # 📚 https://git.io/JvXDl
56 |
57 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
58 | # and modify them (or add more) to build your code if your project
59 | # uses a compiled language
60 |
61 | #- run: |
62 | # make bootstrap
63 | # make release
64 |
65 | - name: Perform CodeQL Analysis
66 | uses: github/codeql-action/analyze@v2
67 |
--------------------------------------------------------------------------------
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - 'master'
7 | - '!dependabot**'
8 | - '!dev'
9 |
10 | jobs:
11 | build:
12 |
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | java: [ '17', '8' ]
17 |
18 | steps:
19 | - uses: actions/checkout@v1
20 | - name: Set up JDK ${{ matrix.java }}
21 | uses: actions/setup-java@v1
22 | with:
23 | java-version: ${{ matrix.java }}
24 | - name: Test with Gradle
25 | run: ./gradlew test -i
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Gradle project-specific cache directory
2 | .gradle
3 |
4 | # Ignore Gradle build output directory
5 | build
6 |
7 | local.properties
8 | /gradle.properties
9 | .idea
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: java
3 | jdk:
4 | - openjdk8
5 | - openjdk9
6 | - openjdk11
7 | - oraclejdk11
8 |
9 |
10 | sudo: false
11 |
12 | addons:
13 | apt:
14 | packages:
15 | - tree
16 |
17 | # https://docs.travis-ci.com/user/customizing-the-build#Skipping-the-Installation-Step
18 | install: true # if we don't skip install, ./gradlew assemble is invoked, but this task is not available.
19 |
20 | script:
21 | - ./gradlew test -i
22 |
23 | # configure caching (https://docs.travis-ci.com/user/languages/java/#Caching)
24 | before_cache:
25 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
26 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
27 | # format from https://docs.travis-ci.com/user/caching/#Enabling-multiple-caching-features
28 | cache:
29 | bundler: true
30 | directories:
31 | - $HOME/.gradle/caches/
32 | - $HOME/.gradle/wrapper/
33 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside.api.generic/-main-page/-main-page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MainPage
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
MainPage
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside.migbase64/-base64-i-o/-base64-i-o.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Base64IO
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
Base64IO
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside.migbase64/-base64/-base64.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Base64
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
Base64
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside.security/-app/id.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | id
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
id
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside.security/-auth/-auth.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Auth
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
Auth
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside/-kotlin-inside/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | app
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
app
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside/-kotlin-inside/auth.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | auth
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
auth
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/-kotlin-inside/be.zvz.kotlininside/-kotlin-inside/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | user
6 |
7 |
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
user
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/images/anchor-copy-button.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/arrow_down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/burger.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/copy-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/copy-successful-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/footer-go-to-link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/go-to-top-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/logo-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/abstract-class-kotlin.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/abstract-class.svg:
--------------------------------------------------------------------------------
1 |
2 |
21 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/annotation-kotlin.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/annotation.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/class-kotlin.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/class.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/enum-kotlin.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/enum.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/exception-class.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/field-value.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/field-variable.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/function.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/interface-kotlin.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/interface.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/object.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/images/nav-icons/typealias-kotlin.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/images/theme-toggle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/scripts/clipboard.js:
--------------------------------------------------------------------------------
1 | window.addEventListener('load', () => {
2 | document.querySelectorAll('span.copy-icon').forEach(element => {
3 | element.addEventListener('click', (el) => copyElementsContentToClipboard(element));
4 | })
5 |
6 | document.querySelectorAll('span.anchor-icon').forEach(element => {
7 | element.addEventListener('click', (el) => {
8 | if(element.hasAttribute('pointing-to')){
9 | const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to')
10 | copyTextToClipboard(element, location)
11 | }
12 | });
13 | })
14 | })
15 |
16 | const copyElementsContentToClipboard = (element) => {
17 | const selection = window.getSelection();
18 | const range = document.createRange();
19 | range.selectNodeContents(element.parentNode.parentNode);
20 | selection.removeAllRanges();
21 | selection.addRange(range);
22 |
23 | copyAndShowPopup(element, () => selection.removeAllRanges())
24 | }
25 |
26 | const copyTextToClipboard = (element, text) => {
27 | var textarea = document.createElement("textarea");
28 | textarea.textContent = text;
29 | textarea.style.position = "fixed";
30 | document.body.appendChild(textarea);
31 | textarea.select();
32 |
33 | copyAndShowPopup(element, () => document.body.removeChild(textarea))
34 | }
35 |
36 | const copyAndShowPopup = (element, after) => {
37 | try {
38 | document.execCommand('copy');
39 | element.nextElementSibling.classList.add('active-popup');
40 | setTimeout(() => {
41 | element.nextElementSibling.classList.remove('active-popup');
42 | }, 1200);
43 | } catch (e) {
44 | console.error('Failed to write to clipboard:', e)
45 | }
46 | finally {
47 | if(after) after()
48 | }
49 | }
50 |
51 | const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0]
52 |
53 |
--------------------------------------------------------------------------------
/docs/scripts/navigation-loader.js:
--------------------------------------------------------------------------------
1 | navigationPageText = fetch(pathToRoot + "navigation.html").then(response => response.text())
2 |
3 | displayNavigationFromPage = () => {
4 | navigationPageText.then(data => {
5 | document.getElementById("sideMenu").innerHTML = data;
6 | }).then(() => {
7 | document.querySelectorAll(".overview > a").forEach(link => {
8 | link.setAttribute("href", pathToRoot + link.getAttribute("href"));
9 | })
10 | }).then(() => {
11 | document.querySelectorAll(".sideMenuPart").forEach(nav => {
12 | if (!nav.classList.contains("hidden"))
13 | nav.classList.add("hidden")
14 | })
15 | }).then(() => {
16 | revealNavigationForCurrentPage()
17 | }).then(() => {
18 | scrollNavigationToSelectedElement()
19 | })
20 | document.querySelectorAll('.footer a[href^="#"]').forEach(anchor => {
21 | anchor.addEventListener('click', function (e) {
22 | e.preventDefault();
23 | document.querySelector(this.getAttribute('href')).scrollIntoView({
24 | behavior: 'smooth'
25 | });
26 | });
27 | });
28 | }
29 |
30 | revealNavigationForCurrentPage = () => {
31 | let pageId = document.getElementById("content").attributes["pageIds"].value.toString();
32 | let parts = document.querySelectorAll(".sideMenuPart");
33 | let found = 0;
34 | do {
35 | parts.forEach(part => {
36 | if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) {
37 | found = 1;
38 | if (part.classList.contains("hidden")) {
39 | part.classList.remove("hidden");
40 | part.setAttribute('data-active', "");
41 | }
42 | revealParents(part)
43 | }
44 | });
45 | pageId = pageId.substring(0, pageId.lastIndexOf("/"))
46 | } while (pageId.indexOf("/") !== -1 && found === 0)
47 | };
48 | revealParents = (part) => {
49 | if (part.classList.contains("sideMenuPart")) {
50 | if (part.classList.contains("hidden"))
51 | part.classList.remove("hidden");
52 | revealParents(part.parentNode)
53 | }
54 | };
55 |
56 | scrollNavigationToSelectedElement = () => {
57 | let selectedElement = document.querySelector('div.sideMenuPart[data-active]')
58 | if (selectedElement == null) { // nothing selected, probably just the main page opened
59 | return
60 | }
61 |
62 | let hasIcon = selectedElement.querySelectorAll(":scope > div.overview span.nav-icon").length > 0
63 |
64 | // for instance enums also have children and are expandable, but are not package/module elements
65 | let isPackageElement = selectedElement.children.length > 1 && !hasIcon
66 | if (isPackageElement) {
67 | // if package is selected or linked, it makes sense to align it to top
68 | // so that you can see all the members it contains
69 | selectedElement.scrollIntoView(true)
70 | } else {
71 | // if a member within a package is linked, it makes sense to center it since it,
72 | // this should make it easier to look at surrounding members
73 | selectedElement.scrollIntoView({
74 | behavior: 'auto',
75 | block: 'center',
76 | inline: 'center'
77 | })
78 | }
79 | }
80 |
81 | /*
82 | This is a work-around for safari being IE of our times.
83 | It doesn't fire a DOMContentLoaded, presumabely because eventListener is added after it wants to do it
84 | */
85 | if (document.readyState == 'loading') {
86 | window.addEventListener('DOMContentLoaded', () => {
87 | displayNavigationFromPage()
88 | })
89 | } else {
90 | displayNavigationFromPage()
91 | }
92 |
--------------------------------------------------------------------------------
/docs/scripts/sourceset_dependencies.js:
--------------------------------------------------------------------------------
1 | sourceset_dependencies='{":dokkaHtml/main":[]}'
2 |
--------------------------------------------------------------------------------
/docs/scripts/symbol-parameters-wrapper_deferred.js:
--------------------------------------------------------------------------------
1 | // helps with some corner cases where starts working already,
2 | // but the signature is not yet long enough to be wrapped
3 | const leftPaddingPx = 60
4 |
5 | const symbolResizeObserver = new ResizeObserver(entries => {
6 | entries.forEach(entry => {
7 | const symbolElement = entry.target
8 | symbolResizeObserver.unobserve(symbolElement) // only need it once, otherwise will be executed multiple times
9 | wrapSymbolParameters(symbolElement);
10 | })
11 | });
12 |
13 | const wrapAllSymbolParameters = () => {
14 | document.querySelectorAll("div.symbol").forEach(symbol => wrapSymbolParameters(symbol))
15 | }
16 |
17 | const wrapSymbolParameters = (symbol) => {
18 | let parametersBlock = symbol.querySelector("span.parameters")
19 | if (parametersBlock == null) {
20 | return // nothing to wrap
21 | }
22 |
23 | let symbolBlockWidth = symbol.clientWidth
24 |
25 | // Even though the script is marked as `defer` and we wait for `DOMContentLoaded` event,
26 | // it can happen that `symbolBlockWidth` is 0, indicating that something hasn't been loaded.
27 | // In this case, just retry once all styles have been applied and it has been resized correctly.
28 | if (symbolBlockWidth === 0) {
29 | symbolResizeObserver.observe(symbol)
30 | return
31 | }
32 |
33 | let innerTextWidth = Array.from(symbol.children)
34 | .filter(it => !it.classList.contains("block")) // blocks are usually on their own (like annotations), so ignore it
35 | .map(it => it.getBoundingClientRect().width).reduce((a, b) => a + b, 0)
36 |
37 | // if signature text takes up more than a single line, wrap params for readability
38 | let shouldWrapParams = innerTextWidth > (symbolBlockWidth - leftPaddingPx)
39 | if (shouldWrapParams) {
40 | parametersBlock.classList.add("wrapped")
41 | parametersBlock.querySelectorAll("span.parameter").forEach(param => {
42 | // has to be a physical indent so that it can be copied. styles like
43 | // paddings and `::before { content: " " }` do not work for that
44 | param.prepend(createNbspIndent())
45 | })
46 | }
47 | }
48 |
49 | const createNbspIndent = () => {
50 | let indent = document.createElement("span")
51 | indent.append(document.createTextNode("\u00A0\u00A0\u00A0\u00A0"))
52 | indent.classList.add("nbsp-indent")
53 | return indent
54 | }
55 |
56 | const resetAllSymbolParametersWrapping = () => {
57 | document.querySelectorAll("div.symbol").forEach(symbol => resetSymbolParametersWrapping(symbol))
58 | }
59 |
60 | const resetSymbolParametersWrapping = (symbol) => {
61 | let parameters = symbol.querySelector("span.parameters")
62 | if (parameters != null) {
63 | parameters.classList.remove("wrapped")
64 | parameters.querySelectorAll("span.parameter").forEach(param => {
65 | let indent = param.querySelector("span.nbsp-indent")
66 | if (indent != null) indent.remove()
67 | })
68 | }
69 | }
70 |
71 | if (document.readyState === 'loading') {
72 | window.addEventListener('DOMContentLoaded', () => {
73 | wrapAllSymbolParameters()
74 | })
75 | } else {
76 | wrapAllSymbolParameters()
77 | }
78 |
79 | window.onresize = event => {
80 | // need to re-calculate if params need to be wrapped after resize
81 | resetAllSymbolParametersWrapping()
82 | wrapAllSymbolParameters()
83 | }
84 |
--------------------------------------------------------------------------------
/docs/styles/font-jb-sans-auto.css:
--------------------------------------------------------------------------------
1 | /* Light weight */
2 | @font-face {
3 | font-family: 'JetBrains Sans';
4 | src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Light.woff2') format('woff2'), url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Light.woff') format('woff');
5 | font-weight: 300;
6 | font-style: normal;
7 | }
8 | /* Regular weight */
9 | @font-face {
10 | font-family: 'JetBrains Sans';
11 | src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Regular.woff2') format('woff2'), url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Regular.woff') format('woff');
12 | font-weight: 400;
13 | font-style: normal;
14 | }
15 | /* SemiBold weight */
16 | @font-face {
17 | font-family: 'JetBrains Sans';
18 | src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-SemiBold.woff2') format('woff2'), url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-SemiBold.woff') format('woff');
19 | font-weight: 600;
20 | font-style: normal;
21 | }
22 |
23 | @supports (font-variation-settings: normal) {
24 | @font-face {
25 | font-family: 'JetBrains Sans';
26 | src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans.woff2') format('woff2 supports variations'),
27 | url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans.woff2') format('woff2-variations'),
28 | url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans.woff') format('woff-variations');
29 | font-weight: 100 900;
30 | font-style: normal;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/docs/styles/jetbrains-mono.css:
--------------------------------------------------------------------------------
1 | @font-face{
2 | font-family: 'JetBrains Mono';
3 | src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/web/JetBrainsMono-Regular.eot') format('embedded-opentype'),
4 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/webfonts/JetBrainsMono-Regular.woff2') format('woff2'),
5 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/ttf/JetBrainsMono-Regular.ttf') format('truetype');
6 | font-weight: normal;
7 | font-style: normal;
8 | }
9 |
10 | @font-face{
11 | font-family: 'JetBrains Mono';
12 | src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/web/JetBrainsMono-Bold.eot') format('embedded-opentype'),
13 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/webfonts/JetBrainsMono-Bold.woff2') format('woff2'),
14 | url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/fonts/ttf/JetBrainsMono-Bold.ttf') format('truetype');
15 | font-weight: bold;
16 | font-style: bold;
17 | }
--------------------------------------------------------------------------------
/docs/styles/logo-styles.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --dokka-logo-image-url: url('../images/logo-icon.svg');
3 | --dokka-logo-height: 50px;
4 | --dokka-logo-width: 50px;
5 | }
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/organization/KotlinInside/4b2cdeb55873a3f08b2fa717a507ef8f2ad7835f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This file was generated by the Gradle 'init' task.
3 | *
4 | * The settings file is used to specify which projects to include in your build.
5 | *
6 | * Detailed information about configuring a multi-project build in Gradle can be found
7 | * in the user guide at https://docs.gradle.org/5.1/userguide/multi_project_builds.html
8 | */
9 |
10 | rootProject.name = 'KotlinInside'
11 |
--------------------------------------------------------------------------------
/src/main/java/be/zvz/kotlininside/migbase64/Base64IO.java:
--------------------------------------------------------------------------------
1 | // Created on 2007-07-04
2 | package be.zvz.kotlininside.migbase64;
3 |
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.OutputStream;
7 |
8 | import static be.zvz.kotlininside.migbase64.Dictionary.CA;
9 |
10 | /**
11 | * Base64 for InputStream
Licence = BSD
12 | *
13 | * @author shamilbi shamilbi@users.sourceforge.net
14 | * @see Base64
15 | */
16 | public class Base64IO {
17 |
18 | private static final int _8_BIT = 0xff;
19 |
20 | private static final int _6_BIT = 0x3f;
21 |
22 | private static final byte EQUAL = '=';
23 |
24 | /**
25 | * Encodes a raw InputStream into a BASE64 OutputStream representation in
26 | * accordance with RFC 2045. This implementation was inspired by MIG Base64
27 | * {@link Base64#encodeToByte(byte[], boolean)}
28 | *
29 | * @param in
30 | * @param out
31 | * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
32 | * No line separator will be in breach of RFC 2045 which
33 | * specifies max 76 per line but will be a little faster.
34 | * @throws IOException
35 | */
36 | public final static void encode(InputStream in, OutputStream out,
37 | boolean lineSep) throws IOException {
38 | // must be inBuf.length % 3 == 0
39 | final byte[] inBuf = new byte[1024 * 32 * 3];
40 | final byte[] outBuf = new byte[4 * 19 + 2];
41 |
42 | int eLen = inBuf.length; // Length of even 24-bits.
43 | int left = 0;
44 | int inOff = 0;
45 | boolean needsRn = false;
46 | int cc = 0;
47 |
48 | while (true) {
49 | // read full buffer
50 | final int read = in.read(inBuf, inOff, inBuf.length - inOff);
51 |
52 | if (read == -1) {
53 | // last bytes
54 | left = inOff % 3; // 0 - 2.
55 | eLen = inOff - left; // Length of even 24-bits.
56 | } else {
57 | inOff += read;
58 | if (inOff != inBuf.length) {
59 | continue;
60 | }
61 | }
62 |
63 | int outOff = 0;
64 |
65 | // encode buffer
66 | // Encode even 24-bits
67 |
68 | for (int s = 0/* , d = 0, cc = 0 */; s < eLen; ) {
69 | if (needsRn) {
70 | outBuf[outOff++] = '\r';
71 | outBuf[outOff++] = '\n';
72 | needsRn = false;
73 | }
74 |
75 | // Copy next three bytes into lower 24 bits of int, paying
76 | // attension to sign.
77 | int i = (inBuf[s++] & _8_BIT) << 16
78 | | (inBuf[s++] & _8_BIT) << 8 | (inBuf[s++] & _8_BIT);
79 |
80 | // Encode the int into four chars
81 | int outOff2 = outOff += 4;
82 | outBuf[--outOff2] = CA[i & _6_BIT];
83 | outBuf[--outOff2] = CA[(i >>>= 6) & _6_BIT];
84 | outBuf[--outOff2] = CA[(i >>>= 6) & _6_BIT];
85 | outBuf[--outOff2] = CA[(i >>>= 6) & _6_BIT];
86 |
87 | if (++cc == 19 /* && d < dLen - 2 */) {
88 | cc = 0;
89 | out.write(outBuf, 0, outOff);
90 | outOff = 0;
91 |
92 | // Add optional line separator
93 | if (lineSep) {
94 | needsRn = true;
95 | }
96 | }
97 | }
98 | out.write(outBuf, 0, outOff);
99 |
100 | // Pad and encode last bits if source isn't an even 24 bits.
101 | if (left > 0) {
102 | // Prepare the int
103 | int i = ((inBuf[eLen] & _8_BIT) << 10)
104 | | (left == 2 ? ((inBuf[inOff - 1] & _8_BIT) << 2) : 0);
105 |
106 | // Set last four chars
107 | outBuf[3] = EQUAL;
108 | outBuf[2] = left == 2 ? CA[i & _6_BIT] : EQUAL;
109 | outBuf[1] = CA[(i >>>= 6) & _6_BIT];
110 | outBuf[0] = CA[i >> 6];
111 | out.write(outBuf, 0, 4);
112 | }
113 |
114 | if (read == -1) {
115 | break;
116 | }
117 |
118 | // new block
119 | inOff = 0;
120 | }
121 | }
122 |
123 | }
--------------------------------------------------------------------------------
/src/main/java/be/zvz/kotlininside/migbase64/Dictionary.java:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.migbase64;
2 |
3 | /*package*/ interface Dictionary {
4 | byte[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes();
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/KotlinInside.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside
2 |
3 | import be.zvz.kotlininside.http.HttpInterface
4 | import be.zvz.kotlininside.security.App
5 | import be.zvz.kotlininside.security.Auth
6 | import be.zvz.kotlininside.session.Session
7 | import be.zvz.kotlininside.session.user.LoginUser
8 | import be.zvz.kotlininside.session.user.User
9 | import java.util.*
10 |
11 | class KotlinInside private constructor(
12 | val user: User,
13 | val httpInterface: HttpInterface,
14 | private val sessionAutoRefresh: Boolean
15 | ) {
16 | val auth = Auth()
17 | lateinit var hashedAppKey: String
18 | lateinit var app: App
19 | lateinit var session: Session
20 |
21 | private fun init() {
22 | this.hashedAppKey = auth.generateHashedAppKey()
23 | this.app = App(hashedAppKey, auth.fetchAppId(hashedAppKey))
24 | this.session = auth.login(user)
25 |
26 | if (sessionAutoRefresh) {
27 | val timer = Timer()
28 |
29 | timer.schedule(
30 | object : TimerTask() {
31 | override fun run() {
32 | if (user is LoginUser) {
33 | synchronized(instance) {
34 | instance.hashedAppKey = instance.auth.generateHashedAppKey()
35 | instance.app =
36 | App(instance.hashedAppKey, instance.auth.fetchAppId(getInstance().hashedAppKey))
37 | instance.session = instance.auth.login(user)
38 | }
39 | }
40 | }
41 | },
42 | 43200L * 1000,
43 | 43200L * 1000
44 | )
45 | }
46 | }
47 |
48 | companion object {
49 | private lateinit var instance: KotlinInside
50 |
51 | /**
52 | * [KotlinInside] 인스턴스를 생성합니다.
53 | * @param user 인스턴스 생성과 동시에 로그인할 유저
54 | * @param httpInterface KotlinInside에서 사용할 HttpInterface
55 | * @param sessionAutoRefresh KotlinInside가 세션을 12시간마다 자동으로 새로고침 할지 정합니다.
56 | */
57 | @JvmStatic
58 | @JvmOverloads
59 | @Synchronized
60 | fun createInstance(user: User, httpInterface: HttpInterface, sessionAutoRefresh: Boolean = false) {
61 | if (!::instance.isInitialized) {
62 | instance = KotlinInside(user, httpInterface, sessionAutoRefresh)
63 | instance.init()
64 | }
65 | }
66 |
67 | /**
68 | *
69 | * @return [KotlinInside] 인스턴스를 반환합니다.
70 | */
71 | @JvmStatic
72 | fun getInstance(): KotlinInside = instance
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/article/ArticleDelete.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.article
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 |
11 | class ArticleDelete @JvmOverloads constructor(
12 | private val gallId: String,
13 | private val articleId: Int,
14 | private val session: Session,
15 | private val fcmToken: String = KotlinInside.getInstance().auth.fcmToken
16 | ) {
17 | data class DeleteResult(
18 | val result: Boolean,
19 | val cause: String? = null,
20 | val message: String? = null,
21 | val status: Int? = null
22 | )
23 |
24 | /**
25 | * 글을 삭제합니다.
26 | * @exception [be.zvz.kotlininside.http.HttpException] 글을 삭제하지 못할 경우, HttpException 발생
27 | */
28 | @Throws(HttpException::class)
29 | fun delete(): DeleteResult {
30 | val option = Request.getDefaultOption()
31 | .addMultipartParameter("id", gallId)
32 | .addMultipartParameter("client_token", fcmToken)
33 | .addMultipartParameter("no", articleId.toString())
34 | .addMultipartParameter("mode", "board_del")
35 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
36 |
37 | if (session.user is Anonymous) {
38 | option
39 | .addMultipartParameter("write_pw", session.user.password)
40 | } else {
41 | option
42 | .addMultipartParameter("user_id", session.detail!!.userId)
43 | }
44 |
45 | var json = JsonBrowser.parse(KotlinInside.getInstance().httpInterface.upload(ApiUrl.Article.DELETE, option))
46 |
47 | if (json.isList) {
48 | json = json.index(0)
49 | }
50 |
51 | return DeleteResult(
52 | result = json.get("result").asBoolean(),
53 | message = json.get("message").text(),
54 | status = json.get("status").asNullableInteger(),
55 | cause = json.get("cause").text()
56 | )
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/article/ArticleHitUpvote.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.article
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 |
11 | class ArticleHitUpvote(
12 | private val gallId: String,
13 | private val articleId: Int,
14 | private val session: Session
15 | ) {
16 | data class HitUpvoteResult(
17 | val result: Boolean,
18 | val cause: String? = null
19 | )
20 |
21 | /**
22 | * 글을 힛갤 추천합니다.
23 | * @exception [be.zvz.kotlininside.http.HttpException] 글을 힛갤 추천하지 못할 경우, HttpException 발생
24 | */
25 | @Throws(HttpException::class)
26 | fun upvote(): HitUpvoteResult {
27 | val option = Request.getDefaultOption()
28 | .addMultipartParameter("id", gallId)
29 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
30 | .addMultipartParameter("no", articleId.toString())
31 |
32 | if (session.user !is Anonymous) {
33 | option
34 | .addMultipartParameter("confirm_id", session.detail!!.userId)
35 | }
36 |
37 | val json = JsonBrowser.parse(KotlinInside.getInstance().httpInterface.upload(ApiUrl.Article.HIT_UPVOTE, option))
38 | .index(0)
39 |
40 | return HitUpvoteResult(
41 | result = json.get("result").asBoolean(),
42 | cause = json.get("cause").text()
43 | )
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/article/ArticleReport.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.article
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.session.Session
6 | import be.zvz.kotlininside.session.user.Anonymous
7 | import be.zvz.kotlininside.value.ApiUrl
8 |
9 | class ArticleReport(
10 | private val gallId: String,
11 | private val articleId: Int,
12 | private val session: Session
13 | ) {
14 | /**
15 | * 글 신고 링크를 반환합니다.
16 | */
17 | fun getLink(): String {
18 | val url =
19 | "${ApiUrl.Article.REPORT}?app_id=${KotlinInside.getInstance().auth.getAppId()}&id=$gallId&no=$articleId"
20 |
21 | if (session.user !is Anonymous) {
22 | url.plus("&confirm_id=${session.detail!!.userId}")
23 | }
24 |
25 | return Request.redirectUrl(url)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/article/ArticleVote.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.article
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.LoginUser
9 | import be.zvz.kotlininside.value.ApiUrl
10 |
11 | class ArticleVote(
12 | private val gallId: String,
13 | private val articleId: Int,
14 | private val session: Session
15 | ) {
16 | data class VoteResult(
17 | val result: Boolean,
18 | val cause: String,
19 | val member: Int? = null
20 | )
21 |
22 | /**
23 | * 글을 추천합니다.
24 | * @exception [be.zvz.kotlininside.http.HttpException] 추천이 실패할 경우, HttpException 발생
25 | */
26 | @Throws(HttpException::class)
27 | fun upvote(): VoteResult {
28 | val option = Request.getDefaultOption()
29 | .addMultipartParameter("id", gallId)
30 | .addMultipartParameter("no", articleId.toString())
31 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
32 |
33 | if (session.user is LoginUser) {
34 | option.addMultipartParameter("confirm_id", session.detail!!.userId)
35 | }
36 |
37 | var json = JsonBrowser.parse(
38 | KotlinInside.getInstance().httpInterface.upload(
39 | ApiUrl.Article.UPVOTE,
40 | option
41 | )
42 | )
43 |
44 | if (json.isList) {
45 | json = json.index(0)
46 | }
47 |
48 | return VoteResult(
49 | result = json.get("result").asBoolean(),
50 | cause = json.get("cause").safeText(),
51 | member = json.get("member").asNullableInteger()
52 | )
53 | }
54 |
55 | /**
56 | * 글을 비추천합니다.
57 | * @exception [be.zvz.kotlininside.http.HttpException] 비추천이 실패할 경우, HttpException 발생
58 | */
59 | @Throws(HttpException::class)
60 | fun downvote(): VoteResult {
61 | val option = Request.getDefaultOption()
62 | .addMultipartParameter("id", gallId)
63 | .addMultipartParameter("no", articleId.toString())
64 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
65 |
66 | if (session.user is LoginUser) {
67 | option.addMultipartParameter("confirm_id", session.detail!!.userId)
68 | }
69 |
70 | val json = JsonBrowser.parse(
71 | KotlinInside.getInstance().httpInterface.upload(
72 | ApiUrl.Article.DOWNVOTE,
73 | option
74 | )
75 | ).index(0)
76 |
77 | return VoteResult(
78 | result = json.get("result").asBoolean(),
79 | cause = json.get("cause").safeText(),
80 | member = null
81 | )
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleDelete.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.article.ArticleDelete
5 | import be.zvz.kotlininside.session.Session
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.async
8 | import kotlinx.coroutines.coroutineScope
9 |
10 | class AsyncArticleDelete @JvmOverloads constructor(
11 | gallId: String,
12 | articleId: Int,
13 | session: Session,
14 | fcmToken: String = KotlinInside.getInstance().auth.fcmToken
15 | ) {
16 | private val articleDelete = ArticleDelete(gallId, articleId, session, fcmToken)
17 |
18 | suspend fun deleteAsync() = coroutineScope {
19 | async(Dispatchers.IO) {
20 | articleDelete.delete()
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleHitUpvote.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.api.article.ArticleHitUpvote
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncArticleHitUpvote(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session
13 | ) {
14 | private val articleHitUpvote = ArticleHitUpvote(gallId, articleId, session)
15 |
16 | suspend fun upvoteAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | articleHitUpvote.upvote()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleList.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.api.article.ArticleList
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncArticleList @JvmOverloads constructor(
10 | gallId: String,
11 | searchKeyword: String,
12 | searchType: ArticleList.SearchType = ArticleList.SearchType.ALL,
13 | page: Int = 1,
14 | recommend: Boolean = false,
15 | notice: Boolean = false,
16 | headId: Int = 0,
17 | session: Session? = null
18 | ) {
19 | @JvmOverloads
20 | constructor(
21 | gallId: String,
22 | page: Int = 1,
23 | recommend: Boolean = false,
24 | notice: Boolean = false,
25 | headId: Int = 0,
26 | session: Session? = null
27 | ) : this(
28 | gallId = gallId,
29 | searchKeyword = "",
30 | searchType = ArticleList.SearchType.ALL,
31 | page = page,
32 | recommend = recommend,
33 | notice = notice,
34 | headId = headId,
35 | session = session
36 | )
37 |
38 | constructor(
39 | gallId: String,
40 | searchKeyword: String,
41 | page: Int = 1,
42 | recommend: Boolean = false,
43 | notice: Boolean = false,
44 | headId: Int = 0,
45 | session: Session? = null
46 | ) : this(
47 | gallId = gallId,
48 | searchKeyword = searchKeyword,
49 | searchType = ArticleList.SearchType.ALL,
50 | page = page,
51 | recommend = recommend,
52 | notice = notice,
53 | headId = headId,
54 | session = session
55 | )
56 |
57 | private val articleList = ArticleList(
58 | gallId,
59 | searchKeyword,
60 | searchType,
61 | page,
62 | recommend,
63 | notice,
64 | headId,
65 | session
66 | )
67 |
68 | suspend fun requestAsync() = coroutineScope {
69 | async(Dispatchers.IO) {
70 | articleList.request()
71 | }
72 | }
73 |
74 | suspend fun getGallInfoAsync() = coroutineScope {
75 | async(Dispatchers.Default) {
76 | articleList.getGallInfo()
77 | }
78 | }
79 |
80 | suspend fun getGallListAsync() = coroutineScope {
81 | async(Dispatchers.Default) {
82 | articleList.getGallList()
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleModify.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.api.article.ArticleModify
4 | import be.zvz.kotlininside.api.type.Article
5 | import be.zvz.kotlininside.session.Session
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.async
8 | import kotlinx.coroutines.coroutineScope
9 |
10 | class AsyncArticleModify(
11 | gallId: String,
12 | articleId: Int,
13 | session: Session
14 | ) {
15 | private val articleModify = ArticleModify(gallId, articleId, session)
16 |
17 | suspend fun modifyInfoAsync() = coroutineScope {
18 | async(Dispatchers.IO) {
19 | articleModify.modifyInfo()
20 | }
21 | }
22 |
23 | suspend fun modifyAsync(article: Article, fcmToken: String = "N") = coroutineScope {
24 | async(Dispatchers.IO) {
25 | articleModify.modify(article, fcmToken)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleRead.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.api.article.ArticleRead
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncArticleRead @JvmOverloads constructor(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session? = null
13 | ) {
14 | private val articleRead = ArticleRead(gallId, articleId, session)
15 |
16 | suspend fun requestAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | articleRead.request()
19 | }
20 | }
21 |
22 | suspend fun getViewInfoAsync() = coroutineScope {
23 | async(Dispatchers.Default) {
24 | articleRead.getViewInfo()
25 | }
26 | }
27 |
28 | suspend fun getViewMainAsync() = coroutineScope {
29 | async(Dispatchers.Default) {
30 | articleRead.getViewMain()
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleReport.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.api.article.ArticleReport
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncArticleReport(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session
13 | ) {
14 | private val articleReport = ArticleReport(gallId, articleId, session)
15 |
16 | suspend fun getLinkAsync() = coroutineScope {
17 | async(Dispatchers.Default) {
18 | articleReport.getLink()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleVote.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.api.article.ArticleVote
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncArticleVote(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session
13 | ) {
14 | private val articleVote = ArticleVote(gallId, articleId, session)
15 |
16 | suspend fun upvoteAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | articleVote.upvote()
19 | }
20 | }
21 |
22 | suspend fun downvoteAsync() = coroutineScope {
23 | async(Dispatchers.IO) {
24 | articleVote.downvote()
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/article/AsyncArticleWrite.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.article
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.article.ArticleWrite
5 | import be.zvz.kotlininside.api.type.Article
6 | import be.zvz.kotlininside.session.Session
7 | import kotlinx.coroutines.Dispatchers
8 | import kotlinx.coroutines.async
9 | import kotlinx.coroutines.coroutineScope
10 |
11 | class AsyncArticleWrite @JvmOverloads constructor(
12 | gallId: String,
13 | article: Article,
14 | session: Session,
15 | fcmToken: String = KotlinInside.getInstance().auth.fcmToken
16 | ) {
17 | private val articleWrite = ArticleWrite(gallId, article, session, fcmToken)
18 |
19 | suspend fun writeAsync() = coroutineScope {
20 | async(Dispatchers.IO) {
21 | articleWrite.write()
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/comment/AsyncCommentDelete.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.comment
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.comment.CommentDelete
5 | import be.zvz.kotlininside.session.Session
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.async
8 | import kotlinx.coroutines.coroutineScope
9 |
10 | class AsyncCommentDelete @JvmOverloads constructor(
11 | gallId: String,
12 | articleId: Int,
13 | commentId: Int,
14 | session: Session,
15 | fcmToken: String = KotlinInside.getInstance().auth.fcmToken
16 | ) {
17 | private val commentDelete = CommentDelete(gallId, articleId, commentId, session, fcmToken)
18 |
19 | suspend fun deleteAsync() = coroutineScope {
20 | async(Dispatchers.IO) {
21 | commentDelete.delete()
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/comment/AsyncCommentRead.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.comment
2 |
3 | import be.zvz.kotlininside.api.comment.CommentRead
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncCommentRead(
9 | gallId: String,
10 | articleId: Int,
11 | rePage: Int
12 | ) {
13 | private val commentRead = CommentRead(gallId, articleId, rePage)
14 |
15 | suspend fun getAsync() = coroutineScope {
16 | async(Dispatchers.IO) {
17 | commentRead.request()
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/comment/AsyncCommentWrite.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.comment
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.comment.CommentWrite
5 | import be.zvz.kotlininside.api.type.comment.Comment
6 | import be.zvz.kotlininside.session.Session
7 | import kotlinx.coroutines.Dispatchers
8 | import kotlinx.coroutines.async
9 | import kotlinx.coroutines.coroutineScope
10 |
11 | class AsyncCommentWrite @JvmOverloads constructor(
12 | gallId: String,
13 | articleId: Int,
14 | comment: Comment,
15 | session: Session,
16 | fcmToken: String = KotlinInside.getInstance().auth.fcmToken
17 | ) {
18 | private val commentWrite = CommentWrite(gallId, articleId, comment, session, fcmToken)
19 |
20 | suspend fun writeAsync() = coroutineScope {
21 | async(Dispatchers.IO) {
22 | commentWrite.write()
23 | }
24 | }
25 |
26 | suspend fun replyAsync(commentId: Int) = coroutineScope {
27 | async(Dispatchers.IO) {
28 | commentWrite.reply(commentId)
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/dccon/AsyncDCConBuy.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.dccon
2 |
3 | import be.zvz.kotlininside.api.dccon.DCConBuy
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import be.zvz.kotlininside.session.Session
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.async
8 | import kotlinx.coroutines.coroutineScope
9 |
10 | class AsyncDCConBuy(
11 | dcCon: DCCon,
12 | session: Session
13 | ) {
14 | private val dcConBuy = DCConBuy(dcCon, session)
15 |
16 | suspend fun buyAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | dcConBuy.buy()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/dccon/AsyncDCConDetail.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.dccon
2 |
3 | import be.zvz.kotlininside.api.dccon.DCConDetail
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncDCConDetail(
10 | dcCon: DCCon
11 | ) {
12 | private val dcConDetail = DCConDetail(dcCon)
13 |
14 | suspend fun getAsync() = coroutineScope {
15 | async(Dispatchers.IO) {
16 | dcConDetail.request()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/dccon/AsyncDCConList.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.dccon
2 |
3 | import be.zvz.kotlininside.api.dccon.DCConList
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncDCConList(
10 | session: Session
11 | ) {
12 | private val dcConList = DCConList(session)
13 |
14 | suspend fun requestAsync() = coroutineScope {
15 | async(Dispatchers.IO) {
16 | dcConList.request()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncGalleryRanking.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.GalleryRanking
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncGalleryRanking {
9 | private val galleryRanking = GalleryRanking()
10 |
11 | suspend fun getAsync() = coroutineScope {
12 | async(Dispatchers.IO) {
13 | galleryRanking.request()
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncGallerySearch.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.GallerySearch
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncGallerySearch(
9 | keyword: String
10 | ) {
11 | private val gallerySearch = GallerySearch(keyword)
12 |
13 | suspend fun searchAsync() = coroutineScope {
14 | async(Dispatchers.IO) {
15 | gallerySearch.search()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncMainPage.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.MainPage
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncMainPage {
9 | private val mainPage = MainPage()
10 |
11 | suspend fun requestAsync() = coroutineScope {
12 | async(Dispatchers.IO) {
13 | mainPage.request()
14 | }
15 | }
16 |
17 | suspend fun getHitAsync() = coroutineScope {
18 | async(Dispatchers.Default) {
19 | mainPage.getHit()
20 | }
21 | }
22 |
23 | suspend fun getBestAsync() = coroutineScope {
24 | async(Dispatchers.Default) {
25 | mainPage.getBest()
26 | }
27 | }
28 |
29 | suspend fun getIssueZoomAsync() = coroutineScope {
30 | async(Dispatchers.Default) {
31 | mainPage.getIssueZoom()
32 | }
33 | }
34 |
35 | suspend fun getNewGalleryAsync() = coroutineScope {
36 | async(Dispatchers.Default) {
37 | mainPage.getNewGallery()
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncMiniGalleryRanking.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.MiniGalleryRanking
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncMiniGalleryRanking {
9 | private val miniGalleryRanking = MiniGalleryRanking()
10 |
11 | suspend fun getAsync() = coroutineScope {
12 | async(Dispatchers.IO) {
13 | miniGalleryRanking.request()
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncMinorGalleryInfo.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.MinorGalleryInfo
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncMinorGalleryInfo(
9 | gallId: String
10 | ) {
11 | private val minorGalleryInfo = MinorGalleryInfo(gallId)
12 |
13 | suspend fun getAsync() = coroutineScope {
14 | async(Dispatchers.IO) {
15 | minorGalleryInfo.request()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncMinorGalleryRanking.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.MinorGalleryRanking
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncMinorGalleryRanking {
9 | private val minorGalleryRanking = MinorGalleryRanking()
10 |
11 | suspend fun getAsync() = coroutineScope {
12 | async(Dispatchers.IO) {
13 | minorGalleryRanking.request()
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/AsyncTotalSearch.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic
2 |
3 | import be.zvz.kotlininside.api.generic.TotalSearch
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.coroutineScope
7 |
8 | class AsyncTotalSearch(
9 | keyword: String
10 | ) {
11 | private val totalSearch = TotalSearch(keyword)
12 |
13 | suspend fun searchAsync() = coroutineScope {
14 | async(Dispatchers.IO) {
15 | totalSearch.search()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/minigallery/AsyncJoinMiniGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic.minigallery
2 |
3 | import be.zvz.kotlininside.api.generic.minigallery.JoinMiniGallery
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncJoinMiniGallery(
10 | gallId: String,
11 | session: Session
12 | ) {
13 | private val joinMiniGallery = JoinMiniGallery(gallId, session)
14 |
15 | suspend fun joinAsync() = coroutineScope {
16 | async(Dispatchers.IO) {
17 | joinMiniGallery.join()
18 | }
19 | }
20 |
21 | suspend fun requestMemberJoinAsync() = coroutineScope {
22 | async(Dispatchers.IO) {
23 | joinMiniGallery.requestMemberJoin()
24 | }
25 | }
26 |
27 | suspend fun requestMemberJoinOkAsync() = coroutineScope {
28 | async(Dispatchers.IO) {
29 | joinMiniGallery.requestMemberJoinOk()
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/minigallery/AsyncQuitMiniGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic.minigallery
2 |
3 | import be.zvz.kotlininside.api.generic.minigallery.QuitMiniGallery
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncQuitMiniGallery(
10 | gallId: String,
11 | session: Session
12 | ) {
13 | private val quitMiniGallery = QuitMiniGallery(gallId, session)
14 |
15 | suspend fun quitAsync() = coroutineScope {
16 | async(Dispatchers.IO) {
17 | quitMiniGallery.quit()
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/userinfo/AsyncCheckJoinedMiniGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic.userinfo
2 |
3 | import be.zvz.kotlininside.api.generic.userinfo.CheckJoinedMiniGallery
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncCheckJoinedMiniGallery(
10 | session: Session
11 | ) {
12 | private val checkJoinMiniGallery = CheckJoinedMiniGallery(session)
13 |
14 | suspend fun requestAsync() = coroutineScope {
15 | async(Dispatchers.IO) {
16 | checkJoinMiniGallery.request()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/userinfo/AsyncCheckManagedGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic.userinfo
2 |
3 | import be.zvz.kotlininside.api.generic.userinfo.CheckManagedGallery
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncCheckManagedGallery(
10 | session: Session
11 | ) {
12 | private val checkManagedGallery = CheckManagedGallery(session)
13 |
14 | suspend fun requestAsync() = coroutineScope {
15 | async(Dispatchers.IO) {
16 | checkManagedGallery.request()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/userinfo/AsyncModifyMyGall.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic.userinfo
2 |
3 | import be.zvz.kotlininside.api.generic.userinfo.ModifyMyGall
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncModifyMyGall(
10 | gallName: String,
11 | gallId: String,
12 | session: Session
13 | ) {
14 | private val modifyMyGall = ModifyMyGall(gallName, gallId, session)
15 |
16 | suspend fun requestAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | modifyMyGall.request()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/generic/userinfo/AsyncMyGall.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.generic.userinfo
2 |
3 | import be.zvz.kotlininside.api.generic.userinfo.MyGall
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncMyGall(
10 | session: Session
11 | ) {
12 | private val myGall = MyGall(session)
13 |
14 | suspend fun requestAsync() = coroutineScope {
15 | async(Dispatchers.IO) {
16 | myGall.request()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/management/AsyncChangeHeadText.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.management
2 |
3 | import be.zvz.kotlininside.api.management.ChangeHeadText
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncChangeHeadText(
10 | gallId: String,
11 | articleId: Int,
12 | headTextId: Int,
13 | session: Session
14 | ) {
15 | private val changeHeadText = ChangeHeadText(gallId, articleId, headTextId, session)
16 |
17 | suspend fun requestAsync() = coroutineScope {
18 | async(Dispatchers.IO) {
19 | changeHeadText.request()
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/management/AsyncGallerySetting.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.management
2 |
3 | import be.zvz.kotlininside.api.management.GallerySetting
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncGallerySetting(
10 | gallId: String,
11 | session: Session
12 | ) {
13 | private val gallerySetting = GallerySetting(gallId, session)
14 |
15 | suspend fun getLinkAsync() = coroutineScope {
16 | async(Dispatchers.IO) {
17 | gallerySetting.getLink()
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/management/AsyncNoMemberBlock.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.management
2 |
3 | import be.zvz.kotlininside.api.management.NoMemberBlock
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncNoMemberBlock(
10 | session: Session,
11 | gallId: String,
12 | option: NoMemberBlock.BlockOption = NoMemberBlock.BlockOption()
13 | ) {
14 | private val noMemberBlock = NoMemberBlock(
15 | session,
16 | gallId,
17 | option
18 | )
19 |
20 | suspend fun blockAsync() = coroutineScope {
21 | async(Dispatchers.IO) {
22 | noMemberBlock.block()
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/management/AsyncNotice.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.management
2 |
3 | import be.zvz.kotlininside.api.management.Notice
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncNotice(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session
13 | ) {
14 | private val notice = Notice(gallId, articleId, session)
15 |
16 | suspend fun requestAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | notice.request()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/management/AsyncRecommend.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.management
2 |
3 | import be.zvz.kotlininside.api.management.Recommend
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncRecommend(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session
13 | ) {
14 | private val recommend = Recommend(gallId, articleId, session)
15 |
16 | suspend fun requestAsync() = coroutineScope {
17 | async(Dispatchers.IO) {
18 | recommend.request()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/async/management/AsyncUserBlock.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.async.management
2 |
3 | import be.zvz.kotlininside.api.management.UserBlock
4 | import be.zvz.kotlininside.session.Session
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.async
7 | import kotlinx.coroutines.coroutineScope
8 |
9 | class AsyncUserBlock @JvmOverloads constructor(
10 | gallId: String,
11 | articleId: Int,
12 | session: Session,
13 | option: UserBlock.BlockOption = UserBlock.BlockOption()
14 | ) {
15 | private val userBlock = UserBlock(gallId, articleId, session, option)
16 |
17 | suspend fun blockAsync() = coroutineScope {
18 | async(Dispatchers.IO) {
19 | userBlock.block()
20 | }
21 | }
22 |
23 | suspend fun getLinkAsync() = coroutineScope {
24 | async(Dispatchers.IO) {
25 | userBlock.getLink()
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/comment/CommentDelete.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.comment
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 |
11 | class CommentDelete @JvmOverloads constructor(
12 | private val gallId: String,
13 | private val articleId: Int,
14 | private val commentId: Int,
15 | private val session: Session,
16 | private val fcmToken: String = KotlinInside.getInstance().auth.fcmToken
17 | ) {
18 | data class DeleteResult(
19 | val result: Boolean,
20 | val cause: String? = null
21 | )
22 |
23 | /**
24 | * 댓글을 삭제합니다.
25 | * @exception [be.zvz.kotlininside.http.HttpException] 댓글을 삭제하지 못할 경우, HttpException 발생
26 | */
27 | @Throws(HttpException::class)
28 | fun delete(): DeleteResult {
29 | val option = Request.getDefaultOption()
30 | .addMultipartParameter("id", gallId)
31 | .addMultipartParameter("no", articleId.toString())
32 | .addMultipartParameter("comment_no", commentId.toString())
33 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
34 | .addMultipartParameter("client_token", fcmToken)
35 | .addMultipartParameter("mode", "comment_del")
36 |
37 | if (session.user is Anonymous) {
38 | option
39 | .addMultipartParameter("comment_pw", session.user.password)
40 | .addMultipartParameter("board_id", "")
41 | } else {
42 | option
43 | .addMultipartParameter("user_id", session.detail!!.userId)
44 | .addMultipartParameter("board_id", session.user.id)
45 | }
46 |
47 | val json =
48 | JsonBrowser.parse(KotlinInside.getInstance().httpInterface.upload(ApiUrl.Comment.DELETE, option)).index(0)
49 |
50 | return DeleteResult(
51 | result = json.get("result").asBoolean(),
52 | cause = json.get("cause").text()
53 | )
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/comment/CommentRead.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.comment
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import be.zvz.kotlininside.api.type.comment.Comment
6 | import be.zvz.kotlininside.api.type.comment.DCConComment
7 | import be.zvz.kotlininside.api.type.comment.StringComment
8 | import be.zvz.kotlininside.http.HttpException
9 | import be.zvz.kotlininside.http.Request
10 | import be.zvz.kotlininside.json.JsonBrowser
11 | import be.zvz.kotlininside.value.ApiUrl
12 |
13 | class CommentRead(
14 | private val gallId: String,
15 | private val articleId: Int,
16 | private val rePage: Int
17 | ) {
18 | data class ReadResult(
19 | val totalComment: Int,
20 | val totalPage: Int,
21 | val rePage: Int,
22 | val commentList: List
23 | )
24 |
25 | data class CommentData(
26 | val memberIcon: Int,
27 | val ipData: String?,
28 | val gallerCon: String?,
29 | val name: String,
30 | val userId: String,
31 | val content: Comment,
32 | val identifier: Int,
33 | val dateTime: String,
34 | val isReply: Boolean,
35 | val isDeleteFlag: String?
36 | )
37 |
38 | /**
39 | * 댓글 데이터를 읽어옵니다.
40 | * @exception [be.zvz.kotlininside.http.HttpException] 댓글을 읽어오지 못할 경우, HttpException 발생
41 | */
42 | @Throws(HttpException::class)
43 | fun request(): ReadResult {
44 | val url =
45 | "${ApiUrl.Comment.READ}?id=$gallId&no=$articleId&re_page=$rePage&app_id=${KotlinInside.getInstance().auth.getAppId()}"
46 |
47 | val json = JsonBrowser.parse(
48 | KotlinInside.getInstance().httpInterface.get(
49 | Request.redirectUrl(url),
50 | Request.getDefaultOption()
51 | )
52 | )
53 | .index(0)
54 |
55 | return ReadResult(
56 | totalComment = json.get("total_comment").asInteger(),
57 | totalPage = json.get("total_page").asInteger(),
58 | rePage = json.get("re_page").asInteger(),
59 | commentList = mutableListOf().apply {
60 | json.get("comment_list").values().forEach {
61 | add(
62 | CommentData(
63 | memberIcon = it.get("member_icon").asInteger(),
64 | ipData = it.get("ipData").text(),
65 | gallerCon = it.get("gallercon").text(),
66 | name = it.get("name").safeText(),
67 | userId = it.get("user_id").safeText(),
68 | content = it.get("dccon").run {
69 | when {
70 | isNull -> {
71 | StringComment(
72 | memo = it.get("comment_memo").safeText()
73 | )
74 | }
75 | else -> {
76 | DCConComment(
77 | dcCon = DCCon(
78 | imgLink = safeText(),
79 | memo = it.get("comment_memo").safeText(),
80 | detailIndex = it.get("dccon_detail_idx").asInteger()
81 | )
82 | )
83 | }
84 | }
85 | },
86 | identifier = it.get("comment_no").asInteger(),
87 | dateTime = it.get("date_time").safeText(),
88 | isReply = it.get("under_step").asBoolean(),
89 | isDeleteFlag = it.get("is_delete_flag").text()
90 | )
91 | )
92 | }
93 | }
94 | )
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/dccon/DCConBuy.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.dccon
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import be.zvz.kotlininside.http.HttpException
6 | import be.zvz.kotlininside.http.Request
7 | import be.zvz.kotlininside.json.JsonBrowser
8 | import be.zvz.kotlininside.session.Session
9 | import be.zvz.kotlininside.session.user.Anonymous
10 | import be.zvz.kotlininside.value.ApiUrl
11 |
12 | class DCConBuy(
13 | private val dcCon: DCCon,
14 | private val session: Session
15 | ) {
16 | data class BuyResult(
17 | val result: Int,
18 | val msg: String
19 | )
20 |
21 | /**
22 | * 디시콘을 구매합니다.
23 | * @return [BuyResult] 구매 결과를 반환합니다.
24 | */
25 | fun buy(): BuyResult {
26 | if (session.user is Anonymous) {
27 | throw HttpException(
28 | RuntimeException("Anonymous 세션은 DCConBuy를 이용할 수 없습니다.")
29 | )
30 | }
31 |
32 | val option = Request.getDefaultOption()
33 | .addMultipartParameter("user_id", session.detail!!.userId)
34 | .addMultipartParameter("package_idx", dcCon.packageIndex.toString())
35 | .addMultipartParameter("type", "buy_dccon")
36 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
37 |
38 | val json = JsonBrowser.parse(
39 | KotlinInside.getInstance().httpInterface.upload(
40 | ApiUrl.DCCon.DCCON,
41 | option
42 | )
43 | )
44 |
45 | return BuyResult(
46 | result = json.get("result").asInteger(),
47 | msg = json.get("msg").safeText()
48 | )
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/dccon/DCConDetail.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.dccon
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.utils.StringUtil
8 | import be.zvz.kotlininside.value.ApiUrl
9 |
10 | class DCConDetail(
11 | private val dcCon: DCCon
12 | ) {
13 | data class DetailResult(
14 | val info: List = listOf(),
15 | val detail: List = listOf()
16 | )
17 |
18 | data class DCConInfo(
19 | val packageIndex: Int,
20 | val mainImg: String,
21 | val title: String,
22 | val description: String,
23 | val mandu: Int,
24 | val getState: Boolean
25 | )
26 |
27 | /**
28 | * 디시콘 정보를 받아오는 메소드입니다.
29 | * @return [DetailResult] 디시콘 정보를 반환합니다.
30 | */
31 | fun request(): DetailResult {
32 | val option = Request.getDefaultOption()
33 | .addMultipartParameter("package_idx", dcCon.packageIndex.toString())
34 | .addMultipartParameter("type", "package_detail")
35 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
36 |
37 | val json = JsonBrowser.parse(
38 | KotlinInside.getInstance().httpInterface.upload(
39 | ApiUrl.DCCon.DCCON,
40 | option
41 | )
42 | )
43 |
44 | return when {
45 | json.isList -> {
46 | DetailResult()
47 | }
48 | else -> DetailResult(
49 | info = mutableListOf().apply {
50 | json.get("info").values().forEach {
51 | add(
52 | DCConInfo(
53 | packageIndex = it.get("package_idx").asInteger(),
54 | mainImg = it.get("main_img").safeText(),
55 | title = it.get("title").safeText(),
56 | description = it.get("description").safeText(),
57 | mandu = it.get("mandu").asInteger(),
58 | getState = StringUtil.ynToBoolean(it.get("get_state").safeText())
59 | )
60 | )
61 | }
62 | },
63 | detail = mutableListOf().apply {
64 | json.get("detail").values().forEach {
65 | add(
66 | DCCon(
67 | imgLink = it.get("img").safeText()
68 | )
69 | )
70 | }
71 | }
72 | )
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/dccon/DCConInsert.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.dccon
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.utils.StringUtil
10 | import be.zvz.kotlininside.value.ApiUrl
11 |
12 | class DCConInsert(
13 | val dcCon: DCCon,
14 | val session: Session
15 | ) {
16 | data class InsertResult(
17 | val result: Boolean,
18 | val newList: String?,
19 | val imageSource: String?,
20 | val alternativeText: String?,
21 | val imageTag: String?
22 | )
23 |
24 | fun request(): InsertResult {
25 | val json = JsonBrowser.parse(
26 | KotlinInside.getInstance().httpInterface.upload(
27 | ApiUrl.DCCon.DCCON,
28 | Request.getDefaultOption().apply {
29 | if (session.user !is Anonymous) {
30 | addMultipartParameter("user_id", session.detail!!.userId)
31 | }
32 | }
33 | .addMultipartParameter("package_idx", dcCon.packageIndex.toString())
34 | .addMultipartParameter("detail_idx", dcCon.detailIndex.toString())
35 | .addMultipartParameter("type", "insert")
36 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
37 | )
38 | )
39 | return InsertResult(
40 | result = StringUtil.okToBoolean(json.get("result").safeText()),
41 | newList = json.get("new_list").text(),
42 | imageSource = json.get("img_src").text(),
43 | alternativeText = json.get("alt").text(),
44 | imageTag = json.get("img_tag").text()
45 | )
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/dccon/DCConList.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.dccon
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.DCCon
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.LoginUser
9 | import be.zvz.kotlininside.value.ApiUrl
10 |
11 | class DCConList(
12 | private val session: Session
13 | ) {
14 | data class ListResult(
15 | val tab: List,
16 | val list: List>
17 | )
18 |
19 | fun request(): ListResult {
20 | val option = Request.getDefaultOption()
21 | .addMultipartParameter("type", "list")
22 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
23 |
24 | if (session.user is LoginUser) {
25 | option.addMultipartParameter("user_id", session.detail!!.userId)
26 | }
27 |
28 | val json = JsonBrowser.parse(
29 | KotlinInside.getInstance().httpInterface.upload(
30 | ApiUrl.DCCon.DCCON,
31 | option
32 | )
33 | )
34 |
35 | return ListResult(
36 | tab = mutableListOf().apply {
37 | json.get("tab").values().forEach {
38 | add(
39 | DCCon(
40 | packageIndex = it.get("package_idx").asInteger(),
41 | title = it.get("title").safeText(),
42 | imgLink = it.get("img").safeText()
43 | )
44 | )
45 | }
46 | },
47 | list = mutableListOf>().apply {
48 | json.get("list").values().forEach { list ->
49 | add(
50 | mutableListOf().apply {
51 | list.values().forEach {
52 | add(
53 | DCCon(
54 | detailIndex = it.get("detail_idx").asInteger(),
55 | packageIndex = it.get("package_idx").asInteger(),
56 | title = it.get("title").safeText(),
57 | imgLink = it.get("img").safeText()
58 | )
59 | )
60 | }
61 | }
62 | )
63 | }
64 | }
65 | )
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/GalleryRanking.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.value.ApiUrl
8 |
9 | class GalleryRanking {
10 | enum class RankType {
11 | UP,
12 | DOWN,
13 | STOP,
14 | UNKNOWN
15 | }
16 |
17 | data class RankingItem(
18 | val gallLink: String,
19 | val gallId: String,
20 | val gallName: String,
21 | val rankType: RankType,
22 | val rank: Int,
23 | val rankUpdown: Int
24 | )
25 |
26 | /**
27 | * 정식 갤러리 랭킹을 불러옵니다.
28 | * @return 정식 갤러리 랭킹을 반환합니다.
29 | * @exception [be.zvz.kotlininside.http.HttpException] 데이터를 불러오지 못할 경우, HttpException 발생
30 | */
31 | @Throws(HttpException::class)
32 | fun request(): List {
33 | return mutableListOf().apply {
34 | val json = JsonBrowser.parse(
35 | KotlinInside.getInstance().httpInterface.get(
36 | ApiUrl.MainInfo.GALLERY_RANKING,
37 | Request.getDefaultOption()
38 | )
39 | )
40 | json.values().forEach {
41 | add(
42 | RankingItem(
43 | gallLink = it.get("link").text()!!,
44 | gallId = it.get("id").text()!!,
45 | gallName = it.get("category").text()!!,
46 | rankType = it.get("rank_type").text()!!.let { rankTypeString ->
47 | return@let when (rankTypeString) {
48 | "up" -> RankType.UP
49 | "stop" -> RankType.STOP
50 | "down" -> RankType.DOWN
51 | else -> RankType.UNKNOWN
52 | }
53 | },
54 | rank = it.get("num").asInteger(),
55 | rankUpdown = it.get("rank").asInteger()
56 | )
57 | )
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/GallerySearch.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.Gallery
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.value.ApiUrl
8 |
9 | class GallerySearch(
10 | private val keyword: String
11 | ) {
12 | data class GallerySearchResult(
13 | val mainGallery: List,
14 | val minorGallery: List,
15 | val mainRecommendGallery: List,
16 | val minorRecommendGallery: List
17 | )
18 |
19 | /**
20 | * 갤러리 목록을 검색하고, 검색 결과를 받아옵니다.
21 | *
22 | * @return 갤러리 목록 검색 결과를 반환합니다.
23 | */
24 | fun search(): GallerySearchResult {
25 | val option = Request.getDefaultOption()
26 | .addMultipartParameter("keyword", keyword)
27 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
28 |
29 | val json = JsonBrowser.parse(
30 | KotlinInside.getInstance().httpInterface.upload(
31 | ApiUrl.Search.SEARCH,
32 | option
33 | )
34 | )
35 |
36 | return GallerySearchResult(
37 | mainGallery = mutableListOf().apply {
38 | json.get("main_gall").values().forEach {
39 | add(
40 | Gallery(
41 | title = it.get("title").safeText(),
42 | id = it.get("id").safeText()
43 | )
44 | )
45 | }
46 | },
47 | minorGallery = mutableListOf().apply {
48 | json.get("minor_gall").values().forEach {
49 | add(
50 | Gallery(
51 | title = it.get("title").safeText(),
52 | id = it.get("id").safeText()
53 | )
54 | )
55 | }
56 | },
57 | mainRecommendGallery = mutableListOf().apply {
58 | json.get("main_recomm_gall").values().forEach {
59 | add(
60 | Gallery(
61 | title = it.get("title").safeText(),
62 | id = it.get("id").safeText()
63 | )
64 | )
65 | }
66 | },
67 | minorRecommendGallery = mutableListOf().apply {
68 | json.get("minor_recomm_gall").values().forEach {
69 | add(
70 | Gallery(
71 | title = it.get("title").safeText(),
72 | id = it.get("id").safeText()
73 | )
74 | )
75 | }
76 | }
77 | )
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/MainPage.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.value.ApiUrl
8 |
9 | class MainPage {
10 | private lateinit var json: JsonBrowser
11 |
12 | data class Article(
13 | val gallId: String,
14 | val articleId: Int,
15 | val gallName: String? = null,
16 | val title: String,
17 | val thumbnail: String
18 | )
19 |
20 | data class NewGallery(
21 | val id: String,
22 | val title: String
23 | )
24 |
25 | /**
26 | * 클래스의 메소드들을 사용하기 전, 이 메소드를 호출해주세요. (권장)
27 | * @exception [be.zvz.kotlininside.http.HttpException] 글 목록을 불러오지 못할 경우, HttpException 발생
28 | */
29 | @Throws(HttpException::class)
30 | fun request() {
31 | json = JsonBrowser.parse(
32 | KotlinInside.getInstance().httpInterface.get(
33 | ApiUrl.MainInfo.APP_MAIN,
34 | Request.getDefaultOption()
35 | )
36 | )
37 | .index(0)
38 | }
39 |
40 | /**
41 | * 메인 화면에 표시되어 있는 Hit갤 게시물 목록을 가져옵니다.
42 | * @exception [be.zvz.kotlininside.http.HttpException] 글 목록을 불러오지 못할 경우, HttpException 발생
43 | */
44 | @Throws(HttpException::class)
45 | fun getHit(): List {
46 | if (!::json.isInitialized) {
47 | request()
48 | }
49 |
50 | return mutableListOf().apply {
51 | json.get("hit").values().forEach {
52 | add(
53 | Article(
54 | gallId = it.get("id").safeText(),
55 | articleId = it.get("no").`as`(Int::class.java),
56 | title = it.get("title").safeText(),
57 | thumbnail = it.get("thumbnail").safeText()
58 | )
59 | )
60 | }
61 | }
62 | }
63 |
64 | /**
65 | * 메인 화면에 표시되어 있는 베스트 게시물 목록을 가져옵니다.
66 | * @exception [be.zvz.kotlininside.http.HttpException] 글 목록을 불러오지 못할 경우, HttpException 발생
67 | */
68 | @Throws(HttpException::class)
69 | fun getBest(): List {
70 | if (!::json.isInitialized) {
71 | request()
72 | }
73 |
74 | return mutableListOf().apply {
75 | json.get("best").values().forEach {
76 | add(
77 | Article(
78 | gallId = it.get("id").safeText(),
79 | articleId = it.get("no").asInteger(),
80 | gallName = it.get("gall_name").text(),
81 | title = it.get("title").safeText(),
82 | thumbnail = it.get("thumbnail").safeText()
83 | )
84 | )
85 | }
86 | }
87 | }
88 |
89 | /**
90 | * 메인 화면에 표시되어 있는 이슈줌갤 게시물 목록을 가져옵니다.
91 | * @exception [be.zvz.kotlininside.http.HttpException] 글 목록을 불러오지 못할 경우, HttpException 발생
92 | */
93 | @Throws(HttpException::class)
94 | fun getIssueZoom(): List {
95 | if (!::json.isInitialized) {
96 | request()
97 | }
98 |
99 | return mutableListOf().apply {
100 | json.get("issuezoom").values().forEach {
101 | add(
102 | Article(
103 | gallId = it.get("id").safeText(),
104 | articleId = it.get("no").asInteger(),
105 | gallName = it.get("gall_name").text(),
106 | title = it.get("title").safeText(),
107 | thumbnail = it.get("thumbnail").safeText()
108 | )
109 | )
110 | }
111 | }
112 | }
113 |
114 | /**
115 | * 메인 화면에 표시되어 있는 신규 갤러리 목록을 가져옵니다.
116 | * @exception [be.zvz.kotlininside.http.HttpException] 신규 갤러리 목록을 불러오지 못할 경우, HttpException 발생
117 | */
118 | @Throws(HttpException::class)
119 | fun getNewGallery(): List {
120 | if (!::json.isInitialized) {
121 | request()
122 | }
123 |
124 | return mutableListOf().apply {
125 | json.get("new_gallery").values().forEach {
126 | add(
127 | NewGallery(
128 | id = it.get("id").safeText(),
129 | title = it.get("title").safeText()
130 | )
131 | )
132 | }
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/MiniGalleryRanking.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.value.ApiUrl
8 |
9 | class MiniGalleryRanking {
10 | enum class RankType {
11 | UP,
12 | DOWN,
13 | STOP,
14 | UNKNOWN
15 | }
16 |
17 | data class RankingItem(
18 | val gallLink: String,
19 | val gallId: String,
20 | val gallName: String,
21 | val rankType: RankType,
22 | val rank: Int,
23 | val rankUpdown: Int
24 | )
25 |
26 | /**
27 | * 미니 갤러리 랭킹을 불러옵니다.
28 | * @return 미니 갤러리 랭킹을 반환합니다.
29 | * @exception [be.zvz.kotlininside.http.HttpException] 데이터를 불러오지 못할 경우, HttpException 발생
30 | */
31 | @Throws(HttpException::class)
32 | fun request(): List {
33 | return mutableListOf().apply {
34 | val json = JsonBrowser.parse(
35 | KotlinInside.getInstance().httpInterface.get(
36 | ApiUrl.MainInfo.MINI_GALLERY_RANKING,
37 | Request.getDefaultOption()
38 | )
39 | )
40 | json.values().forEach {
41 | add(
42 | RankingItem(
43 | gallLink = it.get("link").text()!!,
44 | gallId = it.get("id").text()!!,
45 | gallName = it.get("ko_name").text()!!,
46 | rankType = it.get("rank_type").text()!!.let { rankTypeString ->
47 | return@let when (rankTypeString) {
48 | "up" -> RankType.UP
49 | "stop" -> RankType.STOP
50 | "down" -> RankType.DOWN
51 | else -> RankType.UNKNOWN
52 | }
53 | },
54 | rank = it.get("rank").asInteger(),
55 | rankUpdown = it.get("rank_updown").asInteger()
56 | )
57 | )
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/MinorGalleryInfo.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.json.JsonBrowser
6 | import be.zvz.kotlininside.value.ApiUrl
7 |
8 | class MinorGalleryInfo(
9 | private val gallId: String
10 | ) {
11 | data class MiniGalleryInfo(
12 | val hide: Int,
13 | val totalMember: Int,
14 | val memberLimit: Int,
15 | val isMember: Boolean
16 | )
17 |
18 | data class InfoResult(
19 | val id: String,
20 | val koName: String,
21 | val image: String? = null,
22 | val description: String? = null,
23 | val manager: Manager,
24 | val subManager: List,
25 | val createDate: String,
26 | val new: Boolean,
27 | val hotState: String,
28 | val totalCount: String,
29 | val categoryName: String,
30 | val mini: MiniGalleryInfo? = null
31 | )
32 |
33 | data class Manager(
34 | val isMaster: Boolean,
35 | val id: String,
36 | val name: String
37 | )
38 |
39 | /**
40 | * 갤러리 정보를 받아옵니다.
41 | *
42 | * @return 갤러리 정보를 반환합니다.
43 | */
44 | fun request(): InfoResult {
45 | val option = Request.getDefaultOption()
46 | .addMultipartParameter("id", gallId)
47 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
48 |
49 | val json = JsonBrowser.parse(
50 | KotlinInside.getInstance().httpInterface.upload(
51 | ApiUrl.Gallery.MINOR_INFO,
52 | option
53 | )
54 | ).index(0)
55 |
56 | val miniGalleryInfo = json.get("mini")
57 | return InfoResult(
58 | id = json.get("id").safeText(),
59 | koName = json.get("ko_name").safeText(),
60 | image = json.get("img").text(),
61 | description = json.get("mgallery_desc").text(),
62 | manager = Manager(
63 | isMaster = true,
64 | id = json.get("master_id").safeText(),
65 | name = json.get("master_name").safeText()
66 | ),
67 | subManager = mutableListOf().apply {
68 | json.get("submanager").values().forEach {
69 | add(
70 | Manager(
71 | isMaster = false,
72 | id = it.get("id").safeText(),
73 | name = it.get("name").safeText()
74 | )
75 | )
76 | }
77 | },
78 | createDate = json.get("create_dt").safeText(),
79 | new = json.get("new").asBoolean(),
80 | hotState = json.get("hot_state").safeText(),
81 | totalCount = json.get("total_count").safeText(),
82 | categoryName = json.get("cate_name").safeText(),
83 | mini = if (!miniGalleryInfo.isNull) {
84 | MiniGalleryInfo(
85 | hide = miniGalleryInfo.get("gall_hide").asInteger(),
86 | totalMember = miniGalleryInfo.get("total_member").asInteger(),
87 | memberLimit = miniGalleryInfo.get("member_limit").asInteger(),
88 | isMember = miniGalleryInfo.get("member_ok").asBoolean()
89 | )
90 | } else {
91 | null
92 | }
93 | )
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/MinorGalleryRanking.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.HttpException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.value.ApiUrl
8 |
9 | class MinorGalleryRanking {
10 | enum class RankType {
11 | UP,
12 | DOWN,
13 | STOP,
14 | UNKNOWN
15 | }
16 |
17 | data class RankingItem(
18 | val gallLink: String,
19 | val gallId: String,
20 | val gallName: String,
21 | val rankType: RankType,
22 | val rank: Int,
23 | val rankUpdown: Int
24 | )
25 |
26 | /**
27 | * 마이너 갤러리 랭킹을 불러옵니다.
28 | * @return 마이너 갤러리 랭킹을 반환합니다.
29 | * @exception [be.zvz.kotlininside.http.HttpException] 데이터를 불러오지 못할 경우, HttpException 발생
30 | */
31 | @Throws(HttpException::class)
32 | fun request(): List {
33 | return mutableListOf().apply {
34 | val json = JsonBrowser.parse(
35 | KotlinInside.getInstance().httpInterface.get(
36 | ApiUrl.MainInfo.MINOR_GALLERY_RANKING,
37 | Request.getDefaultOption()
38 | )
39 | )
40 | json.values().forEach {
41 | add(
42 | RankingItem(
43 | gallLink = it.get("link").text()!!,
44 | gallId = it.get("id").text()!!,
45 | gallName = it.get("ko_name").text()!!,
46 | rankType = it.get("rank_type").text()!!.let { rankTypeString ->
47 | return@let when (rankTypeString) {
48 | "up" -> RankType.UP
49 | "stop" -> RankType.STOP
50 | "down" -> RankType.DOWN
51 | else -> RankType.UNKNOWN
52 | }
53 | },
54 | rank = it.get("rank").asInteger(),
55 | rankUpdown = it.get("rank_updown").asInteger()
56 | )
57 | )
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/MovieUpload.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.content.MovieContent
5 | import be.zvz.kotlininside.http.HttpInterface
6 | import be.zvz.kotlininside.http.Request
7 | import be.zvz.kotlininside.json.JsonBrowser
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 | import java.io.IOException
11 |
12 | /**
13 | * [be.zvz.kotlininside.api.type.content.MovieContent] 업로드를 위한 API 클래스
14 | */
15 | class MovieUpload @JvmOverloads constructor(
16 | val gallId: String,
17 | val content: MovieContent,
18 | val checkRestriction: Boolean = true
19 | ) {
20 | class UploadException(
21 | val checkResult: CheckResult
22 | ) : IOException(checkResult.cause)
23 |
24 | data class UploadResult(
25 | val msg: String?,
26 | val fileId: Int?,
27 | val thumbnailUrls: List?,
28 | val width: Int?,
29 | val height: Int?
30 | )
31 |
32 | data class CheckResult(
33 | val result: Boolean,
34 | val cause: String? = null
35 | )
36 |
37 | @Throws(UploadException::class)
38 | fun upload(): UploadResult {
39 | if (checkRestriction && KotlinInside.getInstance().session.user is Anonymous) {
40 | val json = JsonBrowser.parse(
41 | KotlinInside.getInstance().httpInterface.get(
42 | ApiUrl.Upload.CHECK_UPLOAD_RESTRICTION +
43 | "?app_id=${KotlinInside.getInstance().auth.getAppId()}" +
44 | "&id=$gallId" +
45 | "&mode=movie",
46 | Request.getDefaultOption()
47 | )
48 | )
49 | val checkResult = CheckResult(
50 | result = json.get("result").asBoolean(),
51 | cause = json.get("cause").text()
52 | )
53 |
54 | if (!checkResult.result) {
55 | throw UploadException(checkResult)
56 | }
57 | }
58 |
59 | val result = JsonBrowser.parse(
60 | KotlinInside.getInstance().httpInterface.upload(
61 | ApiUrl.Upload.MOVIE,
62 | Request.getDefaultOption().apply {
63 | addMultipartParameter("id", gallId)
64 | addMultipartFile(
65 | "avatar",
66 | HttpInterface.Option.FileInfo(
67 | content.stream,
68 | content.mimeType
69 | )
70 | )
71 | }
72 | )
73 | )
74 | return UploadResult(
75 | msg = result.get("msg").text(),
76 | fileId = result.get("file_no").asNullableInteger()?.apply {
77 | content.uploaded = true
78 | content.fileId = this
79 | },
80 | thumbnailUrls = result.get("thum_url_arr").run {
81 | if (!isNull) {
82 | mutableListOf().apply {
83 | values().forEach {
84 | add(it.safeText())
85 | }
86 | }
87 | } else {
88 | null
89 | }
90 | },
91 | width = result.get("width").asNullableInteger()?.apply {
92 | content.info.width = this
93 | },
94 | height = result.get("height").asNullableInteger()?.apply {
95 | content.info.height = this
96 | }
97 | )
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/minigallery/JoinMiniGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic.minigallery
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.json.JsonBrowser
6 | import be.zvz.kotlininside.session.Session
7 | import be.zvz.kotlininside.session.user.Anonymous
8 | import be.zvz.kotlininside.value.ApiUrl
9 |
10 | class JoinMiniGallery(
11 | private val gallId: String,
12 | private val session: Session
13 | ) {
14 | data class MemberJoinResult(
15 | val result: Boolean,
16 | val joinQuestion: String
17 | )
18 |
19 | data class MemberJoinOkResult(
20 | val result: Boolean,
21 | val cause: String,
22 | val status: String
23 | )
24 |
25 | fun join(): Pair {
26 | val memberJoinResult = requestMemberJoin()
27 | val memberJoinOkResult = requestMemberJoinOk()
28 |
29 | return Pair(memberJoinResult, memberJoinOkResult)
30 | }
31 |
32 | fun requestMemberJoin(): MemberJoinResult {
33 | if (session.user is Anonymous) {
34 | throw RuntimeException("Anonymous는 requestMemberJoin을 사용할 수 없습니다.")
35 | }
36 |
37 | val option = Request.getDefaultOption()
38 | .addMultipartParameter("user_id", session.detail!!.userId)
39 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
40 | .addMultipartParameter("id", gallId)
41 |
42 | val json = JsonBrowser.parse(
43 | KotlinInside.getInstance().httpInterface.upload(
44 | ApiUrl.MiniGallery.JOIN,
45 | option
46 | )
47 | ).index(0)
48 |
49 | return MemberJoinResult(
50 | result = json.get("result").asBoolean(),
51 | joinQuestion = json.get("join_question").safeText()
52 | )
53 | }
54 |
55 | fun requestMemberJoinOk(): MemberJoinOkResult {
56 | if (session.user is Anonymous) {
57 | throw RuntimeException("Anonymous는 requestMemberJoinOk을 사용할 수 없습니다.")
58 | }
59 |
60 | val option = Request.getDefaultOption()
61 | .addMultipartParameter("user_id", session.detail!!.userId)
62 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
63 | .addMultipartParameter("id", gallId)
64 |
65 | val json = JsonBrowser.parse(
66 | KotlinInside.getInstance().httpInterface.upload(
67 | ApiUrl.MiniGallery.JOIN_OK,
68 | option
69 | )
70 | ).index(0)
71 |
72 | return MemberJoinOkResult(
73 | result = json.get("result").asBoolean(),
74 | cause = json.get("cause").safeText(),
75 | status = json.get("status").safeText()
76 | )
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/minigallery/QuitMiniGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic.minigallery
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.json.JsonBrowser
6 | import be.zvz.kotlininside.session.Session
7 | import be.zvz.kotlininside.session.user.Anonymous
8 | import be.zvz.kotlininside.value.ApiUrl
9 |
10 | class QuitMiniGallery(
11 | private val gallId: String,
12 | private val session: Session
13 | ) {
14 | data class MemberQuitResult(
15 | val result: Boolean
16 | )
17 |
18 | fun quit(): MemberQuitResult {
19 | if (session.user is Anonymous) {
20 | throw RuntimeException("Anonymous는 QuitMiniGallery를 사용할 수 없습니다.")
21 | }
22 |
23 | val option = Request.getDefaultOption()
24 | .addMultipartParameter("user_id", session.detail!!.userId)
25 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
26 | .addMultipartParameter("id", gallId)
27 |
28 | val json = JsonBrowser.parse(
29 | KotlinInside.getInstance().httpInterface.upload(
30 | ApiUrl.MiniGallery.QUIT,
31 | option
32 | )
33 | ).index(0)
34 |
35 | return MemberQuitResult(
36 | result = json.get("result").asBoolean()
37 | )
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/userinfo/CheckJoinedMiniGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic.userinfo
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.json.JsonBrowser
6 | import be.zvz.kotlininside.session.Session
7 | import be.zvz.kotlininside.session.user.Anonymous
8 | import be.zvz.kotlininside.value.ApiUrl
9 |
10 | class CheckJoinedMiniGallery(
11 | private val session: Session
12 | ) {
13 | data class Gallery(
14 | val title: String,
15 | val id: String,
16 | val hide: Int
17 | )
18 |
19 | data class CheckResult(
20 | val myJoinMiniIn: List,
21 | val myJoinMiniHold: List,
22 | val myJoinMiniOut: List
23 | )
24 |
25 | /**
26 | * 내 갤러리 정보를 받아옵니다.
27 | *
28 | * @return 내 갤러리 정보를 반환합니다.
29 | */
30 | fun request(): CheckResult {
31 | if (session.user is Anonymous) {
32 | throw RuntimeException("Anonymous는 CheckJoinedMiniGallery을 사용할 수 없습니다.")
33 | }
34 |
35 | val option = Request.getDefaultOption()
36 | .addMultipartParameter("user_id", session.detail!!.userId)
37 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
38 |
39 | val json = JsonBrowser.parse(
40 | KotlinInside.getInstance().httpInterface.upload(
41 | ApiUrl.User.MY_MINI_JOIN_CHECK,
42 | option
43 | )
44 | ).index(0)
45 |
46 | return CheckResult(
47 | myJoinMiniIn = mutableListOf().apply {
48 | json.get("myjoinmini_in").values().forEach {
49 | add(
50 | Gallery(
51 | title = it.get("gall_koname").safeText(),
52 | id = it.get("gall_id").safeText(),
53 | hide = it.get("gall_hide").asInteger()
54 | )
55 | )
56 | }
57 | },
58 | myJoinMiniHold = mutableListOf().apply {
59 | json.get("myjoinmini_hold").values().forEach {
60 | add(
61 | Gallery(
62 | title = it.get("gall_koname").safeText(),
63 | id = it.get("gall_id").safeText(),
64 | hide = it.get("gall_hide").asInteger()
65 | )
66 | )
67 | }
68 | },
69 | myJoinMiniOut = mutableListOf().apply {
70 | json.get("myjoinmini_out").values().forEach {
71 | add(
72 | Gallery(
73 | title = it.get("gall_koname").safeText(),
74 | id = it.get("gall_id").safeText(),
75 | hide = it.get("gall_hide").asInteger()
76 | )
77 | )
78 | }
79 | }
80 | )
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/userinfo/CheckManagedGallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic.userinfo
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.json.JsonBrowser
6 | import be.zvz.kotlininside.session.Session
7 | import be.zvz.kotlininside.session.user.Anonymous
8 | import be.zvz.kotlininside.value.ApiUrl
9 |
10 | class CheckManagedGallery(
11 | private val session: Session
12 | ) {
13 | data class Gallery(
14 | val hide: Int,
15 | val id: String,
16 | val title: String,
17 | val type: String, // TODO: Enum class로 변경
18 | val managerType: String // TODO: Enum class로 변경
19 | )
20 |
21 | data class CheckResult(
22 | val myManageList: List
23 | )
24 |
25 | /**
26 | * 내 갤러리 정보를 받아옵니다.
27 | *
28 | * @return 내 갤러리 정보를 반환합니다.
29 | */
30 | fun request(): CheckResult {
31 | if (session.user is Anonymous) {
32 | throw RuntimeException("Anonymous는 CheckJoinedMiniGallery을 사용할 수 없습니다.")
33 | }
34 |
35 | val option = Request.getDefaultOption()
36 | .addMultipartParameter("user_id", session.detail!!.userId)
37 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
38 |
39 | val json = JsonBrowser.parse(
40 | KotlinInside.getInstance().httpInterface.upload(
41 | ApiUrl.User.MY_MANAGE_GALL_CHECK,
42 | option
43 | )
44 | ).index(0)
45 |
46 | return CheckResult(
47 | myManageList = mutableListOf().apply {
48 | json.get("mymanageList").values().forEach {
49 | add(
50 | Gallery(
51 | hide = it.get("gall_hide").asInteger(),
52 | id = it.get("gall_id").safeText(),
53 | title = it.get("gall_koname").safeText(),
54 | type = it.get("gall_type").safeText(),
55 | managerType = it.get("manager_type").safeText()
56 | )
57 | )
58 | }
59 | }
60 | )
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/userinfo/ModifyMyGall.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic.userinfo
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.http.Request
5 | import be.zvz.kotlininside.json.JsonBrowser
6 | import be.zvz.kotlininside.session.Session
7 | import be.zvz.kotlininside.session.user.Anonymous
8 | import be.zvz.kotlininside.value.ApiUrl
9 |
10 | class ModifyMyGall(
11 | private val gallName: String,
12 | private val gallId: String,
13 | private val session: Session
14 | ) {
15 | data class ModifyMyGallResult(
16 | val result: Boolean,
17 | val cause: String
18 | )
19 |
20 | fun request(): ModifyMyGallResult {
21 | if (session.user is Anonymous) {
22 | throw RuntimeException("Anonymous는 ModifyMyGall을 사용할 수 없습니다.")
23 | }
24 |
25 | val option = Request.getDefaultOption()
26 | .addMultipartParameter("user_id", session.detail!!.userId)
27 | .addMultipartParameter("gall_nm", gallName)
28 | .addMultipartParameter("gall_id", gallId)
29 | .addMultipartParameter("mode", "favori_gall")
30 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
31 |
32 | val json = JsonBrowser.parse(
33 | KotlinInside.getInstance().httpInterface.upload(
34 | ApiUrl.User.MY_GALL_MODIFY,
35 | option
36 | )
37 | ).index(0)
38 |
39 | return ModifyMyGallResult(
40 | result = json.get("result").asBoolean(),
41 | cause = json.get("cause").safeText()
42 | )
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/generic/userinfo/MyGall.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.generic.userinfo
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.api.type.Gallery
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 |
11 | class MyGall(
12 | private val session: Session
13 | ) {
14 | data class MyGallResult(
15 | val myGall: List,
16 | val favorite: List
17 | )
18 |
19 | /**
20 | * 내 갤러리 정보를 받아옵니다.
21 | *
22 | * @return 내 갤러리 정보를 반환합니다.
23 | */
24 | fun request(): MyGallResult {
25 | if (session.user is Anonymous) {
26 | throw RuntimeException("Anonymous는 MyGall을 사용할 수 없습니다.")
27 | }
28 |
29 | val option = Request.getDefaultOption()
30 | .addMultipartParameter("user_id", session.detail!!.userId)
31 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
32 |
33 | val json = JsonBrowser.parse(
34 | KotlinInside.getInstance().httpInterface.upload(
35 | ApiUrl.User.MY_GALL,
36 | option
37 | )
38 | ).index(0)
39 |
40 | return MyGallResult(
41 | myGall = mutableListOf().apply {
42 | json.get("mygall").values().forEach {
43 | add(
44 | Gallery(
45 | title = it.get("gall_koname").safeText(),
46 | id = it.get("gall_id").safeText()
47 | )
48 | )
49 | }
50 | },
51 | favorite = mutableListOf().apply {
52 | json.get("favori").values().forEach {
53 | add(
54 | Gallery(
55 | title = it.get("gall_koname").safeText(),
56 | id = it.get("gall_id").safeText()
57 | )
58 | )
59 | }
60 | }
61 | )
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/management/ChangeHeadText.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.management
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.exception.InsufficientPermissionException
5 | import be.zvz.kotlininside.http.HttpException
6 | import be.zvz.kotlininside.http.Request
7 | import be.zvz.kotlininside.json.JsonBrowser
8 | import be.zvz.kotlininside.session.Session
9 | import be.zvz.kotlininside.session.user.Anonymous
10 | import be.zvz.kotlininside.value.ApiUrl
11 | import java.io.IOException
12 |
13 | class ChangeHeadText(
14 | private val gallId: String,
15 | private val articleId: Int,
16 | private val headTextId: Int,
17 | private val session: Session
18 | ) {
19 | data class ChangeResult(
20 | val result: Boolean,
21 | val cause: String,
22 | val state: String
23 | )
24 |
25 | /**
26 | * 말머리 변경 요청을 전송합니다.
27 | *
28 | * @throws InsufficientPermissionException 유저 세션이 [Anonymous]일 경우, 예외를 반환합니다.
29 | * @return 변경 요청 결과
30 | */
31 | @Throws(InsufficientPermissionException::class)
32 | fun request(): ChangeResult {
33 | val option = Request.getDefaultOption()
34 | .addMultipartParameter("id", gallId)
35 | .addMultipartParameter("no", articleId.toString())
36 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
37 | .addMultipartParameter("mode", "headtext")
38 | .addMultipartParameter("headtxt_no", headTextId.toString())
39 |
40 | if (session.user is Anonymous) {
41 | throw InsufficientPermissionException(ChangeHeadText::class)
42 | } else {
43 | option.addMultipartParameter("user_id", session.detail!!.userId)
44 | }
45 |
46 | val json = try {
47 | JsonBrowser.parse(
48 | KotlinInside.getInstance().httpInterface.upload(
49 | ApiUrl.Gallery.MINOR_MANAGER_REQUEST,
50 | option
51 | )
52 | ).index(0)
53 | } catch (e: HttpException) {
54 | if (e.cause is IOException) {
55 | return ChangeResult(
56 | result = false,
57 | cause = "권한이 없습니다.",
58 | state = ""
59 | )
60 | } else {
61 | throw e
62 | }
63 | }
64 |
65 | return ChangeResult(
66 | result = json.get("result").asBoolean(),
67 | cause = json.get("cause").safeText(),
68 | state = json.get("state").safeText()
69 | )
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/management/GallerySetting.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.management
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.exception.InsufficientPermissionException
5 | import be.zvz.kotlininside.session.Session
6 | import be.zvz.kotlininside.session.user.Anonymous
7 | import be.zvz.kotlininside.value.ApiUrl
8 | import be.zvz.kotlininside.value.Const
9 |
10 | class GallerySetting(
11 | private val gallId: String,
12 | private val session: Session
13 | ) {
14 | /**
15 | * 갤러리 관리 링크를 반환합니다.
16 | *
17 | * @throws InsufficientPermissionException 유저 세션이 [Anonymous]일 경우, 예외를 반환합니다.
18 | * @return 갤러리 관리 페이지 URL
19 | */
20 | @Throws(InsufficientPermissionException::class)
21 | fun getLink(): String {
22 | val url = "${ApiUrl.Gallery.MINOR_MANAGEMENT}?id=$gallId&app_id=${KotlinInside.getInstance().auth.getAppId()}"
23 |
24 | if (session.user is Anonymous) {
25 | throw InsufficientPermissionException(GallerySetting::class)
26 | } else {
27 | url.plus("&confirm_id=${session.detail!!.userId}")
28 | }
29 |
30 | return url
31 | }
32 |
33 | /**
34 | * User-Agent를 반환합니다.
35 | *
36 | * @return 갤러리 관리에 접근할 때 필요한 User-Agent를 반환합니다.
37 | */
38 | fun getUserAgent(): String {
39 | return Const.USER_AGENT
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/management/NoMemberBlock.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.management
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.exception.InsufficientPermissionException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 | import java.io.IOException
11 | import java.text.SimpleDateFormat
12 | import java.util.*
13 |
14 | class NoMemberBlock(
15 | private val session: Session,
16 | private val gallId: String,
17 | private val option: BlockOption = BlockOption()
18 | ) {
19 | private val dateFormat by lazy { SimpleDateFormat("yyyy.MM.dd HH:mm") }
20 |
21 | enum class ImageStatus(val value: String) {
22 | NONE(""),
23 | ANONYMOUS("A"),
24 | PROXY("P"),
25 | CELLULAR("M"),
26 | PROXY_AND_CELLULAR("P,M")
27 | }
28 |
29 | class BlockOption {
30 | val proxy: Date? = null
31 | val cellular: Date? = null
32 | val image: ImageRestrictionOption? = null
33 |
34 | class ImageRestrictionOption(
35 | val time: Date,
36 | val type: ImageStatus
37 | )
38 | }
39 |
40 | data class BlockResult(
41 | val result: Boolean,
42 | val msg: String
43 | )
44 |
45 | @Throws(InsufficientPermissionException::class)
46 | fun block(): BlockResult {
47 | if (session.user is Anonymous) {
48 | throw InsufficientPermissionException(NoMemberBlock::class)
49 | } else {
50 | val option = Request.getDefaultOption()
51 | .addBodyParameter("app_id", KotlinInside.getInstance().auth.getAppId())
52 | .addBodyParameter("confirm_id", session.detail!!.userId)
53 | .apply {
54 | // proxyDate format = 2022.02.03 20:48(yyyy.MM.dd HH:mm)
55 | // proxyDate, mobileDate, imgDate 는 현재시간 + 48시간, 현재시간 + 1시간, 현재시간 + 48시간 을 넘길 수 없습니다.
56 | // 시간을 초과하게 되면 자동으로 해제됩니다.
57 | if (option.proxy !== null) {
58 | addBodyParameter("proxyDate", dateFormat.format(option.proxy))
59 | }
60 | if (option.cellular !== null) {
61 | addBodyParameter("mobileDate", dateFormat.format(option.cellular))
62 | }
63 | if (option.image !== null) {
64 | addBodyParameter("imgDate", dateFormat.format(option.image.time))
65 | if (option.image.type != ImageStatus.NONE) {
66 | addBodyParameter("imgStatus", option.image.type.value)
67 | }
68 | }
69 | }
70 | val json = try {
71 | JsonBrowser.parse(
72 | KotlinInside.getInstance().httpInterface.post(
73 | "${ApiUrl.Gallery.MINOR_NOMEMBER}/$gallId",
74 | option
75 | )
76 | )
77 | } catch (e: IOException) {
78 | return BlockResult(
79 | result = false,
80 | msg = "권한이 없습니다."
81 | )
82 | }
83 | return BlockResult(
84 | result = json.get("result").asBoolean(),
85 | msg = json.get("msg").safeText()
86 | )
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/management/Notice.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.management
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.exception.InsufficientPermissionException
5 | import be.zvz.kotlininside.http.HttpException
6 | import be.zvz.kotlininside.http.Request
7 | import be.zvz.kotlininside.json.JsonBrowser
8 | import be.zvz.kotlininside.session.Session
9 | import be.zvz.kotlininside.session.user.Anonymous
10 | import be.zvz.kotlininside.value.ApiUrl
11 | import java.io.IOException
12 |
13 | class Notice(
14 | private val gallId: String,
15 | private val articleId: Int,
16 | private val session: Session
17 | ) {
18 | data class NoticeResult(
19 | val result: Boolean,
20 | val cause: String,
21 | val state: String
22 | )
23 |
24 | /**
25 | * 공지를 설정하거나, 해제합니다.
26 | *
27 | * @throws InsufficientPermissionException 유저 세션이 [Anonymous]일 경우, 예외를 반환합니다.
28 | * @return 공지 결과
29 | */
30 | @Throws(InsufficientPermissionException::class)
31 | fun request(): NoticeResult {
32 | val option = Request.getDefaultOption()
33 | .addMultipartParameter("id", gallId)
34 | .addMultipartParameter("no", articleId.toString())
35 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
36 | .addMultipartParameter("mode", "notify")
37 |
38 | if (session.user is Anonymous) {
39 | throw InsufficientPermissionException(Notice::class)
40 | } else {
41 | option.addMultipartParameter("user_id", session.detail!!.userId)
42 | }
43 |
44 | val json = try {
45 | JsonBrowser.parse(
46 | KotlinInside.getInstance().httpInterface.upload(
47 | ApiUrl.Gallery.MINOR_MANAGER_REQUEST,
48 | option
49 | )
50 | ).index(0)
51 | } catch (e: HttpException) {
52 | if (e.cause is IOException) {
53 | return NoticeResult(
54 | result = false,
55 | cause = "권한이 없습니다.",
56 | state = ""
57 | )
58 | } else {
59 | throw e
60 | }
61 | }
62 |
63 | return NoticeResult(
64 | result = json.get("result").asBoolean(),
65 | cause = json.get("cause").safeText(),
66 | state = json.get("state").safeText()
67 | )
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/management/Recommend.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.management
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.exception.InsufficientPermissionException
5 | import be.zvz.kotlininside.http.HttpException
6 | import be.zvz.kotlininside.http.Request
7 | import be.zvz.kotlininside.json.JsonBrowser
8 | import be.zvz.kotlininside.session.Session
9 | import be.zvz.kotlininside.session.user.Anonymous
10 | import be.zvz.kotlininside.value.ApiUrl
11 | import java.io.IOException
12 |
13 | class Recommend(
14 | private val gallId: String,
15 | private val articleId: Int,
16 | private val session: Session
17 | ) {
18 | data class RecommendResult(
19 | val result: Boolean,
20 | val cause: String,
21 | val state: String? = null
22 | )
23 |
24 | /**
25 | * 개념글을 내리거나, 올립니다.
26 | *
27 | * @throws InsufficientPermissionException 유저 세션이 [Anonymous]일 경우, 예외를 반환합니다.
28 | * @return 개념글 설정 결과
29 | */
30 | @Throws(InsufficientPermissionException::class)
31 | fun request(): RecommendResult {
32 | val option = Request.getDefaultOption()
33 | .addMultipartParameter("id", gallId)
34 | .addMultipartParameter("no", articleId.toString())
35 | .addMultipartParameter("app_id", KotlinInside.getInstance().auth.getAppId())
36 | .addMultipartParameter("mode", "recommend")
37 |
38 | if (session.user is Anonymous) {
39 | throw InsufficientPermissionException(Recommend::class)
40 | } else {
41 | option.addMultipartParameter("user_id", session.detail!!.userId)
42 | }
43 |
44 | val json = try {
45 | JsonBrowser.parse(
46 | KotlinInside.getInstance().httpInterface.upload(
47 | ApiUrl.Gallery.MINOR_MANAGER_REQUEST,
48 | option
49 | )
50 | ).index(0)
51 | } catch (e: HttpException) {
52 | if (e.cause is IOException) {
53 | return RecommendResult(
54 | result = false,
55 | cause = "권한이 없습니다."
56 | )
57 | } else {
58 | throw e
59 | }
60 | }
61 |
62 | return RecommendResult(
63 | result = json.get("result").asBoolean(),
64 | cause = json.get("cause").safeText(),
65 | state = json.get("state").text()
66 | )
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/management/UserBlock.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.management
2 |
3 | import be.zvz.kotlininside.KotlinInside
4 | import be.zvz.kotlininside.exception.InsufficientPermissionException
5 | import be.zvz.kotlininside.http.Request
6 | import be.zvz.kotlininside.json.JsonBrowser
7 | import be.zvz.kotlininside.session.Session
8 | import be.zvz.kotlininside.session.user.Anonymous
9 | import be.zvz.kotlininside.value.ApiUrl
10 | import be.zvz.kotlininside.value.Const
11 | import java.io.IOException
12 |
13 | class UserBlock @JvmOverloads constructor(
14 | private val gallId: String,
15 | private val articleId: Int,
16 | private val session: Session,
17 | private val option: BlockOption = BlockOption()
18 | ) {
19 | enum class BlockCategory(val code: Int) {
20 | OBSCENE(1),
21 | ADVERTISEMENT(2),
22 | CUSS_WORDS(3),
23 | SPAMMING(4),
24 | PIRACY(5),
25 | DEFAMATION(6),
26 | CUSTOM(7)
27 | }
28 |
29 | class BlockOption {
30 | var commentId = 0
31 | var blockHour = 1
32 | var blockCategory = BlockCategory.CUSTOM
33 | var blockReason: String = "사유 없음"
34 | }
35 |
36 | data class BlockResult(
37 | val result: Boolean,
38 | val cause: String
39 | )
40 |
41 | @Throws(InsufficientPermissionException::class)
42 | fun block(): BlockResult {
43 | if (session.user is Anonymous) {
44 | throw InsufficientPermissionException(UserBlock::class)
45 | }
46 |
47 | val requestOption = Request.getDefaultOption()
48 | .addBodyParameter("_token", "")
49 | .addBodyParameter("avoid_hour", option.blockHour.toString())
50 | .addBodyParameter("avoid_category", option.blockCategory.code.toString())
51 |
52 | if (option.blockCategory === BlockCategory.CUSTOM) {
53 | requestOption.addBodyParameter("avoid_memo", option.blockReason)
54 | }
55 |
56 | requestOption
57 | .addBodyParameter("id", gallId)
58 | .addBodyParameter("no", articleId.toString())
59 |
60 | if (option.commentId > 0) {
61 | requestOption.addBodyParameter("comment_no", option.commentId.toString())
62 | }
63 |
64 | requestOption
65 | .addBodyParameter("app_id", KotlinInside.getInstance().auth.getAppId())
66 | .addBodyParameter("confirm_id", session.detail!!.userId)
67 |
68 | val json: JsonBrowser = try {
69 | JsonBrowser.parse(
70 | KotlinInside.getInstance().httpInterface.post(
71 | ApiUrl.Gallery.MINOR_BLOCK_ADD,
72 | requestOption
73 | )
74 | )
75 | } catch (e: IOException) {
76 | return BlockResult(
77 | result = false,
78 | cause = "권한이 없습니다."
79 | )
80 | }
81 |
82 | return BlockResult(
83 | result = json.get("result").asBoolean(),
84 | cause = json.get("cause").safeText()
85 | )
86 | }
87 |
88 | /**
89 | * 갤러리 유저 차단 링크를 반환합니다.
90 | *
91 | * @throws RuntimeException 유저 세션이 [Anonymous]일 경우, 예외를 반환합니다.
92 | * @return 갤러리 유저 차단 URL을 반환합니다.
93 | */
94 | fun getLink(): String {
95 | val url =
96 | "${ApiUrl.Gallery.MINOR_BLOCK_WEB}?id=$gallId&no=$articleId&app_id=${KotlinInside.getInstance().auth.getAppId()}"
97 |
98 | if (option.commentId > 0) {
99 | url.plus("&comment_no=${option.commentId}")
100 | }
101 |
102 | if (session.user is Anonymous) {
103 | throw RuntimeException("Anonymous는 갤러리 유저 차단을 사용할 수 없습니다.")
104 | } else {
105 | url.plus("&confirm_id=${session.detail!!.userId}")
106 | }
107 |
108 | return url
109 | }
110 |
111 | /**
112 | * User-Agent를 반환합니다.
113 | *
114 | * @return 갤러리 유저 차단에 접근할 때 필요한 User-Agent를 반환합니다.
115 | */
116 | fun getUserAgent(): String {
117 | return Const.USER_AGENT
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/Article.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type
2 |
3 | import be.zvz.kotlininside.api.type.content.Content
4 |
5 | data class Article @JvmOverloads constructor(
6 | val subject: String,
7 | val content: List,
8 | val headText: HeadText? = null
9 | )
10 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/DCCon.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type
2 |
3 | data class DCCon @JvmOverloads constructor(
4 | val packageIndex: Int = 0,
5 | val detailIndex: Int = 0,
6 | val imgLink: String = "",
7 | val memo: String = "",
8 | val title: String = ""
9 | )
10 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/Gallery.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type
2 |
3 | data class Gallery(
4 | val title: String,
5 | val id: String
6 | )
7 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/HeadText.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type
2 |
3 | data class HeadText @JvmOverloads constructor(
4 | val identifier: Int,
5 | val name: String,
6 | val level: Int = 0,
7 | val selected: Boolean = false
8 | )
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/comment/Comment.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.comment
2 |
3 | interface Comment
4 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/comment/DCConComment.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.comment
2 |
3 | import be.zvz.kotlininside.api.type.DCCon
4 |
5 | data class DCConComment(
6 | val dcCon: DCCon
7 | ) : Comment
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/comment/StringComment.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.comment
2 |
3 | data class StringComment(
4 | val memo: String
5 | ) : Comment
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/Content.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | interface Content
4 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/DCConContent.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | import be.zvz.kotlininside.api.dccon.DCConInsert
4 | import be.zvz.kotlininside.api.type.DCCon
5 |
6 | data class DCConContent(
7 | val dcCon: DCCon,
8 | val dcConInsertResult: DCConInsert.InsertResult
9 | ) : Content
10 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/HtmlContent.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | data class HtmlContent(
4 | val htmlString: String
5 | ) : Content
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/ImageContent.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | import java.io.BufferedInputStream
4 | import java.io.File
5 | import java.io.FileInputStream
6 | import java.io.InputStream
7 | import java.net.URLConnection
8 |
9 | data class ImageContent @JvmOverloads constructor(
10 | val stream: InputStream,
11 | val mimeType: String? = null
12 | ) : Content, AutoCloseable {
13 | constructor(
14 | urlConnection: URLConnection
15 | ) : this(
16 | stream = BufferedInputStream(urlConnection.inputStream),
17 | mimeType = urlConnection.contentType
18 | )
19 | constructor(
20 | file: File
21 | ) : this(
22 | stream = BufferedInputStream(FileInputStream(file))
23 | )
24 |
25 | override fun close() {
26 | stream.close()
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/MarkdownContent.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | data class MarkdownContent(
4 | val markdownString: String
5 | ) : Content
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/MovieContent.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | import java.io.BufferedInputStream
4 | import java.io.File
5 | import java.io.FileInputStream
6 | import java.io.InputStream
7 |
8 | /**
9 | * [MovieContent]를 사용한 글을 작성해야 할 경우,
10 | * 글 작성 전에 [be.zvz.kotlininside.api.generic.MovieUpload]를 사용하여
11 | * [MovieContent]를 업로드 해놓아야 합니다.
12 | */
13 | data class MovieContent @JvmOverloads constructor(
14 | val info: MovieInfo,
15 | val stream: InputStream,
16 | val mimeType: String? = null
17 | ) : Content, AutoCloseable {
18 | data class MovieInfo @JvmOverloads constructor(
19 | val allowDownload: Boolean,
20 | val description: String,
21 | val tag: List = emptyList()
22 | ) {
23 | /**
24 | * [be.zvz.kotlininside.api.generic.MovieUpload]에서 얻은 섬네일 URL 중 하나를 입력해주시면 됩니다.
25 | */
26 | var thumbnailUrl: String = ""
27 | var width = 0
28 | internal set
29 | var height = 0
30 | internal set
31 | }
32 |
33 | internal var uploaded = false
34 | internal var fileId: Int = 0
35 | constructor(
36 | info: MovieInfo,
37 | file: File
38 | ) : this(
39 | info,
40 | stream = BufferedInputStream(FileInputStream(file))
41 | )
42 |
43 | override fun close() {
44 | stream.close()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/api/type/content/StringContent.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.api.type.content
2 |
3 | data class StringContent(
4 | val string: String
5 | ) : Content
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/exception/InsufficientPermissionException.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.exception
2 |
3 | import kotlin.reflect.KClass
4 |
5 | class InsufficientPermissionException(val causeClass: KClass<*>) :
6 | IllegalStateException("Insufficient permission to use ${causeClass.simpleName}")
7 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/http/HttpException.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.http
2 |
3 | class HttpException : RuntimeException {
4 | val statusCode: Int
5 |
6 | constructor(
7 | statusCode: Int,
8 | errorMessage: String?
9 | ) : super("Error Code : $statusCode, Error Message : $errorMessage") {
10 | this.statusCode = statusCode
11 | }
12 |
13 | constructor(cause: Throwable?) : super(cause) {
14 | statusCode = 520
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/http/Request.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.http
2 |
3 | import be.zvz.kotlininside.migbase64.Base64
4 | import be.zvz.kotlininside.value.ApiUrl
5 | import be.zvz.kotlininside.value.Const
6 |
7 | object Request {
8 | @JvmStatic
9 | fun redirectUrl(url: String): String =
10 | ApiUrl.REDIRECT + "?hash=" + Base64.encodeToString(url.toByteArray(), false)
11 |
12 | @JvmStatic
13 | fun getDefaultOption(): HttpInterface.Option = HttpInterface.Option()
14 | .setUserAgent(Const.USER_AGENT)
15 | .addHeader("Referer", "http://www.dcinside.com")
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/security/App.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.security
2 |
3 | data class App(val token: String, val id: String)
4 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/security/RandomFidGenerator.kt:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package be.zvz.kotlininside.security
15 |
16 | import be.zvz.kotlininside.migbase64.Base64
17 | import java.nio.ByteBuffer
18 | import java.util.UUID
19 |
20 | /** @hide
21 | */
22 | object RandomFidGenerator {
23 | /**
24 | * Creates a random FID of valid format without checking if the FID is already in use by any
25 | * Firebase Installation.
26 | *
27 | *
28 | * Note: Even though this method does not check with the FIS database if the returned FID is
29 | * already in use, the probability of collision is extremely and negligibly small!
30 | *
31 | * @return random FID value
32 | */
33 | fun createRandomFid(): String {
34 | // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5 bytes.
35 | val uuidBytes = getBytesFromUUID(UUID.randomUUID(), ByteArray(17))
36 | uuidBytes[16] = uuidBytes[0]
37 | uuidBytes[0] = (REMOVE_PREFIX_MASK.toInt() and uuidBytes[0].toInt() or FID_4BIT_PREFIX.toInt()).toByte()
38 | return encodeFidBase64UrlSafe(uuidBytes)
39 | }
40 |
41 | /**
42 | * 1 Byte with the first 4 header-bits set to the identifying FID prefix 0111 (0x7). Use this
43 | * constant to create FIDs or check the first byte of FIDs. This prefix is also used in legacy
44 | * Instance-IDs
45 | */
46 | private val FID_4BIT_PREFIX = "01110000".toByte(2)
47 |
48 | /**
49 | * Byte mask to remove the 4 header-bits of a given Byte. Use this constant with Java's Binary AND
50 | * Operator in order to remove the first 4 bits of a Byte and replacing it with the FID prefix.
51 | */
52 | private val REMOVE_PREFIX_MASK = "00001111".toByte(2)
53 |
54 | /** Length of new-format FIDs as introduced in 2019. */
55 | private const val FID_LENGTH = 22
56 |
57 | /**
58 | * Converts a given byte-array (assumed to be an FID value) to base64-url-safe encoded
59 | * String-representation.
60 | *
61 | *
62 | * Note: The returned String has at most 22 characters, the length of FIDs. Thus, it is
63 | * recommended to deliver a byte-array containing at least 16.5 bytes.
64 | *
65 | * @param rawValue FID value to be encoded
66 | * @return (22-character or shorter) String containing the base64-encoded value
67 | */
68 | private fun encodeFidBase64UrlSafe(rawValue: ByteArray): String {
69 | return Base64.encodeToString(
70 | rawValue,
71 | false
72 | ).substring(0, FID_LENGTH)
73 | }
74 |
75 | private fun getBytesFromUUID(uuid: UUID, output: ByteArray): ByteArray {
76 | val bb = ByteBuffer.wrap(output)
77 | bb.putLong(uuid.mostSignificantBits)
78 | bb.putLong(uuid.leastSignificantBits)
79 | return bb.array()
80 | }
81 | }
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/Session.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session
2 |
3 | import be.zvz.kotlininside.session.user.User
4 |
5 | data class Session(
6 | val user: User,
7 | val detail: SessionDetail?
8 | )
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/SessionDetail.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session
2 |
3 | data class SessionDetail(
4 | val result: Boolean,
5 | val userId: String,
6 | val userNo: String,
7 | val name: String,
8 | val sessionType: String,
9 | val isAdult: Int,
10 | val isDormancy: Int,
11 | val isOtp: Int,
12 | val pwCampaign: Int,
13 | val mailSend: String,
14 | val isGonick: Int,
15 | val isSecurityCode: String,
16 | val authChange: Int,
17 | val cause: String?
18 | )
19 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/user/Anonymous.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session.user
2 |
3 | data class Anonymous(
4 | override val id: String,
5 | override val password: String
6 | ) : User
7 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/user/LoginUser.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session.user
2 |
3 | open class LoginUser(
4 | override val id: String,
5 | override val password: String
6 | ) : User
7 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/user/User.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session.user
2 |
3 | interface User {
4 | val id: String
5 | val password: String
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/user/UserType.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session.user
2 |
3 | enum class UserType(val sessionType: String) {
4 | ANONYMOUS("C"),
5 | NAMED("A"),
6 | DUPLICATE_NAMED("B")
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/user/named/DuplicateNamed.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session.user.named
2 |
3 | import be.zvz.kotlininside.session.user.LoginUser
4 |
5 | data class DuplicateNamed(
6 | override val id: String,
7 | override val password: String
8 | ) : LoginUser(id, password)
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/session/user/named/Named.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.session.user.named
2 |
3 | import be.zvz.kotlininside.session.user.LoginUser
4 |
5 | data class Named(
6 | override val id: String,
7 | override val password: String
8 | ) : LoginUser(id, password)
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/utils/StringUtil.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.utils
2 |
3 | import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
4 | import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
5 | import com.vladsch.flexmark.ext.tables.TablesExtension
6 | import com.vladsch.flexmark.html.HtmlRenderer
7 | import com.vladsch.flexmark.parser.Parser
8 | import com.vladsch.flexmark.util.data.MutableDataSet
9 |
10 | object StringUtil {
11 | private val OPTIONS = MutableDataSet()
12 | .set(
13 | Parser.EXTENSIONS,
14 | listOf(
15 | TablesExtension.create(),
16 | StrikethroughExtension.create(),
17 | TaskListExtension.create()
18 | )
19 | )
20 | .toImmutable()
21 |
22 | private val MD_PARSER = Parser.builder(OPTIONS).build()
23 | private val HTML_RENDERER = HtmlRenderer.builder(OPTIONS).escapeHtml(true).build()
24 |
25 | @JvmStatic
26 | fun ynToBoolean(s: String): Boolean = when (s.lowercase()) {
27 | "y" -> true
28 | else -> false
29 | }
30 |
31 | @JvmStatic
32 | fun okToBoolean(s: String): Boolean = when (s.lowercase()) {
33 | "ok" -> true
34 | else -> false
35 | }
36 |
37 | @JvmStatic
38 | fun mdToHtml(s: String): String = HTML_RENDERER.render(MD_PARSER.parse(s))
39 |
40 | @JvmStatic
41 | fun toHtml(s: String): String = StringBuilder().apply {
42 | var previousWasASpace = false
43 |
44 | s.toCharArray().forEach { c ->
45 | if (c == ' ') {
46 | if (previousWasASpace) {
47 | append(" ")
48 | previousWasASpace = false
49 | return@forEach
50 | }
51 | previousWasASpace = true
52 | } else {
53 | previousWasASpace = false
54 | }
55 |
56 | when (c) {
57 | '<' -> append("<")
58 | '>' -> append(">")
59 | '&' -> append("&")
60 | '"' -> append(""")
61 | '\n' -> append("
")
62 | '\t' -> append(" ")
63 | else -> append(c)
64 | }
65 | }
66 | }.toString()
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/value/ApiUrl.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.value
2 |
3 | object ApiUrl {
4 | const val PC_WEB = Protocol.HTTPS + "gall.dcinside.com/"
5 | const val MOBILE_WEB = Protocol.HTTP + "m.dcinside.com/"
6 | const val MOBILE_WEB_HTTPS = Protocol.HTTPS + "m.dcinside.com/"
7 | const val MOBILE_APP = Protocol.HTTPS + "app.dcinside.com/"
8 | const val APP_API = MOBILE_APP + "api/"
9 | const val AUTH_API = Protocol.HTTPS + "msign.dcinside.com/"
10 | const val MAIN_API = Protocol.HTTP + "json2.dcinside.com/"
11 | const val UPLOAD = Protocol.HTTPS + "upload.dcinside.com/"
12 | const val MOVIE_UPLOAD = Protocol.HTTPS + "m4up4.dcinside.com/"
13 | const val REDIRECT = APP_API + "redirect.php"
14 |
15 | private object Protocol {
16 | const val HTTP = "http://"
17 | const val HTTPS = "https://"
18 | }
19 |
20 | object Firebase {
21 | const val INSTALLATIONS =
22 | Protocol.HTTPS + "firebaseinstallations.googleapis.com/v1/projects/dcinside-b3f40/installations"
23 | const val REMOTE_CONFIG =
24 | Protocol.HTTPS + "firebaseremoteconfig.googleapis.com/v1/projects/${Const.Register3.SENDER}/namespaces/firebase:fetch"
25 | }
26 |
27 | object PlayService {
28 | const val ANDROID_CLIENT = Protocol.HTTPS + "android.clients.google.com"
29 | const val ANDROID_APIS = Protocol.HTTPS + "android.apis.google.com"
30 | const val REGISTER3 = "$ANDROID_APIS/c2dm/register3"
31 | const val CHECKIN = "$ANDROID_CLIENT/checkin"
32 | }
33 |
34 | object Upload {
35 | const val CHECK_UPLOAD_RESTRICTION = APP_API + "chk_upload_restriction"
36 | const val MOVIE = "$MOVIE_UPLOAD/movie_upload_v1.php"
37 | }
38 |
39 | object Article {
40 | const val LIST = APP_API + "gall_list_new.php"
41 | const val READ = APP_API + "gall_view_new.php"
42 | const val WRITE = UPLOAD + "_app_write_api.php"
43 | const val DELETE = APP_API + "gall_del.php"
44 | const val MODIFY = APP_API + "gall_modify.php"
45 | const val UPVOTE = APP_API + "_recommend_up.php"
46 | const val DOWNVOTE = APP_API + "_recommend_down.php"
47 | const val REPORT = MOBILE_WEB + "api/report.php"
48 | const val HIT_UPVOTE = APP_API + "hit_recommend"
49 | const val INSERT_MOVIE_INFO = MOBILE_APP + "movie/insert-mvinfo"
50 | }
51 |
52 | object Comment {
53 | const val OK = APP_API + "comment_ok.php"
54 | const val DELETE = APP_API + "comment_del.php"
55 | const val READ = APP_API + "comment_new.php"
56 | }
57 |
58 | object DCCon {
59 | const val DCCON = APP_API + "dccon.php"
60 | }
61 |
62 | object Gallery {
63 | const val MINOR_INFO = APP_API + "minor_info"
64 | const val MINOR_MANAGEMENT = PC_WEB + "mgallery/management/mobile"
65 | const val MINOR_NOMEMBER = MOBILE_WEB_HTTPS + "management/minor/nomember"
66 | const val MINOR_MANAGER_REQUEST = APP_API + "_manager_request.php"
67 | const val MINOR_BLOCK_WEB = APP_API + "minor_avoid"
68 | const val MINOR_BLOCK_ADD = APP_API + "minor_avoidadd"
69 | }
70 |
71 | object Search {
72 | const val SEARCH = APP_API + "_total_search.php"
73 | }
74 |
75 | object Auth {
76 | const val LOGIN = AUTH_API + "api/login"
77 | const val APP_ID = AUTH_API + "auth/mobile_app_verification"
78 | const val APP_CHECK = MAIN_API + "json0/app_check_A_rina_one_new.php"
79 | }
80 |
81 | object User {
82 | const val MY_GALL = APP_API + "mygall.php"
83 | const val MY_GALL_MODIFY = APP_API + "mygall_modify.php"
84 | const val MY_MANAGE_GALL_CHECK = APP_API + "mymanageGallChk"
85 | const val MY_MINI_JOIN_CHECK = APP_API + "myminijoinGallChk"
86 | }
87 |
88 | object MiniGallery {
89 | const val JOIN = APP_API + "memberjoin"
90 | const val JOIN_OK = APP_API + "memberjoin_ok"
91 | const val QUIT = APP_API + "memberout_ok"
92 | }
93 |
94 | object MainInfo {
95 | const val NOTICE = MAIN_API + "json3/app_dc_notice_one_new.php"
96 | const val APP_MAIN = MAIN_API + "json3/main_content.php"
97 | const val GALLERY_RANKING = MAIN_API + "json3/ranking_gallery.php"
98 | const val MINOR_GALLERY_RANKING = MAIN_API + "json1/mgallmain/mgallery_ranking.php"
99 | const val MINI_GALLERY_RANKING = MAIN_API + "json1/migallmain/migallery_ranking.php"
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/kotlin/be/zvz/kotlininside/value/Const.kt:
--------------------------------------------------------------------------------
1 | package be.zvz.kotlininside.value
2 |
3 | object Const {
4 | const val DC_APP_SIGNATURE = "ReOo4u96nnv8Njd7707KpYiIVYQ3FlcKHDJE046Pg6s="
5 | const val DC_APP_PACKAGE = "com.dcinside.app.android"
6 | const val DC_APP_VERSION_CODE = "100051"
7 | const val DC_APP_VERSION_NAME = "4.8.1"
8 | const val DC_APP_TARGET_VERSION = "33"
9 | const val USER_AGENT = "dcinside.app"
10 |
11 | object Firebase {
12 | const val APP_ID = "1:${Register3.SENDER}:android:d2ffdd960120a207727842"
13 | const val AUTH_VERSION = "FIS_v2"
14 | const val FIREBASE_CLIENT = "H4sIAAAAAAAAAKtWykhNLCpJSk0sKVayio7VUSpLLSrOzM9TslIyUqoFAFyivEQfAAAA"
15 | const val SDK_VERSION = "a:17.1.0"
16 | const val REMOTE_CONFIG_SDK_VERSION = "21.2.1"
17 | const val CERT = "43bd70dfc365ec1749f0424d28174da44ee7659d"
18 | const val OS_VERSION = "25"
19 | const val CLIV = "fcm-23.1.1"
20 | const val INFO = "Q2U3ar09NyAToOhBO1boBVw1nzmBjxg"
21 | const val TARGET_VER = DC_APP_TARGET_VERSION
22 | const val GCM_VERSION = "232512022"
23 | }
24 |
25 | object Installations {
26 | const val X_ANDROID_PACKAGE = DC_APP_PACKAGE
27 | const val X_ANDROID_CERT = Firebase.CERT
28 | const val X_GOOG_API_KEY = "AIzaSyDcbVof_4Bi2GwJ1H8NjSwSTaMPPZeCE38"
29 | }
30 |
31 | object Register3 {
32 | const val SENDER = "477369754343"
33 | const val X_SCOPE_ALL = "*"
34 | const val X_SCOPE_REFRESH_REMOTE_CONFIG = "/topics/DcRefreshRemoteConfig"
35 | const val X_SCOPE_SHOW_NOTICE_MESSAGE = "/topics/DcShowNoticeMessage"
36 | const val X_FIREBASE_APP_NAME_HASH = "R1dAH9Ui7M-ynoznwBdw01tLxhI"
37 | const val USER_AGENT = "Android-GCM/1.5 (generic_x86 KK)"
38 | const val APP = DC_APP_PACKAGE
39 | const val GCM_VERSION = Firebase.GCM_VERSION
40 | const val CERT = Firebase.CERT
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/구현 TODO.md:
--------------------------------------------------------------------------------
1 | # 구현해야하는 API 목록
2 |
3 | ### 알림 (FCM Token)
4 | - [x] 댓글 / 대댓글 알림
5 |
6 | ### 인증
7 | - [x] app_id 키젠
8 | - [ ] 캡차
9 |
10 | ### 계정
11 | - [x] 로그인
12 | - [x] 차단 확인
13 |
14 |
15 | ### 글 관련
16 | - [x] 글 조회
17 | - [x] 댓글 조회
18 | - [x] 글 목록 불러오기
19 | - [x] 사진 업로드
20 | - [x] 글 삭제
21 | - [x] 댓글 삭제
22 | - [x] 대댓글 삭제
23 | - [x] 힛갤 추천
24 | - [x] 게시물 신고
25 |
26 | **고정닉**
27 | - [x] 고닉 추천 & 비추천
28 | - [x] 고닉 글 쓰기
29 | - [x] 고닉 글 수정
30 | - [x] 고닉 댓글 작성
31 | - [x] 고닉 대댓글 작성
32 |
33 | **유동닉**
34 | - [x] 유동 추천 & 비추천
35 | - [x] 유동 글 쓰기
36 | - [x] 유동 글 수정
37 | - [x] 유동 댓글 작성
38 | - [x] 유동 대댓글 작성
39 |
40 |
41 | ### 일반
42 | - [x] 메인화면
43 | - [x] 실북갤 랭킹
44 | - [x] 마이너갤 정보 확인
45 | - [x] 마이너갤 관리자 기능
46 |
47 | **검색**
48 | - [x] 통합검색
49 | - [x] 갤러리 검색
50 | - [x] 갤러리내 글 검색 (개념글 유무 포함)
51 |
52 | **디시콘**
53 | - [x] 모든 디시콘 목록 불러오기
54 | - [x] 댓글 디시콘 사용
55 | - [x] 사용할 디시콘 목록 불러오기
56 | - [x] 다른 디시콘 정보 불러오기
57 |
--------------------------------------------------------------------------------