-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Поддержка перезалива из тиктока(фу блин)
- Loading branch information
1 parent
7e07a3f
commit 50264c7
Showing
26 changed files
with
361 additions
and
71 deletions.
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
src/main/java/ru/spliterash/vkVideoUnlocker/application/MariaDbInitializer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package ru.spliterash.vkVideoUnlocker.application | ||
|
||
import io.micronaut.context.event.ApplicationEventListener | ||
import io.micronaut.context.event.StartupEvent | ||
import jakarta.inject.Singleton | ||
import org.jdbi.v3.core.Jdbi | ||
import org.jdbi.v3.core.kotlin.KotlinMapper | ||
import org.jdbi.v3.core.kotlin.inTransactionUnchecked | ||
import ru.spliterash.vkVideoUnlocker.video.entity.VideoEntity | ||
|
||
@Singleton | ||
class MariaDbInitializer( | ||
private val jdbi: Jdbi | ||
) : ApplicationEventListener<StartupEvent> { | ||
override fun onApplicationEvent(event: StartupEvent) { | ||
val stream = Thread.currentThread().contextClassLoader.getResourceAsStream("MySQL_init.sql")!! | ||
|
||
val initSQL = stream | ||
.readAllBytes() | ||
.decodeToString() | ||
jdbi.registerRowMapper(VideoEntity::class.java, KotlinMapper(VideoEntity::class)) | ||
|
||
jdbi.inTransactionUnchecked { handle -> | ||
handle.begin() | ||
|
||
val batch = handle.createBatch() | ||
for (line in initSQL.split(";")) { | ||
val trimLine = line.trim() | ||
if (trimLine.isBlank()) | ||
continue | ||
|
||
batch.add(line) | ||
} | ||
|
||
batch.execute() | ||
|
||
handle.commit() | ||
} | ||
} | ||
} |
14 changes: 0 additions & 14 deletions
14
src/main/java/ru/spliterash/vkVideoUnlocker/application/VkUnlockerRunner.kt
This file was deleted.
Oops, something went wrong.
35 changes: 35 additions & 0 deletions
35
src/main/java/ru/spliterash/vkVideoUnlocker/common/RedirectHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package ru.spliterash.vkVideoUnlocker.common | ||
|
||
import jakarta.inject.Singleton | ||
import okhttp3.Request | ||
import okhttp3.executeAsync | ||
import ru.spliterash.vkVideoUnlocker.common.okHttp.OkHttpFactory | ||
|
||
@Singleton | ||
class RedirectHelper( | ||
private val okHttpFactory: OkHttpFactory | ||
) { | ||
private val client = okHttpFactory.create().followRedirects(false).build() | ||
|
||
suspend fun finalUrl(startUrl: String): String { | ||
var loop = 0 | ||
var currentUrl = startUrl | ||
while (loop < 50) { | ||
val response = client.newCall( | ||
Request.Builder() | ||
.url(currentUrl) | ||
.head() | ||
.build() | ||
) | ||
.executeAsync() | ||
|
||
if (response.isRedirect) | ||
currentUrl = response.header("Location")!! | ||
else { | ||
return currentUrl | ||
} | ||
loop++ | ||
} | ||
throw RuntimeException("Too much redirects") | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
src/main/java/ru/spliterash/vkVideoUnlocker/message/editableMessage/EditableMessage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
package ru.spliterash.vkVideoUnlocker.message.editableMessage | ||
|
||
interface EditableMessage { | ||
suspend fun sendOrUpdate(text: String?, attachments: String? = null) | ||
suspend fun sendOrUpdate(text: String? = null, attachments: String? = null) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/MariaDbTiktokVideoRepositoryImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
import jakarta.inject.Singleton | ||
import org.jdbi.v3.core.Jdbi | ||
import org.jdbi.v3.core.kotlin.withHandleUnchecked | ||
|
||
@Singleton | ||
class MariaDbTiktokVideoRepositoryImpl( | ||
private val jdbi: Jdbi | ||
) : TiktokVideoRepository { | ||
override suspend fun findVideo(id: String): TiktokVideoEntity? = jdbi.withHandleUnchecked { handle -> | ||
handle.createQuery("SELECT * FROM tiktok_videos where id = ?") | ||
.bind(0, id) | ||
.mapTo(TiktokVideoEntity::class.java) | ||
.findOne() | ||
.orElse(null) | ||
} | ||
|
||
override suspend fun save(entity: TiktokVideoEntity) { | ||
jdbi.withHandleUnchecked { handle -> | ||
handle.createUpdate( | ||
"INSERT INTO tiktok_videos (id,vk_id) values (:id,:vk_id) " + | ||
"on duplicate key update vk_id = :vk_id" | ||
) | ||
.bind("id", entity.id) | ||
.bind("vk_id", entity.vkId) | ||
.execute() | ||
} | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TikCdnDownloader.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
import jakarta.inject.Singleton | ||
import okhttp3.FormBody | ||
import okhttp3.Request | ||
import okhttp3.executeAsync | ||
import ru.spliterash.vkVideoUnlocker.common.okHttp.OkHttpFactory | ||
import ru.spliterash.vkVideoUnlocker.common.okHttp.executeAsync | ||
import ru.spliterash.vkVideoUnlocker.video.accessor.UrlVideoAccessorImpl | ||
import java.net.URL | ||
import java.util.regex.Pattern | ||
|
||
@Singleton | ||
class TikCdnDownloader( | ||
okHttpFactory: OkHttpFactory | ||
) : TiktokDownloader { | ||
private val client = okHttpFactory.create().build() | ||
private val tikCdnTokenPattern = Pattern.compile("s_tt += +'(?<token>[a-zA-Z0-9_-]+)'") | ||
private val tikCdnVideoUrlPattern = Pattern.compile("https://tikcdn\\.io/ssstik/(?<id>\\d+)") | ||
override suspend fun download(videoUrl: String): TiktokVideo { | ||
val token = getActualToken() | ||
|
||
val response = Request.Builder() | ||
.url("https://ssstik.io/abc?url=dl") | ||
.post( | ||
FormBody.Builder() | ||
.addEncoded("id", videoUrl) | ||
.addEncoded("locale", "en") | ||
.addEncoded("tt", token) | ||
.build() | ||
) | ||
.header("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0") | ||
.build() | ||
.executeAsync(client) | ||
.body | ||
.string() | ||
val matcher = tikCdnVideoUrlPattern.matcher(response) | ||
if (!matcher.find()) { | ||
println(response) | ||
throw IllegalStateException("ssstik.io return wrong response") | ||
} | ||
|
||
val url = matcher.group() | ||
val id = matcher.group("id") | ||
|
||
return TiktokVideo(id, UrlVideoAccessorImpl(client, URL(url))) | ||
|
||
} | ||
|
||
private suspend fun getActualToken(): String { | ||
val response = client | ||
.newCall(Request.Builder().get().url("https://ssstik.io/en").build()) | ||
.executeAsync() | ||
|
||
val page = response.body.string() | ||
val matcher = tikCdnTokenPattern.matcher(page) | ||
if (!matcher.find()) throw IllegalStateException("Fail to parse tikcdn token") | ||
|
||
return matcher.group("token") | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TiktokChain.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
import jakarta.inject.Singleton | ||
import ru.spliterash.vkVideoUnlocker.common.RedirectHelper | ||
import ru.spliterash.vkVideoUnlocker.longpoll.message.RootMessage | ||
import ru.spliterash.vkVideoUnlocker.message.editableMessage.EditableMessage | ||
import ru.spliterash.vkVideoUnlocker.messageChain.MessageHandler | ||
import ru.spliterash.vkVideoUnlocker.vk.MessageScanner | ||
import java.util.regex.Pattern | ||
|
||
@Singleton | ||
class TiktokChain( | ||
private val redirectHelper: RedirectHelper, | ||
private val tiktokService: TiktokService, | ||
private val messageScanner: MessageScanner, | ||
) : MessageHandler { | ||
private val pattern = Pattern.compile("https?://(?:www|vt)?\\.tiktok.com/(?:@\\w+/video/(?:(?<id>\\d+))|\\w+)") | ||
override suspend fun handle(message: RootMessage, editableMessage: EditableMessage): Boolean { | ||
val videoUrl = messageScanner.scanForText(message) { | ||
val matcher = pattern.matcher(it) | ||
if (!matcher.find()) null | ||
else matcher.group() | ||
} ?: return false | ||
|
||
val id = tiktokService.getVkId(videoUrl) | ||
editableMessage.sendOrUpdate(attachments = "video$id") | ||
|
||
return true | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TiktokDownloader.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
|
||
interface TiktokDownloader { | ||
suspend fun download(videoUrl: String): TiktokVideo | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TiktokService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
import jakarta.inject.Singleton | ||
import ru.spliterash.vkVideoUnlocker.video.accessor.VideoAccessor | ||
import ru.spliterash.vkVideoUnlocker.vk.actor.GroupUser | ||
import ru.spliterash.vkVideoUnlocker.vk.actor.types.WorkUser | ||
import ru.spliterash.vkVideoUnlocker.vk.api.VkApi | ||
|
||
@Singleton | ||
class TiktokService( | ||
@WorkUser private val workUser: VkApi, | ||
@GroupUser private val groupUser: VkApi, | ||
private val tiktokDownloader: TiktokDownloader, | ||
private val tiktokVideoRepository: TiktokVideoRepository | ||
) { | ||
suspend fun getVkId(tiktokVideoUrl: String): String { | ||
val info = tiktokDownloader.download(tiktokVideoUrl) | ||
val video = tiktokVideoRepository.findVideo(info.id) | ||
if (video != null) return video.vkId | ||
|
||
val vkId = reUpload(info.id, info.accessor) | ||
|
||
tiktokVideoRepository.save(TiktokVideoEntity(info.id, vkId)) | ||
|
||
return vkId | ||
} | ||
|
||
private suspend fun reUpload(number: String, accessor: VideoAccessor) = workUser.videos.upload( | ||
groupUser.id, | ||
"tiktok-$number", | ||
false, | ||
accessor | ||
) | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TiktokVideo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
import ru.spliterash.vkVideoUnlocker.video.accessor.VideoAccessor | ||
|
||
class TiktokVideo( | ||
val id: String, | ||
val accessor: VideoAccessor | ||
) |
6 changes: 6 additions & 0 deletions
6
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TiktokVideoEntity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
class TiktokVideoEntity( | ||
val id: String, | ||
val vkId: String | ||
) |
6 changes: 6 additions & 0 deletions
6
src/main/java/ru/spliterash/vkVideoUnlocker/tiktok/TiktokVideoRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package ru.spliterash.vkVideoUnlocker.tiktok | ||
|
||
interface TiktokVideoRepository { | ||
suspend fun findVideo(id: String): TiktokVideoEntity? | ||
suspend fun save(entity: TiktokVideoEntity) | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/ru/spliterash/vkVideoUnlocker/video/accessor/AdvancedVideoAccessor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package ru.spliterash.vkVideoUnlocker.video.accessor | ||
|
||
import java.net.URL | ||
|
||
interface AdvancedVideoAccessor : VideoAccessor { | ||
val maxQuality: Int | ||
val maxQualityUrl: URL | ||
fun preview(): URL | ||
|
||
suspend fun load(quality: Int): VideoAccessor.Info | ||
suspend fun load(quality: Int, range: String): VideoAccessor.Info | ||
} |
Oops, something went wrong.