fix scheduling posts (#4392)

Mastodon returns different reponses when posting normally and when
scheduling. This was previously ignored silently, but Moshi is more
correct than Gson and fails, which causes the `SendStatusService` to
retry sending forever and a lot of posts are scheduled.
Mastodon should actually ignore multiple attempts at scheduling the same
post, but doesn't so I filed this
https://github.com/mastodon/mastodon/issues/30039

cc @cbeyls
This commit is contained in:
Konrad Pozniak 2024-04-25 17:08:57 +02:00 committed by GitHub
parent f2ffba1679
commit c55d79562c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 12 deletions

View File

@ -4,6 +4,7 @@ import com.keylesspalace.tusky.TabData
import com.keylesspalace.tusky.entity.Account import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Notification import com.keylesspalace.tusky.entity.Notification
import com.keylesspalace.tusky.entity.Poll import com.keylesspalace.tusky.entity.Poll
import com.keylesspalace.tusky.entity.ScheduledStatus
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
data class StatusChangedEvent(val status: Status) : Event data class StatusChangedEvent(val status: Status) : Event
@ -13,7 +14,7 @@ data class BlockEvent(val accountId: String) : Event
data class MuteEvent(val accountId: String) : Event data class MuteEvent(val accountId: String) : Event
data class StatusDeletedEvent(val statusId: String) : Event data class StatusDeletedEvent(val statusId: String) : Event
data class StatusComposedEvent(val status: Status) : Event data class StatusComposedEvent(val status: Status) : Event
data class StatusScheduledEvent(val status: Status) : Event data class StatusScheduledEvent(val scheduledStatus: ScheduledStatus) : Event
data class ProfileEditedEvent(val newProfileData: Account) : Event data class ProfileEditedEvent(val newProfileData: Account) : Event
data class PreferenceChangedEvent(val preferenceKey: String) : Event data class PreferenceChangedEvent(val preferenceKey: String) : Event
data class MainTabsChangedEvent(val newTabs: List<TabData>) : Event data class MainTabsChangedEvent(val newTabs: List<TabData>) : Event

View File

@ -199,6 +199,14 @@ interface MastodonApi {
@Body status: NewStatus @Body status: NewStatus
): NetworkResult<Status> ): NetworkResult<Status>
@POST("api/v1/statuses")
suspend fun createScheduledStatus(
@Header("Authorization") auth: String,
@Header(DOMAIN_HEADER) domain: String,
@Header("Idempotency-Key") idempotencyKey: String,
@Body status: NewStatus
): NetworkResult<ScheduledStatus>
@GET("api/v1/statuses/{id}") @GET("api/v1/statuses/{id}")
suspend fun status(@Path("id") statusId: String): NetworkResult<Status> suspend fun status(@Path("id") statusId: String): NetworkResult<Status>

View File

@ -49,6 +49,7 @@ import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.MediaAttribute import com.keylesspalace.tusky.entity.MediaAttribute
import com.keylesspalace.tusky.entity.NewPoll import com.keylesspalace.tusky.entity.NewPoll
import com.keylesspalace.tusky.entity.NewStatus import com.keylesspalace.tusky.entity.NewStatus
import com.keylesspalace.tusky.entity.ScheduledStatus
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
@ -256,13 +257,24 @@ class SendStatusService : Service(), Injectable {
} }
) )
val scheduled = !statusToSend.scheduledAt.isNullOrEmpty()
val sendResult = if (isNew) { val sendResult = if (isNew) {
if (!scheduled) {
mastodonApi.createStatus( mastodonApi.createStatus(
"Bearer " + account.accessToken, "Bearer " + account.accessToken,
account.domain, account.domain,
statusToSend.idempotencyKey, statusToSend.idempotencyKey,
newStatus newStatus
) )
} else {
mastodonApi.createScheduledStatus(
"Bearer " + account.accessToken,
account.domain,
statusToSend.idempotencyKey,
newStatus
)
}
} else { } else {
mastodonApi.editStatus( mastodonApi.editStatus(
statusToSend.statusId!!, statusToSend.statusId!!,
@ -282,14 +294,12 @@ class SendStatusService : Service(), Injectable {
mediaUploader.cancelUploadScope(*statusToSend.media.map { it.localId }.toIntArray()) mediaUploader.cancelUploadScope(*statusToSend.media.map { it.localId }.toIntArray())
val scheduled = !statusToSend.scheduledAt.isNullOrEmpty()
if (scheduled) { if (scheduled) {
eventHub.dispatch(StatusScheduledEvent(sentStatus)) eventHub.dispatch(StatusScheduledEvent(sentStatus as ScheduledStatus))
} else if (!isNew) { } else if (!isNew) {
eventHub.dispatch(StatusChangedEvent(sentStatus)) eventHub.dispatch(StatusChangedEvent(sentStatus as Status))
} else { } else {
eventHub.dispatch(StatusComposedEvent(sentStatus)) eventHub.dispatch(StatusComposedEvent(sentStatus as Status))
} }
notificationManager.cancel(statusId) notificationManager.cancel(statusId)