Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ object Authors {
val LampDelivery = Author("LampDelivery", 650805815623680030L)
val Ty = Author("Ty", 487443883127472129L)
val miaaaa0a = Author("miaaaa0a", 435750383491481602L)
val Cloudburst = Author("Cloudburst", 295186738085756929L)
val HalalKing = Author("HalalKing", 261634919980204033L)
}

/**
Expand Down
13 changes: 13 additions & 0 deletions plugins/DeleteEmbeds/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import com.aliucord.gradle.repo.Authors
import com.aliucord.gradle.repo.author

plugins {
id("com.aliucord.plugins-repo")
}

version = "1.1.5"
description = "Delete embeds."

aliucord {
author(Authors.Cloudburst)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package cloudburst.plugins.deleteembeds

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.aliucord.Constants
import androidx.core.content.res.ResourcesCompat
import androidx.core.widget.NestedScrollView
import com.aliucord.annotations.AliucordPlugin
import com.aliucord.entities.Plugin
import com.aliucord.fragments.InputDialog
import com.aliucord.patcher.Hook
import com.discord.databinding.WidgetChatListActionsBinding
import com.discord.utilities.color.ColorCompat
import com.discord.stores.StoreStream
import com.discord.widgets.chat.list.actions.WidgetChatListActions
import com.lytefast.flexinput.R
import java.lang.reflect.InvocationTargetException
import com.aliucord.Utils
import com.aliucord.utils.GsonUtils
import com.aliucord.Http
import com.google.gson.JsonObject

@AliucordPlugin
class DeleteEmbeds : Plugin() {
@SuppressLint("SetTextI18n")
override fun start(context: Context) {
val icon = ContextCompat.getDrawable(context, R.e.ic_clear_24dp)
val deleteEmbedId = View.generateViewId()

with(WidgetChatListActions::class.java, {
val getBinding = getDeclaredMethod("getBinding").apply { isAccessible = true }

patcher.patch(getDeclaredMethod("configureUI", WidgetChatListActions.Model::class.java), Hook { callFrame ->
try {
val message = (callFrame.args[0] as WidgetChatListActions.Model).message

val binding = getBinding.invoke(callFrame.thisObject) as WidgetChatListActionsBinding
val deleteEmbed = binding.a.findViewById<TextView>(deleteEmbedId).apply {
if (message.hasEmbeds()) {
visibility = if ((callFrame.args[0] as WidgetChatListActions.Model).manageMessageContext.canDelete)
View.VISIBLE else View.GONE
} else if (message.hasAttachments() && !message.content.isEmpty()) {
visibility = if (message.author.id == StoreStream.getUsers().me.id)
View.VISIBLE else View.GONE
} else {
visibility = View.GONE
}
}

if (!deleteEmbed.hasOnClickListeners()) deleteEmbed.setOnClickListener {
try {
Utils.threadPool.execute {
if (message.hasEmbeds()) {
deleteEmbed(message.channelId, message.id)
}
if (message.hasAttachments() && message.author.id == StoreStream.getUsers().me.id) {
deleteAttachements(message.channelId, message.id)
}
}
(callFrame.thisObject as WidgetChatListActions).dismiss()
} catch (e: IllegalAccessException) {
Utils.showToast("Internal error occured.")
e.printStackTrace()
} catch (e: InvocationTargetException) {
Utils.showToast("Internal error occured.")
e.printStackTrace()
}
}
} catch (ignored: Throwable) {
}
})

patcher.patch(getDeclaredMethod("onViewCreated", View::class.java, Bundle::class.java), Hook { callFrame ->
val linearLayout = (callFrame.args[0] as NestedScrollView).getChildAt(0) as LinearLayout
val ctx = linearLayout.context
val idx = linearLayout.indexOfChild(linearLayout.findViewById(Utils.getResId("dialog_chat_actions_delete", "id"))) + 1

icon?.setTint(ColorCompat.getThemedColor(ctx, R.b.colorInteractiveNormal))

val deleteEmbed = TextView(ctx, null, 0, R.i.UiKit_Settings_Item_Icon).apply {
text = ctx.getString(R.h.delete) + " embed"
id = deleteEmbedId
setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
typeface = ResourcesCompat.getFont(ctx, Constants.Fonts.whitney_medium)
}

linearLayout.addView(deleteEmbed, idx)
})
})
}

override fun stop(context: Context) = patcher.unpatchAll()

fun deleteEmbed(channelId: Long, msgId: Long) {
Http.Request.newDiscordRequest("/channels/%d/messages/%d".format(channelId, msgId), "PATCH")
.setHeader("Referer", "https://discord.com/channels/%d/%d".format(channelId, msgId))
.executeWithJson(GsonUtils.fromJson("{\"flags\":4}", JsonObject::class.java))
}

fun deleteAttachements(channelId: Long, msgId: Long) {
Http.Request.newDiscordRequest("/channels/%d/messages/%d".format(channelId, msgId), "PATCH")
.setHeader("Referer", "https://discord.com/channels/%d/%d".format(channelId, msgId))
.executeWithJson(GsonUtils.fromJson("{\"attachments\":[]}", JsonObject::class.java))
}
}
13 changes: 13 additions & 0 deletions plugins/EditWebhooks/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import com.aliucord.gradle.repo.Authors
import com.aliucord.gradle.repo.author

plugins {
id("com.aliucord.plugins-repo")
}

version = "1.1.13"
description = "Edit Webhooks."

aliucord {
author(Authors.Cloudburst)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package cloudburst.plugins.editwebhooks

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.widget.NestedScrollView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.aliucord.annotations.AliucordPlugin
import com.aliucord.entities.Plugin
import com.aliucord.fragments.InputDialog
import com.aliucord.patcher.Hook
import androidx.core.content.res.ResourcesCompat
import com.discord.utilities.color.ColorCompat
import com.discord.widgets.channels.settings.WidgetTextChannelSettings
import com.discord.databinding.WidgetTextChannelSettingsBinding
import com.lytefast.flexinput.R
import java.lang.reflect.InvocationTargetException
import com.aliucord.utils.ReflectUtils
import com.aliucord.Constants
import com.discord.stores.StoreStream
import com.aliucord.fragments.ConfirmDialog
import com.aliucord.Utils
import com.aliucord.utils.GsonUtils
import com.aliucord.Http
import com.google.gson.JsonObject
import com.discord.utilities.rest.RestAPI
import com.discord.utilities.analytics.AnalyticSuperProperties
import com.aliucord.patcher.Patcher
import cloudburst.plugins.editwebhooks.ui.WebhookList

@AliucordPlugin
class EditWebhooks : Plugin() {
@SuppressLint("SetTextI18n")
override fun start(context: Context) {
val iconLeft = ContextCompat.getDrawable(context, R.e.ic_publish_24dp)
val iconRight = ContextCompat.getDrawable(context, R.e.icon_carrot)
val editWebooksId = View.generateViewId()

with(WidgetTextChannelSettings::class.java, {
val getBinding = getDeclaredMethod("getBinding").apply { isAccessible = true }

patcher.patch(getDeclaredMethod("configureUI", WidgetTextChannelSettings.Model::class.java), Hook { callFrame ->
try {
val channel = (callFrame.args[0] as WidgetTextChannelSettings.Model).channel


val binding = getBinding.invoke(callFrame.thisObject) as WidgetTextChannelSettingsBinding

binding.a.findViewById<TextView>(editWebooksId).apply {
visibility = View.VISIBLE
setOnClickListener {
val list = WebhookList(channel)
Utils.openPageWithProxy(Utils.appActivity, list)
}
isClickable = true
}
} catch (ignored: Throwable) {
logger.error(ignored)
}
})

patcher.patch(getDeclaredMethod("onViewBound", View::class.java), Hook { callFrame ->
val coordinatorLayout = (callFrame.args[0] as CoordinatorLayout)
val nestedScrollView = coordinatorLayout.getChildAt(1) as NestedScrollView
val linearLayout = nestedScrollView.findViewById(Utils.getResId("channel_settings_section_privacy_safety", "id")) as LinearLayout
val ctx = linearLayout.context

iconLeft?.setTint(ColorCompat.getThemedColor(ctx, R.b.colorInteractiveNormal))
iconRight?.setTint(ColorCompat.getThemedColor(ctx, R.b.colorInteractiveNormal))

val editWebhooks = TextView(ctx, null, 0, R.i.UiKit_Settings_Item_Icon).apply {
text = ctx.getString(R.h.edit) + " webhooks"
id = editWebooksId
setCompoundDrawablesRelativeWithIntrinsicBounds(iconLeft, null, iconRight, null)
typeface = ResourcesCompat.getFont(ctx, Constants.Fonts.whitney_medium)
}

linearLayout.addView(editWebhooks)
})
})
}

override fun stop(context: Context) = patcher.unpatchAll()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package cloudburst.plugins.editwebhooks.ui

import android.graphics.Color
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RectShape
import android.view.View
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.aliucord.views.Divider
import com.aliucord.Utils
import com.aliucord.api.SettingsAPI
import com.aliucord.fragments.SettingsPage
import com.aliucord.utils.DimenUtils
import com.aliucord.fragments.InputDialog
import com.aliucord.wrappers.ChannelWrapper
import cloudburst.plugins.editwebhooks.ui.WebhookRecyclerAdapter
import com.discord.api.channel.Channel
import com.aliucord.utils.GsonUtils
import cloudburst.plugins.editwebhooks.utils.Webhook
import cloudburst.plugins.editwebhooks.utils.WebhookRequest
import com.aliucord.Http
import com.aliucord.views.Button
import com.lytefast.flexinput.R

class WebhookList(val channelRaw: Channel) : SettingsPage() {

private val channel = ChannelWrapper(channelRaw)

override fun onViewBound(view: View) {
super.onViewBound(view)
setActionBarTitle(channel.name)

fetchList()
}

public fun fetchList() {
val context = requireContext()
val createWebhookI18n = context.getString(R.h.create) + " webhook"
Utils.threadPool.execute {
val list = Http.Request.newDiscordRequest("/channels/%d/webhooks".format(channel.id))
.setHeader("Referer", "https://discord.com/channels/%d/%d".format(channel.guildId, channel.id))
.execute()
.json(Array<Webhook>::class.java)


Utils.mainThread.post {
clear()
val shape = ShapeDrawable(RectShape())
.apply {
setTint(Color.TRANSPARENT)
intrinsicHeight = DimenUtils.defaultPadding
}

val decoration = DividerItemDecoration(
context,
DividerItemDecoration.VERTICAL
).apply {
setDrawable(shape)
}

val recyclerView = RecyclerView(context)
.apply {
adapter = WebhookRecyclerAdapter(list.toList(), this@WebhookList)
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
addItemDecoration(decoration)
}

addView(recyclerView)

val addButton = Button(context).apply {
text = createWebhookI18n
setOnClickListener {
val inDialog = InputDialog()
.setTitle(createWebhookI18n)
.setDescription("Enter name of the webhook")
.setPlaceholderText("Webhook Name")
inDialog.setOnOkListener {
Utils.threadPool.execute {
createWebhook(inDialog.input.toString().trim())
}
inDialog.dismiss()
}
inDialog.show(parentFragmentManager, "CreateWebhook")
}
}

addView(Divider(context))
addView(addButton)
}
}
}

private fun createWebhook(name: String) {
Http.Request.newDiscordRequest("/channels/%s/webhooks".format(channel.id), "POST")
.executeWithJson(WebhookRequest(name, null))
Utils.showToast("Webhook created")
fetchList()
}
}
Loading