BarInsta/app/src/main/java/awais/instagrabber/webservices/StoriesRepository.kt

202 lines
7.0 KiB
Kotlin

package awais.instagrabber.webservices
import awais.instagrabber.fragments.settings.PreferenceKeys
import awais.instagrabber.repositories.StoriesService
import awais.instagrabber.repositories.requests.StoryViewerOptions
import awais.instagrabber.repositories.responses.stories.ArchiveResponse
import awais.instagrabber.repositories.responses.stories.Story
import awais.instagrabber.repositories.responses.stories.StoryMedia
import awais.instagrabber.repositories.responses.stories.StoryStickerResponse
import awais.instagrabber.utils.Utils
import awais.instagrabber.webservices.RetrofitFactory.retrofit
import java.util.UUID
open class StoriesRepository(private val service: StoriesService) {
suspend fun fetch(mediaId: Long): StoryMedia? {
val response = service.fetch(mediaId)
return response.items?.get(0)
}
suspend fun getFeedStories(): List<Story> {
val response = service.getFeedStories()
val result: MutableList<Story> = mutableListOf()
if (response?.broadcasts != null) {
val length = response.broadcasts.size
for (i in 0 until length) {
val broadcast = response.broadcasts.get(i)
result.add(
Story(
broadcast.id,
broadcast.publishedTime,
1,
0L,
broadcast.broadcastOwner,
broadcast.muted,
false, // unclear
null,
null,
null,
null,
broadcast
)
)
}
}
if (response?.tray != null) result.addAll(response.tray)
return sort(result.toList())
}
open suspend fun fetchHighlights(profileId: Long): List<Story> {
val response = service.fetchHighlights(profileId)
val highlightModels = response?.tray ?: listOf()
return highlightModels
}
suspend fun fetchArchive(maxId: String): ArchiveResponse? {
val form = mutableMapOf(
"include_suggested_highlights" to "false",
"is_in_archive_home" to "true",
"include_cover" to "1",
)
if (!maxId.isNullOrEmpty()) {
form["max_id"] = maxId // NOT TESTED
}
return service.fetchArchive(form)
}
open suspend fun getStories(options: StoryViewerOptions): Story? {
return when (options.type) {
StoryViewerOptions.Type.HIGHLIGHT,
StoryViewerOptions.Type.STORY_ARCHIVE
-> {
val response = service.getReelsMedia(options.name)
response.reels?.get(options.name)
}
StoryViewerOptions.Type.USER -> {
val response = service.getUserStories(options.id.toString())
response.reel
}
// should not reach beyond this point
StoryViewerOptions.Type.LOCATION -> {
val response = service.getStories("locations", options.id.toString())
response.story
}
StoryViewerOptions.Type.HASHTAG -> {
val response = service.getStories("tags", options.name)
response.story
}
else -> null
}
}
private suspend fun respondToSticker(
csrfToken: String,
userId: Long,
deviceUuid: String,
storyId: Long,
stickerId: Long,
action: String,
arg1: String,
arg2: String,
): StoryStickerResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uid" to userId,
"_uuid" to deviceUuid,
"mutation_token" to UUID.randomUUID().toString(),
"client_context" to UUID.randomUUID().toString(),
"radio_type" to "wifi-none",
arg1 to arg2,
)
val signedForm = Utils.sign(form)
return service.respondToSticker(storyId, stickerId, action, signedForm)
}
suspend fun respondToQuestion(
csrfToken: String,
userId: Long,
deviceUuid: String,
storyId: Long,
stickerId: Long,
answer: String,
): StoryStickerResponse = respondToSticker(csrfToken, userId, deviceUuid, storyId, stickerId, "story_question_response", "response", answer)
suspend fun respondToQuiz(
csrfToken: String,
userId: Long,
deviceUuid: String,
storyId: Long,
stickerId: Long,
answer: Int,
): StoryStickerResponse {
return respondToSticker(csrfToken, userId, deviceUuid, storyId, stickerId, "story_quiz_answer", "answer", answer.toString())
}
suspend fun respondToPoll(
csrfToken: String,
userId: Long,
deviceUuid: String,
storyId: Long,
stickerId: Long,
answer: Int,
): StoryStickerResponse = respondToSticker(csrfToken, userId, deviceUuid, storyId, stickerId, "story_poll_vote", "vote", answer.toString())
suspend fun respondToSlider(
csrfToken: String,
userId: Long,
deviceUuid: String,
storyId: Long,
stickerId: Long,
answer: Double,
): StoryStickerResponse = respondToSticker(csrfToken, userId, deviceUuid, storyId, stickerId, "story_slider_vote", "vote", answer.toString())
suspend fun seen(
csrfToken: String,
userId: Long,
deviceUuid: String,
storyMediaId: String,
takenAt: Long,
seenAt: Long,
): String {
val reelsForm = mapOf(storyMediaId to listOf(takenAt.toString() + "_" + seenAt))
val form = mutableMapOf(
"_csrftoken" to csrfToken,
"_uid" to userId,
"_uuid" to deviceUuid,
"container_module" to "feed_timeline",
"reels" to reelsForm,
)
val signedForm = Utils.sign(form)
val queryMap = mapOf(
"reel" to "1",
"live_vod" to "0",
)
return service.seen(queryMap, signedForm)
}
private fun sort(list: List<Story>): List<Story> {
val listCopy = ArrayList(list)
listCopy.sortWith { o1, o2 ->
if (o1.latestReelMedia == null || o2.latestReelMedia == null) return@sortWith 0
else when (Utils.settingsHelper.getString(PreferenceKeys.STORY_SORT)) {
"1" -> return@sortWith o2.latestReelMedia.compareTo(o1.latestReelMedia)
"2" -> return@sortWith o1.latestReelMedia.compareTo(o2.latestReelMedia)
else -> return@sortWith 0
}
}
return listCopy
}
companion object {
@Volatile
private var INSTANCE: StoriesRepository? = null
fun getInstance(): StoriesRepository {
return INSTANCE ?: synchronized(this) {
val service: StoriesService = retrofit.create(StoriesService::class.java)
StoriesRepository(service).also { INSTANCE = it }
}
}
}
}