0910cd4c63c39fcc0d9b70f515e7e62d45442e22..7dc048e4f8673e0cb282bfcaf49d0c34a4df92ae
2024-12-06 cshenfu
change cookiehelper
7dc048 对比 | 目录
2024-12-06 cshenfu
update
581fe3 对比 | 目录
2024-12-06 cshenfu
shipinhao_btn
fb6848 对比 | 目录
6个文件已修改
1个文件已删除
4个文件已添加
768 ■■■■■ 已修改文件
.idea/appInsightsSettings.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/deploymentTargetSelector.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/other.xml 329 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/AppConfig.kt 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/SessionProfileActivity.kt 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/SessionProfileWebView.kt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/UploadSessionActivity.kt 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/action/ActionBilibili.kt 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/action/ActionRedbook.kt 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/shsening/autouploadvideos/action/ActionShipinhao.kt 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
未命名 补丁 | 查看 | 原始文档 | blame | 历史
.idea/appInsightsSettings.xml
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="AppInsightsSettings">
    <option name="selectedTabId" value="Android Vitals" />
  </component>
</project>
.idea/deploymentTargetSelector.xml
@@ -13,9 +13,6 @@
        </DropdownSelection>
        <DialogSelection />
      </SelectionState>
      <SelectionState runConfigName="SessionProfileActivity">
        <option name="selectionMode" value="DROPDOWN" />
      </SelectionState>
    </selectionStates>
  </component>
</project>
.idea/other.xml
File was deleted
app/src/main/java/com/shsening/autouploadvideos/AppConfig.kt
@@ -45,7 +45,7 @@
        const val URL_UPLOAD_SERVER_DOUYIN = "https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"
        const val URL_UPLOAD_SERVER_KUAISHOU = "https://cp.kuaishou.com/article/publish/video"
        const val URL_UPLOAD_SERVER_SHIPINHAO = "https://channels.weixin.qq.com/platform/post/create"
        const val URL_UPLOAD_SERVER_XIAOHONGSHU = "https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"
        const val URL_UPLOAD_SERVER_XIAOHONGSHU = "https://creator.xiaohongshu.com/publish/publish?from=menu"
        const val URL_UPLOAD_SERVER_YOUTUBE = "https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"
        const val URL_UPLOAD_SERVER_TIKTOK = "https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"
@@ -53,7 +53,7 @@
            PlatformItem(1,"抖音",true,"https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"),
            PlatformItem(2,"快手",true,"https://cp.kuaishou.com/article/publish/video"),
            PlatformItem(3,"视频号",true,"https://channels.weixin.qq.com/platform/post/create"),
            PlatformItem(4,"小红书",false,"https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"),
            PlatformItem(4,"小红书",true,"https://creator.xiaohongshu.com/publish/publish?from=menu"),
            PlatformItem(5,"YouTube", false,"https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page"),
            PlatformItem(6,"TikTok", false,"https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page")
        )
app/src/main/java/com/shsening/autouploadvideos/SessionProfileActivity.kt
@@ -124,8 +124,7 @@
                            CookieHelper.saveSessionProfileUrlCookies(
                                activityReference,
                                sessionProfile.id,
                                url,
                                cookies
                                url
                            )
                        } else {
                            Log.w("shsening", "No cookies found for URL: $url")
@@ -207,7 +206,6 @@
    private fun saveSessionProfile() {
        try {
            CookieHelper.saveSessionCookies(this,sessionProfile.id)
            val name = editName.text.toString().trim() // èŽ·å–è¾“å…¥çš„åç§°
            if (name.isEmpty()) {
                Toast.makeText(this, "Name cannot be empty!", Toast.LENGTH_SHORT).show()
app/src/main/java/com/shsening/autouploadvideos/SessionProfileWebView.kt
@@ -69,7 +69,7 @@
        val cookieManager = CookieManager.getInstance()
        val cookies = cookieManager.getCookie(url)
        if (cookies != null) {
            CookieHelper.saveSessionProfileUrlCookies(context, sessionProfileId, url, cookies)
            CookieHelper.saveSessionProfileUrlCookies(context, sessionProfileId, url)
        }
    }
app/src/main/java/com/shsening/autouploadvideos/UploadSessionActivity.kt
@@ -119,6 +119,11 @@
                            ActionKuaishou(activityReference, threadHandler, currentTask)
                        action.checkIfContentLoaded()
                    }
                    "小红书" -> {
                        val action =
                            ActionRedbook(activityReference, threadHandler, currentTask)
                        action.checkIfContentLoaded()
                    }
                    "视频号" -> {
                        val action =
                            ActionShipinhao(activityReference, threadHandler, currentTask)
@@ -133,8 +138,7 @@
                            CookieHelper.saveSessionProfileUrlCookies(
                                activityReference,
                                currentTask.sessionProfileId!!,
                                url,
                                cookies
                                url
                            )
                        } else {
                            Log.w("shsening", "No cookies found for URL: $url")
app/src/main/java/com/shsening/autouploadvideos/action/ActionBilibili.kt
New file
@@ -0,0 +1,233 @@
package com.shsening.autouploadvideos
import android.app.Instrumentation
import android.content.Context
import android.os.SystemClock
import android.os.Handler
import com.shsening.autouploadvideos.UploadSessionActivity
import com.shsening.autouploadvideos.utils.Utils
import com.shsening.autouploadvideos.WebviewUtils
import com.shsening.autouploadvideos.action.PlatformActionInterface
class ActionBilibili (private var activity: UploadSessionActivity, private var threadHandler: Handler, private var videoInfo: Utils.VideoUploadTaskInfo) :
    PlatformActionInterface {
    private var webView = activity.sessionProfileWebView
    var jsCode_CheckContentLoaded = """
        document.querySelector('#video-up-app > div.video-entrance > div.upload-body > div > div.upload-wrp > div.bcc-upload.upload > div > input[type=file]') !== null
    """.trimIndent()
    var jsCode_CheckVideoUploadFinished = """
        document.querySelector('#video-up-app > div.video-basic-wrp > div.video-basic > div.video-upload > div.upload-queue > div > div.file-list > div.drag-list > div > div > div.file-item-content > div.file-item-content-detail > div.file-item-content-operate > div > div') !==null
    """.trimIndent()
    var jsCode_PublishVideo_Finished ="document.querySelector('#video-up-app > div.video-entrance > div.upload-body > div > div.banner-entry > div.banner-entry-right > div') !== null"
    var jsPath_PublishVideo ="#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(17) > div > div > span"
    private fun updatePostDescription(){
        WebviewUtils.addValueToInput(webView,"#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div.form-item.form-item-short-margin > div > div.video-title-content > div.input.input-container > div > input",videoInfo.title+videoInfo.datetime)
        WebviewUtils.addValueToDiv(webView,"#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(7) > div > div.desc-text-wrp > div > div.editor.ql-container > div.ql-editor.ql-blank",videoInfo.description)
        WebviewUtils.simpleElementClick(webView,"#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(8) > div > div.time-switch-wrp > div")
        val datetime1 = videoInfo.datetime.substring(0,8)
        val datetime2 = videoInfo.datetime.substring(8)
        setDatePickerInput("#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(8) > div > div.time-switch-wrp > div.time-picker > div > div > div:nth-child(2) > div",datetime1)
        setTimePickerInput("#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(8) > div > div.time-switch-wrp > div.time-picker > div > div > div:nth-child(3) > div",datetime2)
        // åœ¨ä¸»çº¿ç¨‹ä¸­è®¾ç½®å»¶è¿Ÿæ‰§è¡Œ
        threadHandler.postDelayed(Runnable {
            startToPublishVideo()
        }, 5000)
    }
    override fun checkIfContentLoaded() {
        webView.postDelayed({
            webView.evaluateJavascript(jsCode_CheckContentLoaded) { result ->
                if (result == "true") {
                    simulateSwipeAndUploadVideo()
                } else {
                    webView.postDelayed({
                        checkIfContentLoaded()
                    }, 1000) // 1秒后再次检查
                }
            }
        }, 1000) // æ¯ç§’检查一次
    }
    private fun startToPublishVideo(){
        WebviewUtils.simpleElementClick(webView, jsPath_PublishVideo)
        checkVideoPublishFinished()
    }
    private fun checkVideoUploadFinished(){
        webView.postDelayed({
            webView.evaluateJavascript(jsCode_CheckVideoUploadFinished) { result ->
                if (result == "true") {
                    // ç­‰å¾…视频检测和生成封面
                    threadHandler.postDelayed({updatePostDescription()},3000)
                } else {
                    // å…ƒç´ ä¸å­˜åœ¨ï¼Œ1秒后再次检查
                    webView.postDelayed({
                        checkVideoUploadFinished()
                    }, 1000) // 1秒后再次检查
                }
            }
        }, 1000) // æ¯ç§’检查一次
    }
    private fun checkVideoPublishFinished(){
        webView.postDelayed({
            webView.evaluateJavascript(jsCode_PublishVideo_Finished) { result ->
                if (result == "true") {
                    // video published successfully!!!
                    activity.checkAndStartNextTask()
                } else {
                    // å…ƒç´ ä¸å­˜åœ¨ï¼Œ1秒后再次检查
                    webView.postDelayed({
                        checkVideoPublishFinished()
                    }, 1000) // 1秒后再次检查
                }
            }
        }, 1000) // æ¯ç§’检查一次
    }
    private fun setDatePickerInput(jsPath: String, targetValue: String) {
        var datetimes = Utils.validateAndReturnDateTime(targetValue) ?: return
        var dpPanelText = datetimes[0].toString()+"å¹´"+datetimes[1].toString()+"月";
        var dateRowColum = Utils.getDatePosition(datetimes[0],datetimes[1],datetimes[2])?:return;
        val jsCode = """
       try {
           var dp = document.querySelector('${jsPath}');
           dp.focus(); // ç¡®ä¿è¾“入框获得焦点
           dp.click();
           // need time to popup date-picker
           setTimeout(() => {
               var dpPanel = document.querySelector('.date-picker-container');
               var dpPanelSpan = dpPanel.querySelector('div > p');
               if (dpPanelSpan && dpPanelSpan.textContent != '${dpPanelText}'){
                  document.querySelector('#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(8) > div > div.time-switch-wrp > div.time-picker > div > div > div:nth-child(2) > div.date-picker-container > div.date-picker-nav-wrp > svg.next-btn-day.icon-sprite.icon-sprite-ic_into').click();
               }
               document.querySelector('div > div > div > div > div:nth-child(1) > div.semi-datepicker-month > div.semi-datepicker-weeks > div:nth-child(${dateRowColum[0]}) > div:nth-child(${dateRowColum[1]})').click()
               //switch to time selection
               document.querySelector('#video-up-app > div.video-basic-wrp > div.video-basic > div.form > div:nth-child(8) > div > div.time-switch-wrp > div.time-picker > div > div > div:nth-child(2) > div.date-picker-container > div.date-picker-nav-wrp > svg.next-btn-day.icon-sprite.icon-sprite-ic_into').click();
               setTimeout(() => {
                  dpPanel.querySelector('div > div > div > div.semi-datepicker-tpk > div > div > div.semi-scrolllist-body > div.semi-scrolllist-item-wheel.undefined-list-hour > div.semi-scrolllist-list-outer > ul > li:nth-child(${(datetimes[3]+1)})').click();
                  dpPanel.querySelector('div > div > div > div.semi-datepicker-tpk > div > div > div.semi-scrolllist-body > div.semi-scrolllist-item-wheel.undefined-list-minute > div.semi-scrolllist-list-outer > ul > li:nth-child(${(datetimes[4]+1)})').click();
               }, 500);
           }, 500);
            } catch (error) {
                console.error('设置日期时发生错误:', error);
            }
        """.trimIndent()
        // åœ¨ WebView ä¸­æ‰§è¡Œ JavaScript ä»£ç 
        webView.evaluateJavascript(jsCode, null)
    }
    private fun setTimePickerInput(jsPath: String, targetValue: String) {
        // è§£æžåˆ†ç§’字符串,假设格式为 "MMSS"
        val minutes = targetValue.substring(0, 2).toIntOrNull() ?: return // èŽ·å–å‰ä¸¤ä¸ªå­—ç¬¦ä½œä¸ºåˆ†é’Ÿï¼Œå¦‚æžœè½¬æ¢å¤±è´¥åˆ™è¿”å›ž
        val seconds = targetValue.substring(2, 4).toIntOrNull() ?: return // èŽ·å–åŽä¸¤ä¸ªå­—ç¬¦ä½œä¸ºç§’ï¼Œå¦‚æžœè½¬æ¢å¤±è´¥åˆ™è¿”å›ž
        // æž„建要执行的 JavaScript ä»£ç 
        val jsCode = """
            try {
                setTimeout(() => {
                    var minuteSelector = document.querySelector('.minute-selector-class');
                    var secondSelector = document.querySelector('.second-selector-class');
                    if (minuteSelector && secondSelector) {
                        minuteSelector.value = ${minutes};
                        secondSelector.value = ${seconds};
                    }
                }, 500); // å»¶è¿Ÿæ—¶é—´å¯èƒ½éœ€è¦æ ¹æ®å®žé™…情况调整
            } catch (error) {
                console.error('设置时间时发生错误:', error);
            }
        """.trimIndent()
        // åœ¨ WebView ä¸­æ‰§è¡Œ JavaScript ä»£ç 
        webView.evaluateJavascript(jsCode, null)
    }
    private fun addValueToDatePickerInput(first:Boolean, jsPath: String, targetValue: String) {
        var datetimes = Utils.validateAndReturnDateTime(targetValue) ?: return
        var dpPanelText = datetimes[0].toString()+"å¹´ "+datetimes[1].toString()+"月";
        var dateRowColum = Utils.getDatePosition(datetimes[0], datetimes[1], datetimes[2]) ?:return;
        val jsCode = """
       try {
           var dp = document.querySelector('${jsPath}');
           dp.focus(); // ç¡®ä¿è¾“入框获得焦点
           dp.click();
           // need time to popup date-picker
           setTimeout(() => {
               var dpPanel = document.querySelector('.semi-popover-content');
               var dpPanelSpan = dpPanel.querySelector('div > div > div > div:nth-child(1) > div.semi-datepicker-navigation > div > button > span > span');
               if (dpPanelSpan && dpPanelSpan.textContent != '${dpPanelText}'){
                  dpPanel.querySelector('div > div > div > div > div:nth-child(1) > div.semi-datepicker-navigation > button:nth-child(3)').click();
               }
               dpPanel.querySelector('div > div > div > div > div:nth-child(1) > div.semi-datepicker-month > div.semi-datepicker-weeks > div:nth-child(${dateRowColum[0]}) > div:nth-child(${dateRowColum[1]})').click()
               //switch to time selection
               dpPanel.querySelector('div > div > div > div > div.semi-datepicker-switch > div.semi-datepicker-switch-time').click();
               setTimeout(() => {
                  dpPanel.querySelector('div > div > div > div.semi-datepicker-tpk > div > div > div.semi-scrolllist-body > div.semi-scrolllist-item-wheel.undefined-list-hour > div.semi-scrolllist-list-outer > ul > li:nth-child(${(datetimes[3]+1)})').click();
                  dpPanel.querySelector('div > div > div > div.semi-datepicker-tpk > div > div > div.semi-scrolllist-body > div.semi-scrolllist-item-wheel.undefined-list-minute > div.semi-scrolllist-list-outer > ul > li:nth-child(${(datetimes[4]+1)})').click();
               }, 500);
           }, 500);
       } catch (error) {
        console.error('发生错误:', error);
       }
    """
        webView.evaluateJavascript(jsCode,null)
    }
    private fun simulateSwipeAndUploadVideo() {
        val instrumentation = Instrumentation()
        val displayMetrics = activity.resources.displayMetrics
        val width = displayMetrics.widthPixels
        val height = displayMetrics.heightPixels
        val startX = width.toFloat() * 0.9f // ä»Žå³ä¾§æ»‘动
        val endX = width.toFloat() * 0.1f // æ»‘动到左侧
        val y = height / 3f // Y åæ ‡åœ¨å±å¹•中间
        Thread {
            Utils.instrumentationSwipe(instrumentation, startX, y, endX, y)
            SystemClock.sleep(500)
            Utils.instrumentationSwipe(instrumentation, startX, y, endX, y)
            SystemClock.sleep(500)
            Utils.instrumentationClick(instrumentation, width / 2f, height * 2 / 4f)
            // back to main thread
            threadHandler.post {
                checkVideoUploadFinished()
            }
        }.start()
    }
}
app/src/main/java/com/shsening/autouploadvideos/action/ActionRedbook.kt
New file
@@ -0,0 +1,173 @@
package com.shsening.autouploadvideos
import android.app.Instrumentation
import android.content.Context
import android.os.SystemClock
import android.os.Handler
import android.os.Bundle
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.shsening.autouploadvideos.action.PlatformActionInterface
import com.shsening.autouploadvideos.utils.Utils
class ActionRedbook (private var activity: UploadSessionActivity, private var threadHandler: Handler, private var videoInfo: Utils.VideoUploadTaskInfo):
    PlatformActionInterface {
    private var webView = activity.sessionProfileWebView
    var jsCode_CheckContentLoaded = """
        document.querySelector('input[type="file"][class="upload-input"]') !== null
    """.trimIndent()
    var jsCode_CheckVideoUploadFinished = """
        document.querySelector("#publish-container > div.post-page > div.body > div.content > div.media-area-new > div > div > div.content > div.operator > span:nth-child(1)") !==null
    """.trimIndent()
    var jsCode_PublishVideo_Finished ="document.querySelector('#web > div > div > div > div.upload-content > div.tips-wrapper > div:nth-child(3) > div > p:nth-child(3)') !== null"
    var jsPath_PublishVideo ="button.publishBtn"
    private fun updatePostDescription(){
        WebviewUtils.addValueToInput(webView,"#publish-container > div > div.body > div.content > div.input.titleInput > div.d-input-wrapper.d-inline-block.c-input_inner > div > input",videoInfo.title)
        WebviewUtils.addValueToDiv(webView,"#quillEditor > div > p",videoInfo.description)
        WebviewUtils.simpleElementClick(webView,"#topicBtn")
        SystemClock.sleep(500)
        WebviewUtils.simpleElementClick(webView,"#quill-mention-item-0")
        WebviewUtils.simpleElementClick(webView,"#topicBtn")
        SystemClock.sleep(500)
        WebviewUtils.simpleElementClick(webView,"#quill-mention-item-1")
//        WebviewUtils.simpleElementClick(webView,"#el-id-3410-26 > label:nth-child(1)")
        WebviewUtils.simpleElementClick(webView,"html > body > div:nth-of-type(1) > div > div:nth-of-type(2) > div > div:nth-of-type(2) > main > div:nth-of-type(3) > div > div > div:nth-of-type(1) > div > div > div > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(10) > div > div:nth-of-type(5) > div:nth-of-type(2) > label:nth-of-type(2)")
        addValueToDatePickerInput(true,"html > body > div:nth-of-type(1) > div > div:nth-of-type(2) > div > div:nth-of-type(2) > main > div:nth-of-type(3) > div > div > div:nth-of-type(1) > div > div > div > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(10) > div > div:nth-of-type(5) > div:nth-of-type(2) > div > div:nth-of-type(1) > div",videoInfo.datetime)
        // åœ¨ä¸»çº¿ç¨‹ä¸­è®¾ç½®å»¶è¿Ÿæ‰§è¡Œ
        threadHandler.postDelayed(Runnable {
            startToPublishVideo()
        }, 5000)
    }
    override fun checkIfContentLoaded() {
        webView.postDelayed({
            webView.evaluateJavascript(jsCode_CheckContentLoaded) { result ->
                if (result == "true") {
                    simulateSwipeAndUploadVideo()
                } else {
                    webView.postDelayed({
                        checkIfContentLoaded()
                    }, 1000) // 1秒后再次检查
                }
            }
        }, 1000) // æ¯ç§’检查一次
    }
    private fun startToPublishVideo(){
        WebviewUtils.simpleElementClick(webView,jsPath_PublishVideo)
        checkVideoPublishFinished()
    }
    private fun checkVideoUploadFinished(){
        webView.postDelayed({
            webView.evaluateJavascript(jsCode_CheckVideoUploadFinished) { result ->
                if (result == "true") {
                    // ç­‰å¾…视频检测和生成封面
                    threadHandler.postDelayed({updatePostDescription()},3000)
                } else {
                    // å…ƒç´ ä¸å­˜åœ¨ï¼Œ1秒后再次检查
                    webView.postDelayed({
                        checkVideoUploadFinished()
                    }, 1000) // 1秒后再次检查
                }
            }
        }, 1000) // æ¯ç§’检查一次
    }
    private fun checkVideoPublishFinished(){
        webView.postDelayed({
            webView.evaluateJavascript(jsCode_PublishVideo_Finished) { result ->
                if (result == "true") {
                    // video published successfully!!!
                    activity.checkAndStartNextTask()
                } else {
                    // å…ƒç´ ä¸å­˜åœ¨ï¼Œ1秒后再次检查
                    webView.postDelayed({
                        checkVideoPublishFinished()
                    }, 1000) // 1秒后再次检查
                }
            }
        }, 1000) // æ¯ç§’检查一次
    }
    private fun addValueToDatePickerInput(first:Boolean, jsPath: String, targetValue: String) {
        var datetimes = Utils.validateAndReturnDateTime(targetValue) ?: return
        var dpPanelText = datetimes[0].toString()+"å¹´ "+datetimes[1].toString()+"月";
        var dateRowColum = Utils.getDatePosition(datetimes[0],datetimes[1],datetimes[2])?:return;
        val jsCode = """
       try {
           var dp = document.querySelector('${jsPath}');
           dp.focus(); // ç¡®ä¿è¾“入框获得焦点
           dp.click();
           // need time to popup date-picker
           setTimeout(() => {
               var dpPanel = document.querySelector('.semi-popover-content');
               var dpPanelSpan = dpPanel.querySelector('div > div > div > div:nth-child(1) > div.semi-datepicker-navigation > div > button > span > span');
               if (dpPanelSpan && dpPanelSpan.textContent != '${dpPanelText}'){
                  dpPanel.querySelector('div > div > div > div > div:nth-child(1) > div.semi-datepicker-navigation > button:nth-child(3)').click();
               }
               dpPanel.querySelector('div > div > div > div > div:nth-child(1) > div.semi-datepicker-month > div.semi-datepicker-weeks > div:nth-child(${dateRowColum[0]}) > div:nth-child(${dateRowColum[1]})').click()
               //switch to time selection
               dpPanel.querySelector('div > div > div > div > div.semi-datepicker-switch > div.semi-datepicker-switch-time').click();
               setTimeout(() => {
                  dpPanel.querySelector('div > div > div > div.semi-datepicker-tpk > div > div > div.semi-scrolllist-body > div.semi-scrolllist-item-wheel.undefined-list-hour > div.semi-scrolllist-list-outer > ul > li:nth-child(${(datetimes[3]+1)})').click();
                  dpPanel.querySelector('div > div > div > div.semi-datepicker-tpk > div > div > div.semi-scrolllist-body > div.semi-scrolllist-item-wheel.undefined-list-minute > div.semi-scrolllist-list-outer > ul > li:nth-child(${(datetimes[4]+1)})').click();
               }, 500);
           }, 500);
       } catch (error) {
        console.error('发生错误:', error);
       }
    """
        webView.evaluateJavascript(jsCode,null)
    }
    private fun simulateSwipeAndUploadVideo() {
        val instrumentation = Instrumentation()
        val displayMetrics = activity.resources.displayMetrics
        val width = displayMetrics.widthPixels
        val height = displayMetrics.heightPixels
        val startX = width.toFloat() * 0.9f // ä»Žå³ä¾§æ»‘动
        val endX = width.toFloat() * 0.1f // æ»‘动到左侧
        val y = height / 3f // Y åæ ‡åœ¨å±å¹•中间
        Thread {
            Utils.instrumentationSwipe(instrumentation, startX, y, endX, y)
            SystemClock.sleep(500)
            Utils.instrumentationSwipe(instrumentation, startX, y, endX, y)
            SystemClock.sleep(500)
            Utils.instrumentationClick(instrumentation, width / 2f, height * 2 / 4f)
            // back to main thread
            threadHandler.post {
                checkVideoUploadFinished()
            }
        }.start()
    }
}
app/src/main/java/com/shsening/autouploadvideos/action/ActionShipinhao.kt
@@ -16,12 +16,12 @@
    var jsCode_CheckContentLoaded = """
        document.querySelector("#container-wrap > div.container-center > div > div > div.main-body-wrap.post-create > div.main-body > div > div.post-edit-wrap.material-edit-wrap > div.material > div > div > div > span > div") !== null
        document.querySelector("#container-wrap > div.container-center > div > div > div.main-body-wrap.post-create > div.main-body > div > div.post-edit-wrap.material-edit-wrap > div.material > div > div > div > span > div > span > input[type=file]") !== null
    """.trimIndent()
    var jsCode_CheckVideoUploadFinished = """
        document.querySelector("#container-wrap > div.container-center > div > div > div.main-body-wrap.post-create > div.main-body > div > div.post-edit-wrap.material-edit-wrap > div.material > div.preview > div > div.media-opr > div") !==null
        document.querySelector("#container-wrap > div.container-center > div > div > div.main-body-wrap.post-create > div.main-body > div > div.post-edit-wrap.material-edit-wrap > div.form > div:nth-child(1) > div.form-item-body > div > div.video-cover > div.weui-desktop-popover__wrp.pure-text-popover > span > div") !==null
    """.trimIndent()
    var jsCode_PublishVideo_Finished ="document.querySelector('#container-wrap > div.container-center > div > div.main-body-wrap > div.main-body > div.header-wrap > span') !==null"
    var jsCode_PublishVideo_Finished ="document.querySelector('#footer > div.main-part > div.left-links > a:nth-child(3)') !==null"
    var jsPath_PublishVideo ="#container-wrap > div.container-center > div > div > div.main-body-wrap.post-create > div.main-body > div > div.post-edit-wrap.material-edit-wrap > div.form > div.form-btns > div:nth-child(5) > span > div > button"
δÃüÃû
Binary files differ