Upstream changes (#23)

This commit is contained in:
2024-07-11 02:12:32 +03:00
committed by GitHub
parent 8a6378f509
commit 3503ecffab
906 changed files with 23577 additions and 24115 deletions
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,22 @@
package com.meloda.app.fast.model;
enum class ApiEvent(val value: Int) {
MESSAGE_SET_FLAGS(2),
MESSAGE_CLEAR_FLAGS(3),
MESSAGE_NEW(4),
MESSAGE_EDIT(5),
MESSAGE_READ_INCOMING(6),
MESSAGE_READ_OUTGOING(7),
MESSAGES_DELETED(13),
PIN_UNPIN_CONVERSATION(20),
TYPING(63),
AUDIO_MESSAGE_RECORDING(64),
PHOTO_UPLOADING(65),
VIDEO_UPLOADING(66),
FILE_UPLOADING(67),
UNREAD_COUNT_UPDATE(80);
companion object {
fun parse(value: Int) = entries.first { it.value == value }
}
}
@@ -0,0 +1,5 @@
package com.meloda.app.fast.model
sealed class BaseError {
data object SessionExpired : BaseError()
}
@@ -0,0 +1,8 @@
package com.meloda.app.fast.model
import com.meloda.app.fast.model.api.domain.VkUser
data class FriendsInfo(
val friends: List<VkUser>,
val onlineFriends: List<VkUser>
)
@@ -0,0 +1,20 @@
package com.meloda.app.fast.model
sealed class InteractionType(val value: Int) {
data object Typing : InteractionType(1)
data object VoiceMessage : InteractionType(2)
data object Photo : InteractionType(3)
data object Video : InteractionType(4)
data object File : InteractionType(5)
companion object {
fun parse(value: Int): InteractionType? = when (value) {
1 -> Typing
2 -> VoiceMessage
3 -> Photo
4 -> Video
5 -> File
else -> null
}
}
}
@@ -0,0 +1,35 @@
package com.meloda.app.fast.model
import com.meloda.app.fast.model.api.domain.VkMessage
sealed interface LongPollEvent {
data class VkMessageNewEvent(val message: VkMessage) : LongPollEvent
data class VkMessageEditEvent(val message: VkMessage) : LongPollEvent
data class VkMessageReadIncomingEvent(
val peerId: Int,
val messageId: Int,
val unreadCount: Int,
) : LongPollEvent
data class VkMessageReadOutgoingEvent(
val peerId: Int,
val messageId: Int,
val unreadCount: Int,
) : LongPollEvent
data class VkConversationPinStateChangedEvent(
val peerId: Int,
val majorId: Int,
) : LongPollEvent
data class Interaction(
val interactionType: InteractionType,
val peerId: Int,
val userIds: List<Int>,
val totalCount: Int,
val timestamp: Int
) : LongPollEvent
}
@@ -0,0 +1,3 @@
package com.meloda.app.fast.model.api
fun Boolean.asInt(): Int = if (this) 1 else 0
@@ -0,0 +1,17 @@
package com.meloda.app.fast.model.api;
enum class PeerType(val value: String) {
USER("user"),
GROUP("group"),
CHAT("chat");
fun isUser(): Boolean = this == USER
fun isGroup(): Boolean = this == GROUP
fun isChat(): Boolean = this == CHAT
companion object {
fun parse(type: String): PeerType {
return entries.first { it.value == type }
}
}
}
@@ -0,0 +1,45 @@
package com.meloda.app.fast.model.api.data
import android.util.Log
enum class AttachmentType(var value: String) {
UNKNOWN("unknown"),
PHOTO("photo"),
VIDEO("video"),
AUDIO("audio"),
FILE("doc"),
LINK("link"),
AUDIO_MESSAGE("audio_message"),
MINI_APP("mini_app"),
STICKER("sticker"),
GIFT("gift"),
WALL("wall"),
GRAFFITI("graffiti"),
POLL("poll"),
WALL_REPLY("wall_reply"),
CALL("call"),
GROUP_CALL_IN_PROGRESS("group_call_in_progress"),
CURATOR("curator"),
EVENT("event"),
STORY("story"),
WIDGET("widget"),
ARTIST("artist"),
AUDIO_PLAYLIST("audio_playlist"),
PODCAST("podcast");
fun isMultiple(): Boolean = this in listOf(PHOTO, VIDEO, AUDIO, FILE)
companion object {
fun parse(value: String): AttachmentType {
val parsedValue = entries.firstOrNull {
it.value == value
} ?: UNKNOWN
if (parsedValue == UNKNOWN) {
Log.e("AttachmentType", "Unknown attachment type: $value")
}
return parsedValue
}
}
}
@@ -0,0 +1,14 @@
package com.meloda.app.fast.model.api.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class LongPollUpdates(
@Json(name = "failed") val failed: Int?,
@Json(name = "ts") val ts: Int?,
@Json(name = "pts") val pts: Int?,
// TODO: 14/05/2024, Danil Nikolaev: List<List<Any>>?????
@Json(name = "updates") val updates: List<List<Any>>?,
@Json(name = "error") val error: String?
)
@@ -0,0 +1,27 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkArtistDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkArtistData(
@Json(name = "name") val name: String,
@Json(name = "id") val id: String,
@Json(name = "photo") val photo: List<PhotoSize>?,
@Json(name = "popular_audios_block_id") val popularAudiosBlockId: String?
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class PhotoSize(
val height: Int,
val width: Int,
val url: String
)
fun toDomain(): VkArtistDomain = VkArtistDomain(
id = id,
name = name,
photos = photo.orEmpty()
)
}
@@ -0,0 +1,3 @@
package com.meloda.app.fast.model.api.data
interface VkAttachmentData
@@ -0,0 +1,35 @@
package com.meloda.app.fast.model.api.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkAttachmentItemData(
@Json(name = "type") val type: String,
@Json(name = "photo") val photo: VkPhotoData?,
@Json(name = "video") val video: VkVideoData?,
@Json(name = "audio") val audio: VkAudioData?,
@Json(name = "doc") val file: VkFileData?,
@Json(name = "link") val link: VkLinkData?,
@Json(name = "mini_app") val miniApp: VkMiniAppData?,
@Json(name = "audio_message") val voiceMessage: VkAudioMessageData?,
@Json(name = "sticker") val sticker: VkStickerData?,
@Json(name = "gift") val gift: VkGiftData?,
@Json(name = "wall") val wall: VkWallData?,
@Json(name = "graffiti") val graffiti: VkGraffitiData?,
@Json(name = "poll") val poll: VkPollData?,
@Json(name = "wall_reply") val wallReply: VkWallReplyData?,
@Json(name = "call") val call: VkCallData?,
@Json(name = "group_call_in_progress") val groupCall: VkGroupCallData?,
@Json(name = "curator") val curator: VkCuratorData?,
@Json(name = "event") val event: VkEventData?,
@Json(name = "story") val story: VkStoryData?,
@Json(name = "widget") val widget: VkWidgetData?,
@Json(name = "artist") val artist: VkArtistData?,
@Json(name = "audios") val audios: List<VkAudioData>?,
@Json(name = "audio_playlist") val audioPlaylist: VkAudioPlaylistData?,
@Json(name = "podcast") val podcast: VkPodcastData?
) {
fun getPreparedType(): AttachmentType = AttachmentType.parse(type)
}
@@ -0,0 +1,56 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkAudioDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkAudioData(
@Json(name = "id") val id: Int,
@Json(name = "title") val title: String,
@Json(name = "artist") val artist: String,
@Json(name = "duration") val duration: Int,
@Json(name = "url") val url: String,
@Json(name = "date") val date: Int,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "access_key") val accessKey: String?,
@Json(name = "is_explicit") val isExplicit: Boolean,
@Json(name = "is_focus_track") val isFocusTrack: Boolean,
@Json(name = "is_licensed") val isLicensed: Boolean?,
@Json(name = "genre_id") val genreId: Int?,
@Json(name = "album") val album: Album?,
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class Album(
@Json(name = "id") val id: Int,
@Json(name = "title") val title: String,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "access_key") val accessKey: String,
@Json(name = "thumb") val thumb: Thumb
) {
@JsonClass(generateAdapter = true)
data class Thumb(
@Json(name = "width") val width: Int,
@Json(name = "height") val height: Int,
@Json(name = "photo_34") val photo34: String?,
@Json(name = "photo_68") val photo68: String?,
@Json(name = "photo_135") val photo135: String?,
@Json(name = "photo_270") val photo270: String?,
@Json(name = "photo_300") val photo300: String?,
@Json(name = "photo_600") val photo600: String?,
@Json(name = "photo_1200") val photo1200: String?
)
}
fun toDomain() = VkAudioDomain(
id = id,
ownerId = ownerId,
title = title,
artist = artist,
url = url,
duration = duration,
accessKey = accessKey
)
}
@@ -0,0 +1,31 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkAudioMessageDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkAudioMessageData(
@Json(name = "id") val id: Int,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "duration") val duration: Int,
@Json(name = "waveform") val waveform: List<Int>,
@Json(name = "link_ogg") val linkOgg: String,
@Json(name = "link_mp3") val linkMp3: String,
@Json(name = "access_key") val accessKey: String,
@Json(name = "transcript_state") val transcriptState: String?,
@Json(name = "transcript") val transcript: String?
) {
fun toDomain() = VkAudioMessageDomain(
id = id,
ownerId = ownerId,
duration = duration,
waveform = waveform,
linkOgg = linkOgg,
linkMp3 = linkMp3,
accessKey = accessKey,
transcriptState = transcriptState,
transcript = transcript
)
}
@@ -0,0 +1,23 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkAudioPlaylistDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkAudioPlaylistData(
@Json(name = "id") val id: Int,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "type") val type: Int,
@Json(name = "title") val title: String,
@Json(name = "description") val description: String,
// ... other fields
) : VkAttachmentData {
fun toDomain(): VkAudioPlaylistDomain = VkAudioPlaylistDomain(
id = id,
ownerId = ownerId,
title = title,
description = description
)
}
@@ -0,0 +1,25 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkCallDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkCallData(
@Json(name = "initiator_id") val initiatorId: Int,
@Json(name = "receiver_id") val receiverId: Int,
@Json(name = "state") val state: String,
@Json(name = "time") val time: Int,
@Json(name = "duration") val duration: Int,
@Json(name = "video") val video: Boolean
) {
fun toDomain() = VkCallDomain(
initiatorId = initiatorId,
receiverId = receiverId,
state = state,
time = time,
duration = duration,
isVideo = video
)
}
@@ -0,0 +1,37 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkChatDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkChatData(
@Json(name = "type") val type: String,
@Json(name = "val title") val title: String,
@Json(name = "admin_id") val adminId: Int,
@Json(name = "members_count") val membersCount: Int,
@Json(name = "id") val id: Int,
@Json(name = "photo_50") val photo50: String,
@Json(name = "photo_100") val photo100: String,
@Json(name = "photo_200") val photo200: String,
@Json(name = "is_default_photo") val isDefaultPhoto: Boolean,
@Json(name = "push_settings") val pushSettings: PushSettings?
) {
@JsonClass(generateAdapter = true)
data class PushSettings(
@Json(name = "sound") val sound: Int,
@Json(name = "disabled_until") val disabledUntil: Int
)
fun mapToDomain() = VkChatDomain(
type = type,
title = title,
adminId = adminId,
membersCount = membersCount,
id = id,
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
isDefaultPhoto = isDefaultPhoto
)
}
@@ -0,0 +1,25 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkChatMemberDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkChatMemberData(
@Json(name = "member_id") val memberId: Int,
@Json(name = "invited_by") val invitedBy: Int,
@Json(name = "join_date") val joinDate: Int,
@Json(name = "is_admin") val isAdmin: Boolean?,
@Json(name = "is_owner") val isOwner: Boolean?,
@Json(name = "can_kick") val canKick: Boolean?
) {
fun mapToDomain() = VkChatMemberDomain(
memberId = memberId,
invitedBy = invitedBy,
joinDate = joinDate,
isAdmin = isAdmin == true,
isOwner = isOwner == true,
canKick = canKick == true
)
}
@@ -0,0 +1,22 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkContactDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkContactData(
@Json(name = "id") val id: Int,
@Json(name = "name") val name: String,
@Json(name = "can_write") val canWrite: Boolean,
@Json(name = "user_id") val userId: Int,
@Json(name = "last_seen_status") val lastSeenStatus: String?,
@Json(name = "photo_50") val photo50: String?,
@Json(name = "calls_id") val callsId: String
) {
fun mapToDomain(): VkContactDomain = VkContactDomain(
name = name,
userId = userId
)
}
@@ -0,0 +1,144 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.PeerType
import com.meloda.app.fast.model.api.domain.VkConversation
import com.meloda.app.fast.model.api.domain.VkMessage
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkConversationData(
@Json(name = "peer") val peer: Peer,
@Json(name = "last_message_id") val lastMessageId: Int?,
@Json(name = "in_read") val inRead: Int,
@Json(name = "out_read") val outRead: Int,
@Json(name = "in_read_cmid") val inReadConversationMessageId: Int,
@Json(name = "out_read_cmid") val outReadConversationMessageId: Int,
@Json(name = "sort_id") val sortId: SortId,
@Json(name = "last_conversation_message_id") val lastConversationMessageId: Int,
@Json(name = "is_marked_unread") val isMarkedUnread: Boolean,
@Json(name = "important") val important: Boolean,
@Json(name = "push_settings") val pushSettings: PushSettings?,
@Json(name = "can_write") val canWrite: CanWrite,
@Json(name = "can_send_money") val canSendMoney: Boolean = false,
@Json(name = "can_receive_money") val canReceiveMoney: Boolean = false,
@Json(name = "chat_settings") val chatSettings: ChatSettings?,
@Json(name = "call_in_progress") val callInProgress: CallInProgress?,
@Json(name = "unread_count") val unreadCount: Int?,
) {
@JsonClass(generateAdapter = true)
data class Peer(
@Json(name = "id") val id: Int,
@Json(name = "type") val type: String,
@Json(name = "local_id") val localId: Int,
)
@JsonClass(generateAdapter = true)
data class SortId(
@Json(name = "major_id") val majorId: Int,
@Json(name = "minor_id") val minorId: Int,
)
@JsonClass(generateAdapter = true)
data class PushSettings(
@Json(name = "disabled_forever") val disabledForever: Boolean,
@Json(name = "no_sound") val noSound: Boolean,
@Json(name = "disabled_mentions") val disabledMentions: Boolean,
@Json(name = "disabled_mass_mentions") val disabledMassMentions: Boolean,
)
@JsonClass(generateAdapter = true)
data class CanWrite(
@Json(name = "allowed") val allowed: Boolean,
)
@JsonClass(generateAdapter = true)
data class ChatSettings(
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "title") val title: String,
@Json(name = "state") val state: String,
@Json(name = "acl") val acl: Acl,
@Json(name = "members_count") val membersCount: Int?,
@Json(name = "friends_count") val friendsCount: Int?,
@Json(name = "photo") val photo: Photo?,
@Json(name = "admin_ids") val adminIds: List<Int> = emptyList(),
@Json(name = "active_ids") val activeIds: List<Int> = emptyList(),
@Json(name = "is_group_channel") val isGroupChannel: Boolean = false,
@Json(name = "is_disappearing") val isDisappearing: Boolean = false,
@Json(name = "is_service") val isService: Boolean = false,
@Json(name = "theme") val theme: String?,
@Json(name = "pinned_message") val pinnedMessage: VkPinnedMessageData?,
) {
@JsonClass(generateAdapter = true)
data class Acl(
@Json(name = "can_change_info") val canChangeInfo: Boolean,
@Json(name = "can_change_invite_link") val canChangeInviteLink: Boolean,
@Json(name = "can_change_pin") val canChangePin: Boolean,
@Json(name = "can_invite") val canInvite: Boolean,
@Json(name = "can_promote_users") val canPromoteUsers: Boolean,
@Json(name = "can_see_invite_link") val canSeeInviteLink: Boolean,
@Json(name = "can_moderate") val canModerate: Boolean,
@Json(name = "can_copy_chat") val canCopyChat: Boolean,
@Json(name = "can_call") val canCall: Boolean,
@Json(name = "can_use_mass_mentions") val canUseMassMentions: Boolean,
@Json(name = "can_change_style") val canChangeStyle: Boolean,
)
@JsonClass(generateAdapter = true)
data class Photo(
@Json(name = "photo_50") val photo50: String?,
@Json(name = "photo_100") val photo100: String?,
@Json(name = "photo_200") val photo200: String?,
@Json(name = "is_default_photo") val isDefaultPhoto: Boolean,
)
}
@JsonClass(generateAdapter = true)
data class CallInProgress(
@Json(name = "participants") val participants: Participants,
@Json(name = "join_link") val joinLink: String,
) {
@JsonClass(generateAdapter = true)
data class Participants(
@Json(name = "list") val list: List<Int>,
@Json(name = "count") val count: Int,
)
}
fun asDomain(
lastMessage: VkMessage? = null,
): VkConversation = VkConversation(
id = peer.id,
localId = peer.localId,
title = chatSettings?.title,
photo50 = chatSettings?.photo?.photo50,
photo100 = chatSettings?.photo?.photo100,
photo200 = chatSettings?.photo?.photo200,
isCallInProgress = callInProgress != null,
isPhantom = chatSettings?.isDisappearing == true,
lastConversationMessageId = lastConversationMessageId,
inRead = inRead,
outRead = outRead,
lastMessageId = lastMessageId,
unreadCount = unreadCount ?: 0,
membersCount = chatSettings?.membersCount,
ownerId = chatSettings?.ownerId,
majorId = sortId.majorId,
minorId = sortId.minorId,
canChangePin = chatSettings?.acl?.canChangePin == true,
canChangeInfo = chatSettings?.acl?.canChangeInfo == true,
pinnedMessageId = chatSettings?.pinnedMessage?.id,
inReadCmId = inReadConversationMessageId,
outReadCmId = outReadConversationMessageId,
interactionType = -1,
interactionIds = emptyList(),
peerType = PeerType.parse(peer.type),
lastMessage = lastMessage,
pinnedMessage = chatSettings?.pinnedMessage?.mapToDomain(),
user = null,
group = null,
)
}
@@ -0,0 +1,25 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkCuratorDomain
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkCuratorData(
val id: Int,
val name: String,
val description: String,
val url: String,
val photo: List<Photo>
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class Photo(
val height: Int,
val url: String,
val width: String
)
fun toDomain() = VkCuratorDomain(
id = id
)
}
@@ -0,0 +1,20 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkEventDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkEventData(
@Json(name = "button_text") val buttonText: String,
@Json(name = "id") val id: Int,
@Json(name = "is_favorite") val isFavorite: Boolean,
@Json(name = "text") val text: String,
@Json(name = "address") val address: String,
@Json(name = "friends") val friends: List<Int> = emptyList(),
@Json(name = "member_status") val memberStatus: Int,
@Json(name = "time") val time: Int
) : VkAttachmentData {
fun toDomain() = VkEventDomain(id = id)
}
@@ -0,0 +1,60 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkFileDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkFileData(
@Json(name = "id") val id: Int,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "title") val title: String,
@Json(name = "size") val size: Int,
@Json(name = "ext") val extension: String,
@Json(name = "date") val date: Int,
@Json(name = "type") val type: Int,
@Json(name = "url") val url: String,
@Json(name = "preview") val preview: Preview?,
@Json(name = "ic_licensed") val isLicensed: Int?,
@Json(name = "access_key") val accessKey: String?,
@Json(name = "web_preview_url") val webPreviewUrl: String?
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class Preview(
val photo: Photo?,
val video: Video?
) {
@JsonClass(generateAdapter = true)
data class Photo(val sizes: List<Size>) {
@JsonClass(generateAdapter = true)
data class Size(
val height: Int,
val width: Int,
val type: String,
val src: String
)
}
@JsonClass(generateAdapter = true)
data class Video(
@Json(name = "src") val src: String,
@Json(name = "width") val width: Int,
@Json(name = "height") val height: Int,
@Json(name = "file_size") val fileSize: Int
)
}
fun toDomain() = VkFileDomain(
id = id,
ownerId = ownerId,
title = title,
ext = extension,
url = url,
size = size,
accessKey = accessKey,
preview = preview
)
}
@@ -0,0 +1,21 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkGiftDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkGiftData(
@Json(name = "id") val id: Int,
@Json(name = "thumb_256") val thumb256: String?,
@Json(name = "thumb_96") val thumb96: String?,
@Json(name = "thumb_48") val thumb48: String
) {
fun toDomain() = VkGiftDomain(
id = id,
thumb256 = thumb256,
thumb96 = thumb96,
thumb48 = thumb48
)
}
@@ -0,0 +1,25 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkGraffitiDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkGraffitiData(
@Json(name = "id") val id: Int,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "url") val url: String,
@Json(name = "width") val width: Int,
@Json(name = "height") val height: Int,
@Json(name = "access_key") val accessKey: String
) {
fun toDomain() = VkGraffitiDomain(
id = id,
ownerId = ownerId,
url = url,
width = width,
height = height,
accessKey = accessKey
)
}
@@ -0,0 +1,21 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkGroupCallDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkGroupCallData(
@Json(name = "initiator_id") val initiatorId: Int,
@Json(name = "join_link") val joinLink: String,
@Json(name = "participants") val participants: Participants
) {
@JsonClass(generateAdapter = true)
data class Participants(
val list: List<Int>,
val count: Int
)
fun toDomain() = VkGroupCallDomain(initiatorId = initiatorId)
}
@@ -0,0 +1,33 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkGroupDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import kotlin.math.abs
@JsonClass(generateAdapter = true)
data class VkGroupData(
@Json(name = "id") val id: Int,
@Json(name = "name") val name: String,
@Json(name = "screen_name") val screenName: String,
@Json(name = "is_closed") val isClosed: Int,
@Json(name = "type") val type: String,
@Json(name = "is_admin") val isAdmin: Int,
@Json(name = "is_member") val isMember: Int,
@Json(name = "is_advertiser") val isAdvertiser: Int,
@Json(name = "photo_50") val photo50: String?,
@Json(name = "photo_100") val photo100: String?,
@Json(name = "photo_200") val photo200: String?,
@Json(name = "members_count") val membersCount: Int?
) {
fun mapToDomain() = VkGroupDomain(
id = abs(id),
name = name,
screenName = screenName,
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
membersCount = membersCount
)
}
@@ -0,0 +1,25 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkLinkDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkLinkData(
@Json(name = "url") val url: String,
@Json(name = "title") val title: String?,
@Json(name = "caption") val caption: String?,
@Json(name = "photo") val photo: VkPhotoData?,
@Json(name = "target") val target: String?,
@Json(name = "is_favorite") val isFavorite: Boolean?
) : VkAttachmentData {
fun toDomain() = VkLinkDomain(
url = url,
title = title,
caption = caption,
photo = photo?.toDomain(),
target = target,
isFavorite = isFavorite == true
)
}
@@ -0,0 +1,12 @@
package com.meloda.app.fast.model.api.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkLongPollData(
@Json(name = "server") val server: String,
@Json(name = "key") val key: String,
@Json(name = "ts") val ts: Int,
@Json(name = "pts") val pts: Int
)
@@ -0,0 +1,208 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkAttachment
import com.meloda.app.fast.model.api.domain.VkMessage
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkMessageData(
@Json(name = "id") val id: Int?,
@Json(name = "peer_id") val peerId: Int?,
@Json(name = "date") val date: Int,
@Json(name = "from_id") val fromId: Int,
@Json(name = "out") val out: Int?,
@Json(name = "text") val text: String,
@Json(name = "conversation_message_id") val conversationMessageId: Int,
@Json(name = "fwd_messages") val fwdMessages: List<VkMessageData>? = emptyList(),
@Json(name = "important") val important: Boolean = false,
@Json(name = "random_id") val randomId: Int = 0,
@Json(name = "attachments") val attachments: List<VkAttachmentItemData> = emptyList(),
@Json(name = "is_hidden") val isHidden: Boolean = false,
@Json(name = "payload") val payload: String?,
@Json(name = "geo") val geo: Geo?,
@Json(name = "action") val action: Action?,
@Json(name = "ttl") val ttl: Int?,
@Json(name = "reply_message") val replyMessage: VkMessageData?,
@Json(name = "update_time") val updateTime: Int?
) {
@JsonClass(generateAdapter = true)
data class Geo(
@Json(name = "type") val type: String,
@Json(name = "coordinates") val coordinates: Coordinates,
@Json(name = "place") val place: Place
) {
@JsonClass(generateAdapter = true)
data class Coordinates(
@Json(name = "latitude") val latitude: Float,
@Json(name = "longitude") val longitude: Float
)
@JsonClass(generateAdapter = true)
data class Place(
@Json(name = "country") val country: String,
@Json(name = "city") val city: String,
@Json(name = "title") val title: String
)
}
@JsonClass(generateAdapter = true)
data class Action(
@Json(name = "type") val type: String,
@Json(name = "member_id") val memberId: Int?,
@Json(name = "text") val text: String?,
@Json(name = "conversation_message_id") val conversationMessageId: Int?,
@Json(name = "message") val message: String?
)
}
fun VkMessageData.asDomain(): VkMessage = VkMessage(
id = id ?: -1,
text = text.ifBlank { null },
isOut = out == 1,
peerId = peerId ?: -1,
fromId = fromId,
date = date,
randomId = randomId,
action = VkMessage.Action.parse(action?.type),
actionMemberId = action?.memberId,
actionText = action?.text,
actionConversationMessageId = action?.conversationMessageId,
actionMessage = action?.message,
geoType = geo?.type,
important = important,
updateTime = updateTime,
forwards = fwdMessages.orEmpty().map(VkMessageData::asDomain),
attachments = parseAttachments(),
replyMessage = replyMessage?.asDomain(),
user = null,
group = null,
actionUser = null,
actionGroup = null,
)
private fun VkMessageData.parseAttachments(): List<VkAttachment> {
if (attachments.isEmpty()) return emptyList()
val attachments = mutableListOf<VkAttachment>()
for (baseAttachment in this.attachments) {
when (baseAttachment.getPreparedType()) {
AttachmentType.UNKNOWN -> continue
AttachmentType.PHOTO -> {
val photo = baseAttachment.photo ?: continue
attachments += photo.toDomain()
}
AttachmentType.VIDEO -> {
val video = baseAttachment.video ?: continue
attachments += video.toDomain()
}
AttachmentType.AUDIO -> {
val audio = baseAttachment.audio ?: continue
attachments += audio.toDomain()
}
AttachmentType.FILE -> {
val file = baseAttachment.file ?: continue
attachments += file.toDomain()
}
AttachmentType.LINK -> {
val link = baseAttachment.link ?: continue
attachments += link.toDomain()
}
AttachmentType.MINI_APP -> {
val miniApp = baseAttachment.miniApp ?: continue
attachments += miniApp.toDomain()
}
AttachmentType.AUDIO_MESSAGE -> {
val voiceMessage = baseAttachment.voiceMessage ?: continue
attachments += voiceMessage.toDomain()
}
AttachmentType.STICKER -> {
val sticker = baseAttachment.sticker ?: continue
attachments += sticker.toDomain()
}
AttachmentType.GIFT -> {
val gift = baseAttachment.gift ?: continue
attachments += gift.toDomain()
}
AttachmentType.WALL -> {
val wall = baseAttachment.wall ?: continue
attachments += wall.toDomain()
}
AttachmentType.GRAFFITI -> {
val graffiti = baseAttachment.graffiti ?: continue
attachments += graffiti.toDomain()
}
AttachmentType.POLL -> {
val poll = baseAttachment.poll ?: continue
attachments += poll.toDomain()
}
AttachmentType.WALL_REPLY -> {
val wallReply = baseAttachment.wallReply ?: continue
attachments += wallReply.toDomain()
}
AttachmentType.CALL -> {
val call = baseAttachment.call ?: continue
attachments += call.toDomain()
}
AttachmentType.GROUP_CALL_IN_PROGRESS -> {
val groupCall = baseAttachment.groupCall ?: continue
attachments += groupCall.toDomain()
}
AttachmentType.CURATOR -> {
val curator = baseAttachment.curator ?: continue
attachments += curator.toDomain()
}
AttachmentType.EVENT -> {
val event = baseAttachment.event ?: continue
attachments += event.toDomain()
}
AttachmentType.STORY -> {
val story = baseAttachment.story ?: continue
attachments += story.toDomain()
}
AttachmentType.WIDGET -> {
val widget = baseAttachment.widget ?: continue
attachments += widget.toDomain()
}
AttachmentType.ARTIST -> {
val artist = baseAttachment.artist ?: continue
attachments += artist.toDomain()
val audios = baseAttachment.audios ?: continue
audios.map(VkAudioData::toDomain).let(attachments::addAll)
}
AttachmentType.AUDIO_PLAYLIST -> {
val audioPlaylist = baseAttachment.audioPlaylist ?: continue
attachments += audioPlaylist.toDomain()
}
AttachmentType.PODCAST -> {
val podcast = baseAttachment.podcast ?: continue
attachments += podcast.toDomain()
}
}
}
return attachments
}
@@ -0,0 +1,40 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkMiniAppDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkMiniAppData(
@Json(name = "title") val title: String,
@Json(name = "description") val description: String,
@Json(name = "app") val app: App,
@Json(name = "images") val images: List<Image>?,
@Json(name = "button_text") val buttonText: String
) {
@JsonClass(generateAdapter = true)
data class App(
@Json(name = "type") val type: String,
@Json(name = "id") val id: Int,
@Json(name = "title") val title: String,
@Json(name = "author_owner_id") val authorOwnerId: Int,
@Json(name = "is_favorite") val isFavorite: Boolean,
@Json(name = "share_url") val shareUrl: String,
@Json(name = "webview_url") val webViewUrl: String,
@Json(name = "icon_75") val icon75: String?,
@Json(name = "icon_139") val icon139: String?,
@Json(name = "icon_150") val icon150: String?,
@Json(name = "icon_278") val icon278: String?,
@Json(name = "icon_576") val icon576: String?,
)
@JsonClass(generateAdapter = true)
data class Image(
@Json(name = "height") val height: Int,
@Json(name = "width") val width: Int,
@Json(name = "url") val url: String
)
fun toDomain() = VkMiniAppDomain(link = app.shareUrl)
}
@@ -0,0 +1,42 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkPhotoDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkPhotoData(
@Json(name = "album_id") val albumId: Int,
val date: Int,
val id: Int,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "has_tags") val hasTags: Boolean,
@Json(name = "access_key") val accessKey: String?,
val sizes: List<Size>,
val text: String?,
@Json(name = "user_id") val userId: Int?,
val lat: Double?,
val long: Double?,
@Json(name = "post_id") val postId: Int?
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class Size(
val height: Int,
val width: Int,
val type: String,
val url: String
)
fun toDomain() = VkPhotoDomain(
albumId = albumId,
date = date,
id = id,
ownerId = ownerId,
hasTags = hasTags,
accessKey = accessKey,
sizes = sizes,
text = text,
userId = userId
)
}
@@ -0,0 +1,56 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkMessage
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkPinnedMessageData(
@Json(name = "id") val id: Int?,
@Json(name = "peer_id") val peerId: Int?,
@Json(name = "date") val date: Int,
@Json(name = "from_id") val fromId: Int,
@Json(name = "out") val out: Boolean?,
@Json(name = "text") val text: String,
@Json(name = "conversation_message_id") val conversationMessageId: Int,
@Json(name = "fwd_messages") val forwards: List<VkMessageData>?,
@Json(name = "important") val important: Boolean = false,
@Json(name = "random_id") val randomId: Int = 0,
@Json(name = "attachments") val attachments: List<VkAttachmentItemData>?,
@Json(name = "is_hidden") val isHidden: Boolean = false,
@Json(name = "payload") val payload: String?,
@Json(name = "geo") val geo: VkMessageData.Geo?,
@Json(name = "action") val action: VkMessageData.Action?,
@Json(name = "ttl") val ttl: Int?,
@Json(name = "reply_message") val replyMessage: VkMessageData?,
@Json(name = "update_time") val updateTime: Int?
) {
fun mapToDomain(): VkMessage = VkMessage(
id = id ?: -1,
text = text.ifBlank { null },
isOut = out == true,
peerId = peerId ?: -1,
fromId = fromId,
date = date,
randomId = randomId,
action = VkMessage.Action.parse(action?.type),
actionMemberId = action?.memberId,
actionText = action?.text,
actionConversationMessageId = action?.conversationMessageId,
actionMessage = action?.message,
geoType = geo?.type,
important = important,
updateTime = updateTime,
forwards = forwards.orEmpty().map(VkMessageData::asDomain),
// TODO: 05/05/2024, Danil Nikolaev: parse attachments
attachments = emptyList(),
replyMessage = replyMessage?.asDomain(),
user = null,
group = null,
actionUser = null,
actionGroup = null,
)
}
@@ -0,0 +1,20 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkPodcastDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkPodcastData(
@Json(name = "id") val id: Int,
@Json(name = "title") val title: String,
@Json(name = "artist") val artist: String,
// ... other fields
) : VkAttachmentData {
fun toDomain(): VkPodcastDomain = VkPodcastDomain(
id = id,
title = title,
artist = artist
)
}
@@ -0,0 +1,62 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkPollDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkPollData(
val multiple: Boolean,
val id: Int,
val votes: Int,
val anonymous: Boolean?,
val closed: Boolean,
@Json(name = "end_date") val endDate: Int,
@Json(name = "is_board") val isBoard: Boolean,
@Json(name = "can_vote") val canVote: Boolean,
@Json(name = "can_edit") val canEdit: Boolean,
@Json(name = "can_report") val canReport: Boolean,
@Json(name = "can_share") val canShare: Boolean,
val created: Int,
@Json(name = "owner_id") val ownerId: Int,
val question: String,
@Json(name = "disable_unvote") val disableUnvote: Boolean,
val friends: List<Friend>?,
@Json(name = "embed_hash") val embedHash: String,
val answers: List<Answer>,
@Json(name = "author_id") val authorId: Int?,
val background: Background?
) {
@JsonClass(generateAdapter = true)
data class Friend(
val id: Int
)
@JsonClass(generateAdapter = true)
data class Answer(
val id: Int,
val rate: Double,
val text: String,
val votes: Int
)
@JsonClass(generateAdapter = true)
data class Background(
val angle: Int,
val color: String,
val id: Int,
val name: String,
val type: String,
val points: List<Point>
) {
@JsonClass(generateAdapter = true)
data class Point(
val color: String,
val position: Double
)
}
fun toDomain() = VkPollDomain(id = id)
}
@@ -0,0 +1,36 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkStickerDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkStickerData(
@Json(name = "product_id") val productId: Int,
@Json(name = "sticker_id") val stickerId: Int,
@Json(name = "images") val images: List<Image>,
@Json(name = "images_with_background") val imagesWithBackground: List<Image>,
@Json(name = "animation_url") val animationUrl: String?,
@Json(name = "animations") val animations: List<Animation>?
) {
@JsonClass(generateAdapter = true)
data class Image(
@Json(name = "width") val width: Int,
@Json(name = "height") val height: Int,
@Json(name = "url") val url: String
)
@JsonClass(generateAdapter = true)
data class Animation(
@Json(name = "type") val type: String,
@Json(name = "url") val url: String
)
fun toDomain() = VkStickerDomain(
id = stickerId,
productId = productId,
images = images,
backgroundImages = imagesWithBackground
)
}
@@ -0,0 +1,41 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkStoryDomain
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkStoryData(
val id: Int,
val owner_id: Int,
val access_key: String?,
val can_comment: Int?,
val can_reply: Int?,
val can_like: Boolean?,
val can_share: Int?,
val can_hide: Int?,
val date: Int,
val expires_at: Int,
val is_ads: Boolean?,
val photo: VkPhotoData?,
val replies: Replies?,
val is_one_time: Boolean?,
val track_code: String?,
val type: String?,
val views: Int?,
val likes_count: Int?,
val is_restricted: Boolean?,
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class Replies(
val count: Int,
val new: Int?
)
fun toDomain() = VkStoryDomain(
id = id,
ownerId = owner_id,
date = date,
photo = photo?.toDomain()
)
}
@@ -0,0 +1,59 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.OnlineStatus
import com.meloda.app.fast.model.api.domain.VkUser
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkUserData(
@Json(name = "id") val id: Int,
@Json(name = "first_name") val firstName: String,
@Json(name = "last_name") val lastName: String,
@Json(name = "can_access_closed") val canAccessClosed: Boolean,
@Json(name = "is_closed") val isClosed: Boolean,
@Json(name = "can_invite_to_chats") val canInviteToChats: Boolean = false,
@Json(name = "sex") val sex: Int?,
@Json(name = "photo_50") val photo50: String?,
@Json(name = "photo_100") val photo100: String?,
@Json(name = "photo_200") val photo200: String?,
@Json(name = "online") val online: Int?,
@Json(name = "online_info") val onlineInfo: OnlineInfo?,
@Json(name = "screen_name") val screenName: String,
@Json(name = "bdate") val birthday: String?
//...other fields
) {
@JsonClass(generateAdapter = true)
data class OnlineInfo(
@Json(name = "visible") val visible: Boolean,
@Json(name = "status") val status: String?,
@Json(name = "last_seen") val lastSeen: Int?,
@Json(name = "is_online") val isOnline: Boolean?,
@Json(name = "online_mobile") val onlineMobile: Boolean?,
@Json(name = "app_id") val appId: Int?
)
fun mapToDomain() = VkUser(
id = id,
firstName = firstName,
lastName = lastName,
// TODO: 05/05/2024, Danil Nikolaev: improve
onlineStatus = when {
online != 1 -> OnlineStatus.Offline
onlineInfo?.onlineMobile == true -> {
OnlineStatus.OnlineMobile(appId = onlineInfo.appId)
}
else -> {
OnlineStatus.Online(appId = onlineInfo?.appId)
}
},
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
lastSeen = onlineInfo?.lastSeen,
lastSeenStatus = onlineInfo?.status,
birthday = birthday
)
}
@@ -0,0 +1,75 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkVideoDomain
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkVideoData(
val id: Int,
val title: String,
val width: Int?,
val height: Int?,
val duration: Int,
val date: Int,
val comments: Int?,
val description: String,
val player: String?,
val added: Int?,
val type: String,
val views: Int,
val access_key: String?,
val owner_id: Int,
val is_favorite: Boolean?,
val image: List<Image>,
val first_frame: List<FirstFrame>?,
val files: File?,
) : VkAttachmentData {
@JsonClass(generateAdapter = true)
data class Image(
val width: Int,
val height: Int,
val url: String,
val with_padding: Int?
) {
fun asVideoImage() = VkVideoDomain.VideoImage(
width = width,
height = height,
url = url,
withPadding = with_padding == 1
)
}
@JsonClass(generateAdapter = true)
data class FirstFrame(
val height: Int,
val width: Int,
val url: String
)
@JsonClass(generateAdapter = true)
data class File(
val mp4_240: String?,
val mp4_360: String?,
val mp4_480: String?,
val mp4_720: String?,
val mp4_1080: String?,
val mp4_1440: String?,
val hls: String?,
val dash_uni: String?,
val dash_sep: String?,
val hls_ondemand: String?,
val dash_ondemand: String?,
val failover_host: String?
)
fun toDomain() = VkVideoDomain(
id = id,
ownerId = owner_id,
images = image.map { it.asVideoImage() },
firstFrames = first_frame,
accessKey = access_key,
title = title
)
}
@@ -0,0 +1,71 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkWallDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkWallData(
@Json(name = "id") val id: Int,
@Json(name = "from_id") val from_id: Int,
@Json(name = "to_id") val to_id: Int,
@Json(name = "date") val date: Int,
@Json(name = "text") val text: String,
@Json(name = "attachments") val attachments: List<VkAttachmentItemData>?,
@Json(name = "post_source") val post_source: PostSource?,
@Json(name = "comments") val comments: Comments?,
@Json(name = "likes") val likes: Likes?,
@Json(name = "reposts") val reposts: Reposts?,
@Json(name = "views") val views: Views?,
@Json(name = "is_favorite") val is_favorite: Boolean,
@Json(name = "donut") val donut: Donut?,
@Json(name = "access_key") val access_key: String?,
@Json(name = "short_text_rate") val short_text_rate: Double?
) {
@JsonClass(generateAdapter = true)
data class PostSource(
val type: String,
val platform: String?
)
@JsonClass(generateAdapter = true)
data class Comments(
val count: Int,
)
@JsonClass(generateAdapter = true)
data class Likes(
val count: Int
)
@JsonClass(generateAdapter = true)
data class Reposts(
val count: Int,
)
@JsonClass(generateAdapter = true)
data class Views(
val count: Int
)
@JsonClass(generateAdapter = true)
data class Donut(
val is_donut: Boolean
)
fun toDomain() = VkWallDomain(
id = id,
fromId = from_id,
toId = to_id,
date = date,
text = text,
attachments = attachments,
comments = comments?.count,
likes = likes?.count,
reposts = reposts?.count,
views = views?.count,
isFavorite = is_favorite,
accessKey = access_key
)
}
@@ -0,0 +1,29 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkWallReplyDomain
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkWallReplyData(
val id: Int,
val from_id: Int,
val date: Int,
val text: String,
val post_id: Int,
val owner_id: Int,
val parents_stack: List<Int>,
val likes: Likes,
val reply_to_user: Int?,
val reply_to_comment: Int?
) {
@JsonClass(generateAdapter = true)
data class Likes(
val count: Int,
val can_like: Int,
val user_likes: Int,
val can_publish: Int
)
fun toDomain() = VkWallReplyDomain(id = id)
}
@@ -0,0 +1,12 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkWidgetDomain
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkWidgetData(
val id: Int
) : VkAttachmentData {
fun toDomain() = VkWidgetDomain(id)
}
@@ -0,0 +1,13 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.data.VkArtistData
data class VkArtistDomain(
val id: String,
val name: String,
val photos: List<VkArtistData.PhotoSize>
) : VkAttachment {
override val type: AttachmentType = AttachmentType.ARTIST
}
@@ -0,0 +1,7 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
interface VkAttachment {
val type: AttachmentType get() = AttachmentType.UNKNOWN
}
@@ -0,0 +1,25 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkAudioDomain(
val id: Int,
val ownerId: Int,
val title: String,
val artist: String,
val url: String,
val duration: Int,
val accessKey: String?
) : VkAttachment {
override val type: AttachmentType = AttachmentType.AUDIO
override fun toString(): String {
val result = StringBuilder(type.value).append(ownerId).append('_').append(id)
if (!accessKey.isNullOrBlank()) {
result.append('_')
result.append(accessKey)
}
return result.toString()
}
}
@@ -0,0 +1,18 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkAudioMessageDomain(
val id: Int,
val ownerId: Int,
val duration: Int,
val waveform: List<Int>,
val linkOgg: String,
val linkMp3: String,
val accessKey: String,
val transcriptState: String?,
val transcript: String?
) : VkAttachment {
override val type: AttachmentType = AttachmentType.AUDIO_MESSAGE
}
@@ -0,0 +1,13 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkAudioPlaylistDomain(
val id: Int,
val ownerId: Int,
val title: String,
val description: String,
) : VkAttachment {
override val type: AttachmentType = AttachmentType.AUDIO_PLAYLIST
}
@@ -0,0 +1,15 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkCallDomain(
val initiatorId: Int,
val receiverId: Int,
val state: String,
val time: Int,
val duration: Int,
val isVideo: Boolean
) : VkAttachment {
override val type: AttachmentType = AttachmentType.CALL
}
@@ -0,0 +1,44 @@
package com.meloda.app.fast.model.api.domain
data class VkChatDomain(
val type: String,
val title: String,
val adminId: Int,
val membersCount: Int,
val id: Int,
val members: List<ChatMember> = emptyList(),
val photo50: String,
val photo100: String,
val photo200: String,
val isDefaultPhoto: Boolean
) {
data class ChatMember(
val id: Int,
val type: ChatMemberType,
val isOnline: Boolean?,
val lastSeen: Int?,
val name: String?,
val firstName: String?,
val lastName: String?,
val invitedBy: Int,
val photo50: String?,
val photo100: String?,
val photo200: String?,
val isOwner: Boolean,
val isAdmin: Boolean,
val canKick: Boolean
) {
fun isProfile(): Boolean = type == ChatMemberType.Profile
fun isGroup(): Boolean = type == ChatMemberType.Group
enum class ChatMemberType(val value: String) {
Profile("profile"), Group("group");
companion object {
fun parse(value: String) = entries.first { it.value == value }
}
}
}
}
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
data class VkChatMemberDomain(
val memberId: Int,
val invitedBy: Int,
val joinDate: Int,
val isAdmin: Boolean,
val isOwner: Boolean,
val canKick: Boolean
)
@@ -0,0 +1,6 @@
package com.meloda.app.fast.model.api.domain
data class VkContactDomain(
val name: String,
val userId: Int
)
@@ -0,0 +1,66 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.PeerType
import com.meloda.app.fast.model.database.VkConversationEntity
data class VkConversation(
val id: Int,
val localId: Int,
val ownerId: Int?,
val title: String?,
val photo50: String?,
val photo100: String?,
val photo200: String?,
val isCallInProgress: Boolean,
val isPhantom: Boolean,
val lastConversationMessageId: Int,
val inReadCmId: Int,
val outReadCmId: Int,
val inRead: Int,
val outRead: Int,
val lastMessageId: Int?,
val unreadCount: Int,
val membersCount: Int?,
val canChangePin: Boolean,
val canChangeInfo: Boolean,
val majorId: Int,
val minorId: Int,
val pinnedMessageId: Int?,
val interactionType: Int,
val interactionIds: List<Int>,
val peerType: PeerType,
val lastMessage: VkMessage?,
val pinnedMessage: VkMessage?,
val user: VkUser?,
val group: VkGroupDomain?
) {
fun isPinned(): Boolean = majorId > 0
fun isInUnread() = inRead - (lastMessageId ?: 0) < 0
fun isOutUnread() = outRead - (lastMessageId ?: 0) < 0
}
fun VkConversation.asEntity(): VkConversationEntity = VkConversationEntity(
id = id,
localId = localId,
ownerId = ownerId,
title = title,
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
isPhantom = isPhantom,
lastConversationMessageId = lastConversationMessageId,
inReadCmId = inReadCmId,
outReadCmId = outReadCmId,
inRead = inRead,
outRead = outRead,
lastMessageId = lastMessageId,
unreadCount = unreadCount,
membersCount = membersCount,
canChangePin = canChangePin,
canChangeInfo = canChangeInfo,
majorId = majorId,
minorId = minorId,
pinnedMessageId = pinnedMessageId,
peerType = peerType.value,
)
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkCuratorDomain(
val id: Int,
) : VkAttachment {
override val type: AttachmentType = AttachmentType.CURATOR
}
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkEventDomain(
val id: Int
) : VkAttachment {
override val type: AttachmentType = AttachmentType.EVENT
}
@@ -0,0 +1,29 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.data.VkFileData
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkFileDomain(
val id: Int,
val ownerId: Int,
val title: String,
val ext: String,
val size: Int,
val url: String,
val accessKey: String?,
val preview: VkFileData.Preview?
) : VkAttachment {
override val type: AttachmentType = AttachmentType.FILE
override fun toString(): String {
val result = StringBuilder(type.value).append(ownerId).append('_').append(id)
if (!accessKey.isNullOrBlank()) {
result.append('_')
result.append(accessKey)
}
return result.toString()
}
}
@@ -0,0 +1,13 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkGiftDomain(
val id: Int,
val thumb256: String?,
val thumb96: String?,
val thumb48: String
) : VkAttachment {
override val type: AttachmentType = AttachmentType.GIFT
}
@@ -0,0 +1,15 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkGraffitiDomain(
val id: Int,
val ownerId: Int,
val url: String,
val width: Int,
val height: Int,
val accessKey: String
) : VkAttachment {
override val type: AttachmentType = AttachmentType.GRAFFITI
}
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkGroupCallDomain(
val initiatorId: Int
) : VkAttachment {
override val type: AttachmentType = AttachmentType.GROUP_CALL_IN_PROGRESS
}
@@ -0,0 +1,26 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.database.VkGroupEntity
data class VkGroupDomain(
val id: Int,
val name: String,
val screenName: String,
val photo50: String?,
val photo100: String?,
val photo200: String?,
val membersCount: Int?
) {
override fun toString() = name.trim()
fun mapToDB(): VkGroupEntity = VkGroupEntity(
id = id,
name = name,
screenName = screenName,
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
membersCount = membersCount
)
}
@@ -0,0 +1,15 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkLinkDomain(
val url: String,
val title: String?,
val caption: String?,
val photo: VkPhotoDomain?,
val target: String?,
val isFavorite: Boolean
) : VkAttachment {
override val type: AttachmentType = AttachmentType.LINK
}
@@ -0,0 +1,99 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.database.VkMessageEntity
data class VkMessage(
val id: Int,
val text: String?,
val isOut: Boolean,
val peerId: Int,
val fromId: Int,
val date: Int,
val randomId: Int,
val action: Action?,
val actionMemberId: Int?,
val actionText: String?,
val actionConversationMessageId: Int?,
val actionMessage: String?,
val updateTime: Int?,
val important: Boolean = false,
val forwards: List<VkMessage>?,
val attachments: List<VkAttachment>?,
val replyMessage: VkMessage?,
val geoType: String?,
val user: VkUser?,
val group: VkGroupDomain?,
val actionUser: VkUser?,
val actionGroup: VkGroupDomain?
) {
fun isPeerChat() = peerId > 2_000_000_000
fun isUser() = fromId > 0
fun isGroup() = fromId < 0
fun isRead(conversation: VkConversation) =
if (isOut) {
conversation.outRead - id >= 0
} else {
conversation.inRead - id >= 0
}
fun hasAttachments(): Boolean = attachments.orEmpty().isNotEmpty()
fun hasReply(): Boolean = replyMessage != null
fun hasForwards(): Boolean = !forwards.isNullOrEmpty()
fun hasGeo(): Boolean = geoType != null
fun isUpdated(): Boolean = updateTime != null && updateTime > 0
enum class Action(val value: String) {
CHAT_CREATE("chat_create"),
CHAT_PHOTO_UPDATE("chat_photo_update"),
CHAT_PHOTO_REMOVE("chat_photo_remove"),
CHAT_TITLE_UPDATE("chat_title_update"),
CHAT_PIN_MESSAGE("chat_pin_message"),
CHAT_UNPIN_MESSAGE("chat_unpin_message"),
CHAT_INVITE_USER("chat_invite_user"),
CHAT_INVITE_USER_BY_LINK("chat_invite_user_by_link"),
CHAT_KICK_USER("chat_kick_user"),
CHAT_SCREENSHOT("chat_screenshot"),
CHAT_INVITE_USER_BY_CALL("chat_invite_user_by_call"),
CHAT_INVITE_USER_BY_CALL_LINK("chat_invite_user_by_call_join_link"),
CHAT_STYLE_UPDATE("conversation_style_update");
companion object {
fun parse(value: String?): Action? = entries.firstOrNull { it.value == value }
}
}
}
fun VkMessage.asEntity(): VkMessageEntity = VkMessageEntity(
id = id,
text = text,
isOut = isOut,
peerId = peerId,
fromId = fromId,
date = date,
randomId = randomId,
action = action?.value,
actionMemberId = actionMemberId,
actionText = actionText,
actionConversationMessageId = actionConversationMessageId,
actionMessage = actionMessage,
updateTime = updateTime,
important = important,
forwardIds = forwards.orEmpty().map(VkMessage::id),
// TODO: 05/05/2024, Danil Nikolaev: save attachments
attachments = emptyList(),
replyMessageId = replyMessage?.id,
geoType = geoType
)
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkMiniAppDomain(
val link: String
) : VkAttachment {
override val type: AttachmentType = AttachmentType.MINI_APP
}
@@ -0,0 +1,92 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.data.VkPhotoData
import java.util.Stack
// TODO: 11/04/2024, Danil Nikolaev: review
data class VkPhotoDomain(
val albumId: Int,
val date: Int,
val id: Int,
val ownerId: Int,
val hasTags: Boolean,
val accessKey: String?,
val sizes: List<VkPhotoData.Size>,
val text: String?,
val userId: Int?
) : VkAttachment {
override val type: AttachmentType = AttachmentType.PHOTO
private val sizesChars = Stack<Char>()
init {
sizesChars.push(SIZE_TYPE_75)
sizesChars.push(SIZE_TYPE_130)
sizesChars.push(SIZE_TYPE_604)
sizesChars.push('o')
sizesChars.push('p')
sizesChars.push('q')
sizesChars.push('r')
sizesChars.push(SIZE_TYPE_807)
sizesChars.push(SIZE_TYPE_1080_1024)
sizesChars.push(SIZE_TYPE_2560_2048)
}
fun getMaxSize(): VkPhotoData.Size? {
return getSizeOrSmaller(sizesChars.peek())
}
fun getSizeOrNull(type: Char): VkPhotoData.Size? {
for (size in sizes) {
if (size.type == type.toString()) return size
}
return null
}
fun getSizeOrSmaller(type: Char): VkPhotoData.Size? {
val photoStack = sizesChars.clone() as Stack<*>
val sizeIndex = photoStack.search(type)
if (sizeIndex == -1) return null
for (i in 0 until sizeIndex) {
photoStack.pop()
}
for (i in 0 until photoStack.size) {
val size = getSizeOrNull(photoStack.peek() as Char)
if (size == null) {
photoStack.pop()
continue
} else {
return size
}
}
return null
}
companion object {
const val SIZE_TYPE_75 = 's'
const val SIZE_TYPE_130 = 'm'
const val SIZE_TYPE_604 = 'x'
const val SIZE_TYPE_807 = 'y'
const val SIZE_TYPE_1080_1024 = 'z'
const val SIZE_TYPE_2560_2048 = 'w'
}
override fun toString(): String {
val result = StringBuilder(type.value).append(ownerId).append('_').append(id)
if (!accessKey.isNullOrBlank()) {
result.append('_')
result.append(accessKey)
}
return result.toString()
}
}
@@ -0,0 +1,11 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkPodcastDomain(
val id: Int,
val title: String,
val artist: String
) : VkAttachment {
override val type: AttachmentType = AttachmentType.PODCAST
}
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkPollDomain(
val id: Int
) : VkAttachment {
override val type: AttachmentType = AttachmentType.POLL
}
@@ -0,0 +1,24 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.data.VkStickerData
data class VkStickerDomain(
val id: Int,
val productId: Int,
val images: List<VkStickerData.Image>,
val backgroundImages: List<VkStickerData.Image>
) : VkAttachment {
override val type: AttachmentType = AttachmentType.STICKER
val className: String = this::class.java.name
fun urlForSize(size: Int): String? {
for (image in images) {
if (image.width == size) return image.url
}
return null
}
}
@@ -0,0 +1,13 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkStoryDomain(
val id: Int,
val ownerId: Int,
val date: Int,
val photo: VkPhotoDomain?
) : VkAttachment {
override val type: AttachmentType = AttachmentType.STORY
}
@@ -0,0 +1,44 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.database.VkUserEntity
data class VkUser(
val id: Int,
val firstName: String,
val lastName: String,
val onlineStatus: OnlineStatus,
val photo50: String?,
val photo100: String?,
val photo200: String?,
val lastSeen: Int?,
val lastSeenStatus: String?,
val birthday: String?,
) {
override fun toString() = fullName
val fullName get() = "$firstName $lastName".trim()
}
sealed class OnlineStatus(open val appId: Int?) {
data class Online(override val appId: Int?) : OnlineStatus(appId)
data class OnlineMobile(override val appId: Int?) : OnlineStatus(appId)
data object Offline : OnlineStatus(null)
fun isOnline(): Boolean = this is Online || this is OnlineMobile
fun isMobile(): Boolean = this is OnlineMobile
}
fun VkUser.asEntity(): VkUserEntity = VkUserEntity(
id = id,
firstName = firstName,
lastName = lastName,
isOnline = onlineStatus.isOnline(),
isOnlineMobile = onlineStatus.isMobile(),
onlineAppId = onlineStatus.appId,
lastSeen = lastSeen,
lastSeenStatus = lastSeenStatus,
birthday = birthday,
photo50 = photo50,
photo100 = photo100,
photo200 = photo200
)
@@ -0,0 +1,88 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.data.VkVideoData
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkVideoDomain(
val id: Int,
val ownerId: Int,
val images: List<VideoImage>,
val firstFrames: List<VkVideoData.FirstFrame>?,
val accessKey: String?,
val title: String,
) : VkAttachment {
override val type: AttachmentType = AttachmentType.VIDEO
fun imageForWidth(width: Int): VideoImage? {
return images.find { it.width == width }
}
fun imageForWidthAtLeast(width: Int): VideoImage? {
var certainImages = images.sortedByDescending { it.width }
var containsVertical = false
for (image in images) {
if (image.shapeKind == ShapeKind.Vertical) {
containsVertical = true
break
}
}
if (containsVertical) {
certainImages = certainImages.filter { it.shapeKind == ShapeKind.Vertical }
}
certainImages = certainImages.filter { it.width >= width }
return certainImages.firstOrNull()
}
@JsonClass(generateAdapter = true)
data class VideoImage(
val width: Int,
val height: Int,
val url: String,
val withPadding: Boolean,
) {
var shapeKind: ShapeKind? = null
init {
val ratio = width.toFloat() / height.toFloat()
shapeKind = when {
ratio > 1 -> ShapeKind.Horizontal
ratio < 1 -> ShapeKind.Vertical
else -> ShapeKind.Square
}
}
}
sealed class ShapeKind(val value: Int) {
data object Square : ShapeKind(0)
data object Vertical : ShapeKind(1)
data object Horizontal : ShapeKind(2)
companion object {
fun parse(value: Int) = when (value) {
0 -> Square
1 -> Vertical
2 -> Horizontal
else -> throw IllegalArgumentException("Unknown value: $value")
}
}
}
override fun toString(): String {
val result = StringBuilder(type.value).append(ownerId).append('_').append(id)
if (!accessKey.isNullOrBlank()) {
result.append('_')
result.append(accessKey)
}
return result.toString()
}
}
@@ -0,0 +1,22 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.data.VkAttachmentItemData
data class VkWallDomain(
val id: Int,
val fromId: Int,
val toId: Int,
val date: Int,
val text: String,
val attachments: List<VkAttachmentItemData>?,
val comments: Int?,
val likes: Int?,
val reposts: Int?,
val views: Int?,
val isFavorite: Boolean,
val accessKey: String?
) : VkAttachment {
override val type: AttachmentType = AttachmentType.WALL
}
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkWallReplyDomain(
val id: Int
) : VkAttachment {
override val type: AttachmentType = AttachmentType.WALL_REPLY
}
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkWidgetDomain(
val id: Int
) : VkAttachment {
override val type: AttachmentType = AttachmentType.WIDGET
}
@@ -0,0 +1,20 @@
package com.meloda.app.fast.model.api.requests
import com.meloda.app.fast.model.api.asInt
data class AccountSetOnlineRequest(
val voip: Boolean,
val accessToken: String
) {
val map
get() = mutableMapOf(
"voip" to voip.asInt().toString(),
"access_token" to accessToken
)
}
data class AccountSetOfflineRequest(val accessToken: String) {
val map get() = mutableMapOf("access_token" to accessToken)
}
@@ -0,0 +1,34 @@
package com.meloda.app.fast.model.api.requests
data class ConversationsGetRequest(
val count: Int? = null,
val offset: Int? = null,
val fields: String = "",
val filter: String = "all",
val extended: Boolean? = true,
val startMessageId: Int? = null
) {
val map
get() = mutableMapOf(
"fields" to fields,
"filter" to filter
).apply {
count?.let { this["count"] = it.toString() }
offset?.let { this["offset"] = it.toString() }
extended?.let { this["extended"] = it.toString() }
startMessageId?.let { this["start_message_id"] = it.toString() }
}
}
data class ConversationsDeleteRequest(val peerId: Int) {
val map get() = mapOf("peer_id" to peerId.toString())
}
data class ConversationsPinRequest(val peerId: Int) {
val map get() = mapOf("peer_id" to peerId.toString())
}
data class ConversationsUnpinRequest(val peerId: Int) {
val map get() = mapOf("peer_id" to peerId.toString())
}
@@ -0,0 +1,33 @@
package com.meloda.app.fast.model.api.requests
data class GetFriendsRequest(
val order: String?,
val count: Int?,
val offset: Int?,
val fields: String?
) {
val map
get() = mutableMapOf<String, String>()
.apply {
order?.let { this["order"] = it }
count?.let { this["count"] = it.toString() }
offset?.let { this["offset"] = it.toString() }
fields?.let { this["fields"] = it }
}
}
data class GetOnlineFriendsRequest(
val order: String?,
val count: Int?,
val offset: Int?,
) {
val map
get() = mutableMapOf<String, String>()
.apply {
order?.let { this["order"] = it }
count?.let { this["count"] = it.toString() }
offset?.let { this["offset"] = it.toString() }
}
}
@@ -0,0 +1,21 @@
package com.meloda.app.fast.model.api.requests
data class LongPollGetUpdatesRequest(
val act: String = "a_check",
val key: String,
val ts: Int,
val wait: Int,
val mode: Int,
val version: Int
) {
val map
get() = mutableMapOf(
"act" to act,
"key" to key,
"ts" to ts.toString(),
"wait" to wait.toString(),
"mode" to mode.toString(),
"version" to version.toString()
)
}
@@ -0,0 +1,245 @@
package com.meloda.app.fast.model.api.requests
import com.meloda.app.fast.model.api.asInt
import com.meloda.app.fast.model.api.domain.VkAttachment
data class MessagesGetHistoryRequest(
val count: Int? = null,
val offset: Int? = null,
val peerId: Int,
val extended: Boolean? = null,
val startMessageId: Int? = null,
val rev: Boolean? = null,
val fields: String? = null,
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString()
).apply {
count?.let { this["count"] = it.toString() }
offset?.let { this["offset"] = it.toString() }
extended?.let { this["extended"] = (if (it) 1 else 0).toString() }
startMessageId?.let { this["start_message_id"] = it.toString() }
rev?.let { this["rev"] = (if (it) 1 else 0).toString() }
fields?.let { this["fields"] = it }
}
}
data class MessagesSendRequest(
val peerId: Int,
val randomId: Int = 0,
val message: String?,
val lat: Int? = null,
val lon: Int? = null,
val replyTo: Int? = null,
val stickerId: Int? = null,
val disableMentions: Boolean? = null,
val doNotParseLinks: Boolean? = null,
val silent: Boolean? = null,
val attachments: List<VkAttachment>? = null
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString(),
"random_id" to randomId.toString()
).apply {
message?.let { this["message"] = it }
lat?.let { this["lat"] = it.toString() }
lon?.let { this["lon"] = it.toString() }
replyTo?.let { this["reply_to"] = it.toString() }
stickerId?.let { this["sticker_id"] = it.toString() }
disableMentions?.let { this["disable_mentions"] = it.asInt().toString() }
doNotParseLinks?.let { this["dont_parse_links"] = it.asInt().toString() }
silent?.let { this["silent"] = it.toString() }
// TODO: 05/05/2024, Danil Nikolaev: add attachments
// attachments?.let {
// this["attachment"] = it.joinToString() { attachment ->
// attachment.asString(true)
// }
// }
}
}
data class MessagesMarkAsReadRequest(
val peerId: Int,
val startMessageId: Int?
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString(),
).apply {
startMessageId?.let { this["start_message_id"] = it.toString() }
}
}
data class MessagesMarkAsImportantRequest(
val messagesIds: List<Int>,
val important: Boolean
) {
val map: Map<String, String>
get() = mapOf(
"message_ids" to messagesIds.joinToString(),
"important" to important.asInt().toString()
)
}
data class MessagesGetLongPollServerRequest(
val needPts: Boolean,
val version: Int
) {
val map: Map<String, String>
get() = mapOf(
"need_pts" to needPts.asInt().toString(),
"version" to version.toString()
)
}
data class MessagesPinMessageRequest(
val peerId: Int,
val messageId: Int? = null,
val conversationMessageId: Int? = null
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString()
).apply {
messageId?.let { this["message_id"] = it.toString() }
conversationMessageId?.let { this["conversation_message_id"] = it.toString() }
}
}
data class MessagesUnPinMessageRequest(val peerId: Int) {
val map: Map<String, String>
get() = mapOf("peer_id" to peerId.toString())
}
data class MessagesDeleteRequest(
val peerId: Int,
val messagesIds: List<Int>? = null,
val conversationsMessagesIds: List<Int>? = null,
val isSpam: Boolean? = null,
val deleteForAll: Boolean? = null
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString()
).apply {
isSpam?.let { this["spam"] = it.asInt().toString() }
deleteForAll?.let { this["delete_for_all"] = it.asInt().toString() }
messagesIds?.let { this["message_ids"] = it.joinToString() }
conversationsMessagesIds?.let {
this["conversation_message_ids"] = it.joinToString()
}
}
}
data class MessagesEditRequest(
val peerId: Int,
val messageId: Int,
val message: String? = null,
val lat: Float? = null,
val long: Float? = null,
val attachments: List<VkAttachment>? = null,
val notParseLinks: Boolean = false,
val keepSnippets: Boolean = true,
val keepForwardedMessages: Boolean = true
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString(),
"message_id" to messageId.toString(),
"dont_parse_links" to notParseLinks.asInt().toString(),
"keep_snippets" to keepSnippets.asInt().toString(),
"keep_forward_messages" to keepForwardedMessages.asInt().toString()
).apply {
message?.let { this["message"] = it }
lat?.let { this["lat"] = it.toString() }
long?.let { this["long"] = it.toString() }
// TODO: 05/05/2024, Danil Nikolaev: add attachments
// attachments?.let {
// val attachments =
// if (it.isEmpty()) ""
// else it.joinToString() { it.asString() }
// this["attachment"] = attachments
// }
}
}
data class MessagesGetByIdRequest(
val messagesIds: List<Int>,
val extended: Boolean? = null,
val fields: String? = null
) {
val map: Map<String, String>
get() = mutableMapOf(
"message_ids" to messagesIds.joinToString(),
).apply {
extended?.let { this["extended"] = it.asInt().toString() }
fields?.let { this["fields"] = it }
}
}
data class MessagesGetChatRequest(
val chatId: Int,
val fields: String? = null
) {
val map: Map<String, String>
get() = mutableMapOf(
"chat_id" to chatId.toString()
).apply {
fields?.let { this["fields"] = it }
}
}
data class MessagesGetConversationMembersRequest(
val peerId: Int,
val offset: Int? = null,
val count: Int? = null,
val extended: Boolean? = null,
val fields: String? = null
) {
val map: Map<String, String>
get() = mutableMapOf(
"peer_id" to peerId.toString()
).apply {
offset?.let { this["offset"] = it.toString() }
count?.let { this["count"] = it.toString() }
extended?.let { this["extended"] = it.toString() }
fields?.let { this["fields"] = it }
}
}
data class MessagesRemoveChatUserRequest(
val chatId: Int,
val memberId: Int
) {
val map: Map<String, String>
get() = mapOf(
"chat_id" to chatId.toString(),
"member_id" to memberId.toString()
)
}
@@ -0,0 +1,61 @@
package com.meloda.app.fast.model.api.requests
data class AuthDirectRequest(
val grantType: String,
val clientId: String,
val clientSecret: String,
val username: String,
val password: String,
val scope: String,
val twoFaSupported: Boolean = true,
val twoFaForceSms: Boolean = false,
val twoFaCode: String? = null,
val captchaSid: String? = null,
val captchaKey: String? = null,
val trustedHash: String? = null
) {
val map
get() = mutableMapOf(
"grant_type" to grantType,
"client_id" to clientId,
"client_secret" to clientSecret,
"username" to username,
"password" to password,
"scope" to scope,
"2fa_supported" to if (twoFaSupported) "1" else "0",
"force_sms" to if (twoFaForceSms) "1" else "0"
)
.apply {
twoFaCode?.let { this["code"] = it }
captchaSid?.let { this["captcha_sid"] = it }
captchaKey?.let { this["captcha_key"] = it }
trustedHash?.let { this["trusted_hash"] = it }
}
}
data class AuthWithAppRequest(
val redirectUrl: String = "https://oauth.vk.com/blank.html",
val display: String = "page",
val responseType: String = "token",
val accessToken: String,
val revoke: Int = 1,
val scope: Int = 136297695,
val clientId: String,
val sdkPackage: String,
val sdkFingerprint: String
) {
val map
get() = mutableMapOf(
"redirect_url" to redirectUrl,
"display" to display,
"response_type" to responseType,
"access_token" to accessToken,
"revoke" to revoke.toString(),
"scope" to scope.toString(),
"client_id" to clientId,
"sdk_package" to sdkPackage,
"sdk_fingerprint" to sdkFingerprint
)
}
@@ -0,0 +1,14 @@
package com.meloda.app.fast.model.api.requests
data class PhotosSaveMessagePhotoRequest(
val photo: String,
val server: Int,
val hash: String
) {
val map
get() = mapOf(
"photo" to photo,
"server" to server.toString(),
"hash" to hash
)
}
@@ -0,0 +1,16 @@
package com.meloda.app.fast.model.api.requests
data class UsersGetRequest(
val userIds: List<Int>? = null,
val fields: String? = null,
val nomCase: String? = null
) {
val map
get() = mutableMapOf<String, String>()
.apply {
userIds?.let { this["user_ids"] = it.joinToString() }
fields?.let { this["fields"] = it }
nomCase?.let { this["nom_case"] = it }
}
}
@@ -0,0 +1,16 @@
package com.meloda.app.fast.model.api.responses
import com.squareup.moshi.Json
data class AudiosGetUploadServerResponse(
@Json(name = "upload_url")
val uploadUrl: String
)
data class AudiosUploadResponse(
val redirect: String,
val server: Int,
val audio: String?,
val hash: String,
val error: String?
)
@@ -0,0 +1,12 @@
package com.meloda.app.fast.model.api.responses
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class SendSmsResponse(
@Json(name = "sid") val validationSid: String?,
@Json(name = "delay") val delay: Int?,
@Json(name = "validation_type") val validationType: String?,
@Json(name = "validation_resend") val validationResend: String?
)
@@ -0,0 +1,30 @@
package com.meloda.app.fast.model.api.responses
import com.meloda.app.fast.model.api.data.VkContactData
import com.meloda.app.fast.model.api.data.VkConversationData
import com.meloda.app.fast.model.api.data.VkGroupData
import com.meloda.app.fast.model.api.data.VkMessageData
import com.meloda.app.fast.model.api.data.VkUserData
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class ConversationsGetResponse(
@Json(name = "count") val count: Int,
@Json(name = "items") val items: List<ConversationsResponseItem>,
@Json(name = "unread_count") val unreadCount: Int?,
@Json(name = "profiles") val profiles: List<VkUserData>?,
@Json(name = "groups") val groups: List<VkGroupData>?,
@Json(name = "contacts") val contacts: List<VkContactData>?
)
@JsonClass(generateAdapter = true)
data class ConversationsResponseItem(
@Json(name = "conversation") val conversation: VkConversationData,
@Json(name = "last_message") val lastMessage: VkMessageData?
)
@JsonClass(generateAdapter = true)
data class ConversationsDeleteResponse(
@Json(name = "last_deleted_id") val lastDeletedId: Int
)
@@ -0,0 +1,20 @@
package com.meloda.app.fast.model.api.responses
import com.meloda.app.fast.model.api.data.VkAudioMessageData
import com.meloda.app.fast.model.api.data.VkFileData
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
data class FilesGetMessagesUploadServerResponse(
@Json(name = "upload_url")
val uploadUrl: String
)
data class FilesUploadFileResponse(val file: String?, val error: String?)
@JsonClass(generateAdapter = true)
data class FilesSaveFileResponse(
@Json(name = "type") val type: String,
@Json(name = "doc") val file: VkFileData?,
@Json(name = "audio_message") val voiceMessage: VkAudioMessageData?
)
@@ -0,0 +1,11 @@
package com.meloda.app.fast.model.api.responses
import com.meloda.app.fast.model.api.data.VkUserData
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class GetFriendsResponse(
@Json(name = "count") val count: Int,
@Json(name = "items") val items: List<VkUserData>
)
@@ -0,0 +1,35 @@
package com.meloda.app.fast.model.api.responses
import com.meloda.app.fast.model.api.data.VkChatMemberData
import com.meloda.app.fast.model.api.data.VkContactData
import com.meloda.app.fast.model.api.data.VkConversationData
import com.meloda.app.fast.model.api.data.VkGroupData
import com.meloda.app.fast.model.api.data.VkMessageData
import com.meloda.app.fast.model.api.data.VkUserData
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class MessagesGetHistoryResponse(
val count: Int,
val items: List<VkMessageData>,
val conversations: List<VkConversationData>?,
val profiles: List<VkUserData>?,
val groups: List<VkGroupData>?,
val contacts: List<VkContactData>?
)
@JsonClass(generateAdapter = true)
data class MessagesGetByIdResponse(
val count: Int,
val items: List<VkMessageData> = emptyList(),
val profiles: List<VkUserData>?,
val groups: List<VkGroupData>?
)
@JsonClass(generateAdapter = true)
data class MessagesGetConversationMembersResponse(
val count: Int,
val items: List<VkChatMemberData>?,
val profiles: List<VkUserData>?,
val groups: List<VkGroupData>?
)
@@ -0,0 +1,37 @@
package com.meloda.app.fast.model.api.responses
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class AuthDirectResponse(
@Json(name = "access_token") val accessToken: String?,
@Json(name = "user_id") val userId: Int?,
@Json(name = "trusted_hash") val twoFaHash: String?,
@Json(name = "validation_sid") val validationSid: String?,
@Json(name = "validation_type") val validationType: String?,
@Json(name = "phone_mask") val phoneMask: String?,
@Json(name = "redirect_uri") val redirectUri: String?,
@Json(name = "validation_resend") val validationResend: String?,
@Json(name = "cant_get_code_open_restore") val restoreIfCannotGetCode: Boolean?,
@Json(name = "error") val error: String?,
@Json(name = "error_description") val errorDescription: String?,
@Json(name = "error_type") val errorType: String?,
@Json(name = "ban_info") val banInfo: BanInfo?,
@Json(name = "captcha_sid") val captchaSid: String?,
@Json(name = "captcha_img") val captchaImage: String?,
@Json(name = "captcha_ts") val captchaTs: Double?,
@Json(name = "captcha_ratio") val captchaRatio: Double?,
@Json(name = "captcha_track") val captchaTrack: String?,
@Json(name = "is_refresh_enabled") val isRefreshEnabled: Boolean?,
@Json(name = "is_sound_captcha_available") val isSoundCaptchaAvailable: Boolean?
) {
@JsonClass(generateAdapter = true)
data class BanInfo(
@Json(name = "member_name") val memberName: String,
@Json(name = "message") val message: String,
@Json(name = "access_token") val accessToken: String,
@Json(name = "restore_url") val restoreUrl: String
)
}
@@ -0,0 +1,16 @@
package com.meloda.app.fast.model.api.responses
import com.squareup.moshi.Json
data class PhotosGetMessagesUploadServerResponse(
@Json(name = "album_id")
val albumId: Int,
@Json(name = "upload_url")
val uploadUrl: String
)
data class PhotosUploadPhotoResponse(
val server: Int,
val photo: String,
val hash: String
)
@@ -0,0 +1,21 @@
package com.meloda.app.fast.model.api.responses
import com.squareup.moshi.Json
data class VideosSaveResponse(
@Json(name = "access_key") val accessKey: String,
val description: String,
@Json(name = "owner_id") val ownerId: Int,
val title: String,
@Json(name = "upload_url") val uploadUrl: String,
@Json(name = "video_id") val videoId: Int
)
data class VideosUploadResponse(
@Json(name = "video_hash") val hash: String?,
val size: Int,
@Json(name = "direct_link") val directLink: String,
@Json(name = "owner_id") val ownerId: Int,
@Json(name = "video_id") val videoId: Int,
val error: String?
)
@@ -0,0 +1,13 @@
package com.meloda.app.fast.model.database
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "accounts")
data class AccountEntity(
@PrimaryKey(autoGenerate = false)
val userId: Int,
val accessToken: String,
val fastToken: String?,
val trustedHash: String?
)
@@ -0,0 +1,13 @@
package com.meloda.app.fast.model.database
import androidx.room.Embedded
import androidx.room.Relation
data class ConversationWithMessage(
@Embedded val conversation: VkConversationEntity,
@Relation(
parentColumn = "lastMessageId",
entityColumn = "id"
)
val message: VkMessageEntity?
)
@@ -0,0 +1,64 @@
package com.meloda.app.fast.model.database
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.meloda.app.fast.model.api.PeerType
import com.meloda.app.fast.model.api.domain.VkConversation
@Entity(tableName = "conversations")
data class VkConversationEntity(
@PrimaryKey val id: Int,
val localId: Int,
val ownerId: Int?,
val title: String?,
val photo50: String?,
val photo100: String?,
val photo200: String?,
val isPhantom: Boolean,
val lastConversationMessageId: Int,
val inReadCmId: Int,
val outReadCmId: Int,
val inRead: Int,
val outRead: Int,
val lastMessageId: Int?,
val unreadCount: Int,
val membersCount: Int?,
val canChangePin: Boolean,
val canChangeInfo: Boolean,
val majorId: Int,
val minorId: Int,
val pinnedMessageId: Int?,
val peerType: String,
)
fun VkConversationEntity.asExternalModel(): VkConversation = VkConversation(
id = id,
localId = localId,
ownerId = ownerId,
title = title,
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
isCallInProgress = false,
isPhantom = isPhantom,
lastConversationMessageId = lastConversationMessageId,
inReadCmId = inReadCmId,
outReadCmId = outReadCmId,
inRead = inRead,
outRead = outRead,
lastMessageId = lastMessageId,
unreadCount = unreadCount,
membersCount = membersCount,
canChangePin = canChangePin,
canChangeInfo = canChangeInfo,
majorId = majorId,
minorId = minorId,
pinnedMessageId = pinnedMessageId,
interactionType = -1,
interactionIds = emptyList(),
peerType = PeerType.parse(peerType),
lastMessage = null,//lastMessage?.asExternalModel(),
pinnedMessage = null,//pinnedMessage?.asExternalModel(),
user = null,
group = null,
)
@@ -0,0 +1,15 @@
package com.meloda.app.fast.model.database
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "groups")
data class VkGroupEntity(
@PrimaryKey val id: Int,
val name: String,
val screenName: String,
val photo50: String?,
val photo100: String?,
val photo200: String?,
val membersCount: Int?
)
@@ -0,0 +1,54 @@
package com.meloda.app.fast.model.database
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.meloda.app.fast.model.api.domain.VkAttachment
import com.meloda.app.fast.model.api.domain.VkMessage
@Entity(tableName = "messages")
data class VkMessageEntity(
@PrimaryKey val id: Int,
val text: String?,
val isOut: Boolean,
val peerId: Int,
val fromId: Int,
val date: Int,
val randomId: Int,
val action: String?,
val actionMemberId: Int?,
val actionText: String?,
val actionConversationMessageId: Int?,
val actionMessage: String?,
val updateTime: Int?,
val important: Boolean,
val forwardIds: List<Int>?,
val attachments: List<String>?, // TODO: 01/05/2024, Danil Nikolaev: how to store???
val replyMessageId: Int?,
val geoType: String?
)
fun VkMessageEntity.asExternalModel(): VkMessage = VkMessage(
id = id,
text = text,
isOut = isOut,
peerId = peerId,
fromId = fromId,
date = date,
randomId = randomId,
action = VkMessage.Action.parse(action),
actionMemberId = actionMemberId,
actionText = actionText,
actionConversationMessageId = actionConversationMessageId,
actionMessage = actionMessage,
updateTime = updateTime,
important = important,
forwards = emptyList(),//forwards.orEmpty().map(VkMessageEntity::asExternalModel),
// TODO: 05/05/2024, Danil Nikolaev: restore attachments
attachments = attachments.orEmpty().map { object : VkAttachment {} },
replyMessage = null,//replyMessage?.asExternalModel(),
geoType = geoType,
user = null,
group = null,
actionUser = null,
actionGroup = null,
)
@@ -0,0 +1,20 @@
package com.meloda.app.fast.model.database
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "users")
data class VkUserEntity(
@PrimaryKey val id: Int,
val firstName: String,
val lastName: String,
val isOnline: Boolean,
val isOnlineMobile: Boolean,
val onlineAppId: Int?,
val lastSeen: Int?,
val lastSeenStatus: String?,
val birthday: String?,
val photo50: String?,
val photo100: String?,
val photo200: String?
)