Skip to content

Commit

Permalink
Merge pull request #503 from crimera/dev
Browse files Browse the repository at this point in the history
chore: Merge branch `dev` to `main`
  • Loading branch information
crimera authored Jan 7, 2025
2 parents 5aa2990 + 4db32a4 commit 0002c81
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 131 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ jobs:
uses: actions/checkout@v4

- name: Open pull request
run: gh pr create -d -B main -H dev --title '${{ env.TITLE }}' --body '${{ env.BODY }}' || gh pr edit -B main --title '${{ env.TITLE }}' --body '${{ env.BODY }}'
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GH_TOKEN: ${{ github.token }}
run: gh pr create -d -B main -H dev --title '${{ env.TITLE }}' --body '${{ env.BODY }}' || gh pr edit -B main --title '${{ env.TITLE }}' --body '${{ env.BODY }}'
14 changes: 11 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
## [1.47.1](https://github.com/crimera/piko/compare/v1.47.0...v1.47.1) (2024-12-22)
## [1.48.0-dev.2](https://github.com/crimera/piko/compare/v1.48.0-dev.1...v1.48.0-dev.2) (2024-12-24)

### Bug Fixes
### Refactors

* Improve getUsername fingerprint ([af617af](https://github.com/crimera/piko/commit/af617af523bfa7df00a232a51364ea9e8ea4d34f))
* **Twitter:** Added 'Native features' section ([12d2bda](https://github.com/crimera/piko/commit/12d2bdaafd111eee81f22bdafa306c3493754c80))
* **Twitter:** Added Native download filename customization ([99a10b1](https://github.com/crimera/piko/commit/99a10b1615ffa3fb72df0ad283255e9c837a012f))

## [1.48.0-dev.1](https://github.com/crimera/piko/compare/v1.47.1-dev.1...v1.48.0-dev.1) (2024-12-22)

### Features

* **Translations:** Updated Traditional Chinese string-zh-rCN.xml ([6cc2373](https://github.com/crimera/piko/commit/6cc2373e417a1ed386a2682f970662e367033b43))
* **Translations:** Updated Traditional Chinese string-zh-rTW.xml ([6787c28](https://github.com/crimera/piko/commit/6787c28318762382d73f1eb8c6ad9abc4b2ee2e6))

## [1.47.1-dev.1](https://github.com/crimera/piko/compare/v1.47.0...v1.47.1-dev.1) (2024-12-22)

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 1.47.1
version = 1.48.0-dev.2
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
package crimera.patches.twitter.misc.shareMenu.nativeDownloader

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
import com.android.tools.smali.dexlib2.dexbacked.instruction.DexBackedInstruction35c
import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedMethodReference
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction

internal abstract class NativeDownloaderMethodFingerprint(
private val methodName: String,
) : MethodFingerprint(customFingerprint = { methodDef, classDef ->
methodDef.name == methodName && classDef.toString() == "Lapp/revanced/integrations/twitter/patches/NativeDownloader;"
})
methodDef.name == methodName && classDef.toString() == "Lapp/revanced/integrations/twitter/patches/NativeDownloader;"
})

internal object TweetObjectFingerprint : MethodFingerprint(strings = listOf("https://x.com/%1\$s/status/%2\$d"))

Expand All @@ -28,87 +30,110 @@ internal object GetTweetIdFingerprint : NativeDownloaderMethodFingerprint("getTw

internal object GetTweetUsernameFingerprint : NativeDownloaderMethodFingerprint("getTweetUsername")

internal object GetTweetProfileNameFingerprint : NativeDownloaderMethodFingerprint("getTweetProfileName")

internal object GetTweetUserIdFingerprint : NativeDownloaderMethodFingerprint("getTweetUserId")

internal object GetTweetMediaFingerprint : NativeDownloaderMethodFingerprint("getTweetMedia")

internal object GetUserNameMethodCaller : MethodFingerprint(
returnType = "Z", opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.RETURN
)
returnType = "V",
strings =
listOf(
"Ref_ID (Tweet ID)",
"Name",
"User Name",
),
)

@Patch(
compatiblePackages = [CompatiblePackage("com.twitter.android")],
)
class NativeDownloaderHooksPatch : BytecodePatch(
setOf(
GetTweetClassFingerprint,
GetTweetIdFingerprint,
GetTweetUsernameFingerprint,
GetTweetMediaFingerprint,
GetUserNameMethodCaller,
TweetObjectFingerprint,
),
) {
class NativeDownloaderHooksPatch :
BytecodePatch(
setOf(
GetTweetClassFingerprint,
GetTweetIdFingerprint,
GetTweetUsernameFingerprint,
GetTweetMediaFingerprint,
GetUserNameMethodCaller,
TweetObjectFingerprint,
GetTweetProfileNameFingerprint,
GetTweetUserIdFingerprint,
),
) {
private fun MutableMethod.changeFirstString(value: String) {
this.getInstructions().firstOrNull { it.opcode == Opcode.CONST_STRING }?.let { instruction ->
val register = (instruction as BuilderInstruction21c).registerA
this.replaceInstruction(instruction.location.index, "const-string v$register, \"$value\"")
} ?: throw PatchException("const-string not found for method: ${this.name}")
}

private fun Reference.getMethodFromReference(): Char {
val ref = this.toString()
val index = ref.indexOf("->")
return ref[index + 2]
}
private fun MethodFingerprintResult.getMethodName(index: Int): String =
(this.mutableMethod.getInstruction<ReferenceInstruction>(index).reference as DexBackedMethodReference).name

override fun execute(context: BytecodeContext) {
val getTweetObjectFingerprint = TweetObjectFingerprint.result ?: throw PatchException("bruh")
val getTweetObjectResult = TweetObjectFingerprint.result ?: throw PatchException("bruh")

val tweetObjectClass = getTweetObjectFingerprint.classDef
val tweetObjectClass = getTweetObjectResult.classDef
val tweetObjectClassName = tweetObjectClass.toString().removePrefix("L").removeSuffix(";")

val getIdMethod = tweetObjectClass.methods.firstOrNull { mutableMethod ->
mutableMethod.name == "getId"
} ?: throw PatchException("getIdMethod not found")
val getIdMethod =
tweetObjectClass.methods.firstOrNull { mutableMethod ->
mutableMethod.name == "getId"
} ?: throw PatchException("getIdMethod not found")

val getUserNameMethodCaller =
GetUserNameMethodCaller.result ?: throw PatchException("Could not find UserNameMethodCaller fingerprint")
val getUserNameMethodName = getUserNameMethodCaller.method.implementation?.instructions?.firstOrNull { t ->
t.opcode == Opcode.INVOKE_STATIC
}.let {
(it as DexBackedInstruction35c).reference.getMethodFromReference()
}

val getUsernameMethod = tweetObjectClass.methods.firstOrNull { mutableMethod ->
mutableMethod.name.contains(getUserNameMethodName) && mutableMethod.returnType == "Ljava/lang/String;"
} ?: throw PatchException("getUsernameMethod not found")
var getUsernameMethod = ""
var getProfileNameMethod = ""
getUserNameMethodCaller.scanResult.stringsScanResult!!.matches.forEach { match ->
val str = match.string
if (str == "Name") {
getProfileNameMethod = getUserNameMethodCaller.getMethodName(match.index + 1)
}
if (str == "User Name") {
getUsernameMethod = getUserNameMethodCaller.getMethodName(match.index + 1)
}
}

val getMediaObjectMethod = tweetObjectClass.methods.firstOrNull { methodDef ->
methodDef.implementation?.instructions?.map { it.opcode }?.toList() == listOf(
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.RETURN_OBJECT,
)
} ?: throw PatchException("getMediaObject not found")
val getTweetUserIdMethod =
getTweetObjectResult.classDef.methods
.last {
it.returnType.equals("J")
}.name

val getMediaObjectMethod =
tweetObjectClass.methods.firstOrNull { methodDef ->
methodDef.implementation
?.instructions
?.map { it.opcode }
?.toList() ==
listOf(
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.RETURN_OBJECT,
)
} ?: throw PatchException("getMediaObject not found")

GetTweetClassFingerprint.result?.mutableMethod?.changeFirstString(tweetObjectClassName)
?: throw GetTweetClassFingerprint.exception

GetTweetIdFingerprint.result?.mutableMethod?.changeFirstString(getIdMethod.name)
?: throw GetTweetIdFingerprint.exception

GetTweetUsernameFingerprint.result?.mutableMethod?.changeFirstString(getUsernameMethod.name)
GetTweetUsernameFingerprint.result?.mutableMethod?.changeFirstString(getUsernameMethod)
?: throw GetTweetUsernameFingerprint.exception

GetTweetProfileNameFingerprint.result?.mutableMethod?.changeFirstString(getProfileNameMethod)
?: throw GetTweetProfileNameFingerprint.exception

GetTweetUserIdFingerprint.result?.mutableMethod?.changeFirstString(getTweetUserIdMethod)
?: throw GetTweetUserIdFingerprint.exception

GetTweetMediaFingerprint.result?.mutableMethod?.changeFirstString(getMediaObjectMethod.name)
?: throw GetTweetMediaFingerprint.exception
}
Expand Down
22 changes: 13 additions & 9 deletions src/main/resources/twitter/settings/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,22 @@
<string name="piko_pref_download_media_link_handle_copy_media_link">نسخ رابط الوسائط</string>
<string name="piko_pref_download_media_link_handle_share_media_link">مشاركة رابط الوسائط</string>

<!-- خيارات التنزيل -->
<!-- محلي -->
<string name="piko_title_native">الميزات المحلية</string>
<string name="piko_title_native_downloader">برنامج التنزيل المحلي</string>
<string name="piko_title_native_downloader_toggle">تمكين التنزيل المحلي</string>
<string name="piko_pref_native_downloader_alert_title">تنزيل الوسائط</string>
<string name="piko_pref_native_downloader_download_all">تنزيل الكل</string>
<string name="piko_pref_native_downloader_no_media">لم يتم العثور على الوسائط</string>
<string name="piko_pref_native_downloader_filename_title">حفظ نمط اسم الملف</string>

<string name="piko_title_native_translator">المترجم المحلي للمنشورات</string>
<string name="piko_native_translator_toggle">تمكين ترجمة المنشور المحلي</string>
<string name="piko_native_translator_provider">مقدمي خدمات الترجمة</string>
<string name="piko_native_translator_to_lang">ترجم إلى</string>
<string name="piko_native_translator_zero_text">لم يتم العثور على نص للترجمة</string>
<string name="piko_native_translator_google">Google مترجم</string>
<string name="piko_native_translator_google_v2">مترجم Google V2</string>

<!-- إعدادات الإعلانات -->
<string name="piko_title_ads">الإعلانات</string>
Expand Down Expand Up @@ -121,7 +132,7 @@
<string name="piko_pref_customisation_sidebartabs">عناصر الشريط الجانبي المراد إخفاؤها</string>
<string name="piko_pref_customisation_navbartabs">عناصر شريط التنقل المراد إخفاؤها</string>
<string name="piko_pref_customisation_inlinetabs">عناصر الشريط المضمنة المراد إخفاؤها</string>
<string name="piko_pref_customisation_exploretabs">علامات تبويب استكشاف المراد إخفاؤها</string>
<string name="piko_pref_customisation_exploretabs">علامات تبويب استكشف المراد إخفاؤها</string>
<string name="piko_pref_customisation_searchtabs">علامات تبويب البحث المراد إخفاؤها</string>
<string name="piko_pref_customisation_reply_sorting">مرشح فرز الردود الافتراضية</string>
<string name="piko_pref_customisation_reply_sorting_remember">تم اختياره مسبقًا</string>
Expand Down Expand Up @@ -152,13 +163,6 @@
<string name="piko_single_page_settings">صفحة الإعدادات الفردية</string>
<string name="piko_single_page_settings_desc">عرض الإعدادات في صفحة واحدة</string>

<string name="piko_native_translator">تمكين ترجمة المنشور المحلي</string>
<string name="piko_native_translator_provider">مقدمي خدمات الترجمة</string>
<string name="piko_native_translator_to_lang">ترجم إلى</string>
<string name="piko_native_translator_zero_text">لم يتم العثور على نص للترجمة</string>
<string name="piko_native_translator_google">Google مترجم</string>
<string name="piko_native_translator_google_v2">مترجم Google V2</string>

<string name="piko_pref_search_type_ahead_users">المستخدمون</string>
<string name="piko_pref_search_type_ahead_events">الأحداث</string>
<string name="piko_pref_search_type_ahead_ordered_section">القسم المطلوب</string>
Expand Down
16 changes: 16 additions & 0 deletions src/main/resources/twitter/settings/values-v21/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,20 @@
<item>7</item>
<item>13</item>
</string-array>

<string-array name="piko_array_native_download_filename">
<item>username_tweetid</item>
<item>name_tweetid</item>
<item>userid_tweetid</item>
<item>tweetid</item>
<item>Current timestamp</item>
</string-array>

<string-array name="piko_array_native_download_filename_val">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
</string-array>
</resources>
Loading

0 comments on commit 0002c81

Please sign in to comment.