Compare commits

...

1 commit

59 changed files with 1632 additions and 468 deletions

View file

@ -148,8 +148,8 @@ android {
// of the source app. (Data is displayed when the source apk library is built.) // of the source app. (Data is displayed when the source apk library is built.)
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 1367 versionCode 1368
versionName '53.8' versionName '54.0'
} }

View file

@ -14,7 +14,7 @@ public class PatchConfig {
public static final boolean EMBEDLINKS_ENABLED = true; public static final boolean EMBEDLINKS_ENABLED = true;
public static final boolean SHOWTAG_ENABLED = true; public static final boolean SHOWTAG_ENABLED = true;
public static final boolean NONEARBY_ENABLED = true; public static final boolean NONEARBY_ENABLED = true;
public static final boolean NOSPOILER_ENABLED = false; public static final boolean NOSPOILER_ENABLED = true;
public static final boolean DISABLE_MOBILE_INDICATOR_ENABLED = true; public static final boolean DISABLE_MOBILE_INDICATOR_ENABLED = true;
public static final boolean HQAVATARS_ENABLED = true; public static final boolean HQAVATARS_ENABLED = true;
@ -27,5 +27,9 @@ public class PatchConfig {
public static final boolean LITECORD_ENABLED = false; // TODO public static final boolean LITECORD_ENABLED = false; // TODO
public static final boolean NOTRACK_ENABLED = true; public static final boolean NOTRACK_ENABLED = true;
public static String getEnabledPatchList() {
// TODO
return "";
}
} }

View file

@ -11,6 +11,7 @@ import kotlin.jvm.functions.Function0;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
import rx.subjects.Subject; import rx.subjects.Subject;
@SuppressWarnings("deprecation")
@DexIgnore @DexIgnore
public class AppFragment extends Fragment implements AppComponent, AppPermissions.Requests, MediaPicker.Provider { public class AppFragment extends Fragment implements AppComponent, AppPermissions.Requests, MediaPicker.Provider {

View file

@ -1,12 +1,106 @@
package com.discord.models.domain; package com.discord.models.domain;
import androidx.annotation.NonNull;
import com.discord.models.messages.LocalAttachment;
import com.discord.models.sticker.dto.ModelSticker;
import com.discord.utilities.time.Clock;
import java.io.IOException; import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import lanchon.dexpatcher.annotation.DexAdd;
import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap;
@DexIgnore @DexEdit
public class ModelMessage implements Model { public class ModelMessage implements Model {
@DexIgnore
public static class Call implements Model {
@DexIgnore
@Override
public void assignField(JsonReader jsonReader) throws IOException {
}
}
@DexIgnore
public ModelMessage(
long id,
String nonce,
long channelId,
int type,
String content,
@NonNull ModelUser author,
List<ModelUser> mentions,
String timestamp,
String editedTimestamp,
List<ModelMessageAttachment> attachments,
List<ModelMessageEmbed> embeds,
boolean tts,
Call call,
boolean mentionEveryone,
LinkedHashMap<String, ModelMessageReaction> reactions,
Boolean pinned,
Long webhookId,
ModelApplication application,
Activity activity,
boolean hit,
List<Long> mentionRoles,
boolean hasLocalUploads,
Long flags,
MessageReference messageReference,
ModelAllowedMentions allowedMentions,
List<LocalAttachment> localAttachments,
Long lastManualAttemptTimestamp,
Long initialAttemptTimestamp,
Integer num,
List<ModelSticker> stickers) {
}
@DexAdd
private boolean isCTCMessage = false;
@DexAdd
public void setCTCMessage(boolean isCTCMessage) {
this.isCTCMessage = isCTCMessage;
}
@DexWrap
public boolean canResend() {
// Prevent resending of messages from commands that are not public.
return canResend() && !isCTCMessage;
}
@DexIgnore
public static ModelMessage createLocalMessage(
String content,
long channelId,
@NonNull ModelUser author,
List<ModelUser> mentions,
boolean z2,
boolean hasLocalUploads,
ModelApplication application,
Activity activity,
Clock clock,
List<LocalAttachment> localAttachments,
Long lastManualAttemptTimestamp,
Long initialAttemptTimestamp,
Integer num,
List<ModelSticker> stickers,
MessageReference messageReference,
ModelAllowedMentions allowedMentions) {
return null;
}
@DexIgnore @DexIgnore
@Override @Override
public void assignField(JsonReader jsonReader) throws IOException { public void assignField(JsonReader jsonReader) throws IOException {

View file

@ -0,0 +1,10 @@
package com.discord.models.domain;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public class ModelMessageAttachment implements Model {
@DexIgnore
@Override
public void assignField(JsonReader jsonReader) {}
}

View file

@ -24,9 +24,15 @@ public class ModelMessageEmbed implements Model {
return false; return false;
} }
// end of nospoiler patch
// Interfaces
@DexIgnore @DexIgnore
@Override @Override
public void assignField(JsonReader jsonReader) throws IOException { public void assignField(JsonReader jsonReader) throws IOException {
} }
// End of interfaces
} }

View file

@ -0,0 +1,16 @@
package com.discord.models.domain;
import java.io.IOException;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public class ModelMessageReaction implements Model {
@DexIgnore
@Override
public void assignField(JsonReader jsonReader) throws IOException {
}
}

View file

@ -6,6 +6,7 @@ import com.discordtest.BuildConfig;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import lanchon.dexpatcher.annotation.DexAdd;
import lanchon.dexpatcher.annotation.DexEdit; import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@ -13,6 +14,41 @@ import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
public class ModelUser implements Model { public class ModelUser implements Model {
// add ctc bot
@DexIgnore
public long id;
@DexIgnore
public String username;
@DexIgnore
public int discriminator;
@DexIgnore
public boolean bot;
@DexIgnore
public String avatar;
@DexIgnore
public boolean system;
@DexAdd
public static final ModelUser CTC_BOT = createCtcBot();
@DexAdd
private static ModelUser createCtcBot() {
ModelUser user = new ModelUser();
user.id = -1;
user.username = "CutTheCord";
user.discriminator = 1;
user.bot = true;
//user.system = true;
user.avatar = "asset://asset/images/default_avatar_clyde.jpg";
return user;
}
// showtag patch // showtag patch
@DexWrap @DexWrap

View file

@ -0,0 +1,13 @@
package com.discord.models.domain;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public final class NonceGenerator {
@DexIgnore
public static final long computeNonce() {
return -1;
}
}

View file

@ -0,0 +1,7 @@
package com.discord.models.messages;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public final class LocalAttachment {
}

View file

@ -0,0 +1,15 @@
package com.discord.stores;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public final class Dispatcher {
@DexIgnore
public final void schedule(Function0<Unit> function0) {
}
}

View file

@ -0,0 +1,23 @@
package com.discord.stores;
import com.discord.models.domain.ModelMessage;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import lanchon.dexpatcher.annotation.DexIgnore;
import x.m.c.k;
@DexIgnore
public final class StoreMessages$sendMessage$1 extends k implements Function0<Unit> {
@DexIgnore
public StoreMessages$sendMessage$1(StoreMessages storeMessages, ModelMessage modelMessage) {
}
@DexIgnore
@Override
public Unit invoke() {
return null;
}
}

View file

@ -5,15 +5,20 @@ import com.discord.models.domain.ModelAllowedMentions;
import com.discord.models.domain.ModelApplication; import com.discord.models.domain.ModelApplication;
import com.discord.models.domain.ModelMessage; import com.discord.models.domain.ModelMessage;
import com.discord.models.domain.ModelUser; import com.discord.models.domain.ModelUser;
import com.discord.models.domain.NonceGenerator;
import com.discord.models.domain.activity.ModelActivity; import com.discord.models.domain.activity.ModelActivity;
import com.discord.models.sticker.dto.ModelSticker; import com.discord.models.sticker.dto.ModelSticker;
import com.discord.utilities.messagesend.MessageResult; import com.discord.utilities.messagesend.MessageResult;
import com.discord.utilities.time.Clock;
import com.discord.utilities.time.TimeUtils;
import com.lytefast.flexinput.model.Attachment; import com.lytefast.flexinput.model.Attachment;
import java.util.List; import java.util.List;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd; import lanchon.dexpatcher.annotation.DexAdd;
import lanchon.dexpatcher.annotation.DexEdit; import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
import rx.Observable; import rx.Observable;
@ -22,34 +27,48 @@ public final class StoreMessages extends Store {
// TODO extra patch that allows @ user selection window to appear when entering a slash command // TODO extra patch that allows @ user selection window to appear when entering a slash command
@DexIgnore
public StoreMessages(StoreStream storeStream, Dispatcher dispatcher, Clock clock2) {
}
@DexIgnore
private final Dispatcher dispatcher = null;
@DexIgnore
private final StoreMessagesHolder holder = new StoreMessagesHolder();
@DexIgnore
private final Clock clock = null;
// slashmessages patch // slashmessages patch
// Wrap edit function to check for commands // Wrap edit function to check for commands
@SuppressWarnings("InfiniteRecursion") // Wrapped method @SuppressWarnings("InfiniteRecursion") // Wrapped method
@DexWrap @DexWrap
public final void editMessage(long j, long j2, String str) { public final void editMessage(long messageId, long channelId, String content) {
if (!PatchConfig.SLASH_COMMANDS_ENABLED) { if (!PatchConfig.SLASH_COMMANDS_ENABLED) {
// Patch not enabled // Patch not enabled
editMessage(j, j2, str); editMessage(messageId, channelId, content);
return; return;
} }
String interceptEditMessage = interceptEditMessage(str); String interceptEditMessage = CommandHandler.interceptEditMessage(this, channelId, content);
editMessage(j, j2, interceptEditMessage); editMessage(messageId, channelId, interceptEditMessage);
} }
// Wrap send function to check for commands // Wrap send function to check for commands
@SuppressWarnings("InfiniteRecursion") // Wrapped method @SuppressWarnings("InfiniteRecursion") // Wrapped method
@DexWrap @DexWrap
public final Observable<MessageResult> sendMessage(long j, public final Observable<MessageResult> sendMessage(long channel,
ModelUser modelUser, ModelUser author,
String message, String message,
List<? extends ModelUser> list, List<? extends ModelUser> mentionedUsers,
List<? extends Attachment<?>> list2, List<? extends Attachment<?>> attachments,
List<ModelSticker> list3, List<ModelSticker> stickers,
ModelMessage.MessageReference messageReference, ModelMessage.MessageReference messageReference,
ModelAllowedMentions modelAllowedMentions, ModelAllowedMentions modelAllowedMentions,
ModelApplication modelApplication, ModelApplication application,
ModelActivity modelActivity, ModelActivity modelActivity,
ModelMessage.Activity activity, ModelMessage.Activity activity,
Long l, Long l,
@ -57,444 +76,26 @@ public final class StoreMessages extends Store {
Integer num) { Integer num) {
if (!PatchConfig.SLASH_COMMANDS_ENABLED) { if (!PatchConfig.SLASH_COMMANDS_ENABLED) {
// Patch not enabled // Patch not enabled
return sendMessage(j, modelUser, message, list, list2, list3, messageReference, modelAllowedMentions, modelApplication, modelActivity, activity, l, l2, num); return sendMessage(channel, author, message, mentionedUsers, attachments, stickers, messageReference, modelAllowedMentions, application, modelActivity, activity, l, l2, num);
} }
String interceptEditMessage = interceptSendMessage(message); String interceptEditMessage = CommandHandler.interceptSendMessage(this, channel, message);
return sendMessage(j, modelUser, interceptEditMessage, list, list2, list3, messageReference, modelAllowedMentions, modelApplication, modelActivity, activity, l, l2, num); return sendMessage(channel, author, interceptEditMessage, mentionedUsers, attachments, stickers, messageReference, modelAllowedMentions, application, modelActivity, activity, l, l2, num);
} }
// Add in helper functions // Helper methods for slashcommands etc
// Sends a bot message to a channel, only visible by the local client
// TODO for whatever reason these can't be deleted.. when type -1/0
// this is a big workaround, we add an additional check in ModelMessage to see if this is an internal message or not, to prevent resends, and send internal responses as error messages
@DexAdd @DexAdd
public static String interceptEditMessage(String str) { @StoreThread
return str.startsWith("/") ? slashCommands(str) : str; public void sendCTCBotMessageToChannel(long channelId, String content) {
long computeNonce = NonceGenerator.computeNonce();
ModelMessage modelMessage = new ModelMessage(computeNonce, String.valueOf(computeNonce), channelId, -2 /* Send failed */, content, ModelUser.CTC_BOT, null, TimeUtils.currentTimeUTCDateString(clock), null, null, null, false, null, false, null, null, null, null, null, false, null, false, null, null, null, null, null, null, null, null);
modelMessage.setCTCMessage(true);
this.dispatcher.schedule(new StoreMessages$sendMessage$1(this, modelMessage));
} }
@DexAdd
public static String interceptSendMessage(String str) {
StoreStream.getUserSettings().setImageSpoiler(false);
return str.startsWith("/") ? slashCommands(str) : str;
}
@DexAdd
public static String slashCommands(String str) {
String msg = str.trim();
String command = "";
String remaining = "";
int spacePos = str.indexOf(" ");
if (spacePos == -1) {
// Assume entire input is command
command = str.substring(1);
} else {
// Split command and remaining
command = str.substring(0, spacePos);
remaining = str.substring(spacePos + 1);
}
if (msg.startsWith("/upper ")) {
msg = slashUpper(remaining);
} else if (msg.startsWith("/lower ")) {
msg = slashLower(remaining);
} else if (msg.startsWith("/bold ")) {
msg = slashBold(remaining);
} else if (msg.startsWith("/spoiler ")) {
msg = slashSpoiler(remaining);
} else if (msg.startsWith("/me ")) {
msg = slashMe(remaining);
} else if (msg.startsWith("/st ")) {
msg = slashSt(remaining);
} else if (msg.startsWith("/lenny")) {
msg = slashLenny(remaining);
} else if (msg.startsWith("/fw ")) {
msg = slashFw(remaining);
} else if (msg.startsWith("/small ")) {
msg = slashSmall(remaining);
} else if (msg.startsWith("/smaller ")) {
msg = slashSmaller(remaining);
} else if (msg.startsWith("/flip ")) {
msg = slashFlip(remaining);
} else if (msg.startsWith("/clap ")) {
msg = slashClap(remaining);
} else if (msg.startsWith("/owo ")) {
msg = slashOwo(remaining);
} else if (msg.startsWith("/morse ")) {
msg = slashMorse(remaining);
} else if (msg.startsWith("/spoilerimg")) {
msg = slashSpoilerImg(remaining);
} else if (msg.startsWith("/gordon ")) {
msg = slashGordon(remaining);
} else if (msg.startsWith("/slap ")) {
msg = slashSlap(remaining);
}
return msg.trim();
}
@DexAdd
public static String slashSlap(String remaining) {
return "*Slaps "+remaining+" around a bit with a large trout.*";
}
@DexAdd
public static String slashBold(String remaining) {
return "**" + remaining + "**";
}
@DexAdd
public static String slashClap(String remaining) {
return remaining.replace(" ", " :clap: ");
}
@DexAdd
public static String slashCtc(String remaining) {
String subcommand = remaining.substring(5);
if (subcommand.startsWith("channelleak ")) {
StoreStream.getUserSettings().setLeakChannels(subcommand.substring(12).startsWith("false"));
return "CTC: Successfully set channelleak state.";
} else if (subcommand.startsWith("showtyping ")) {
StoreStream.getUserSettings().setShowTyping(subcommand.substring(11).startsWith("true"));
return "CTC: Successfully set showtyping state.";
} else if (subcommand.startsWith("token ")) {
StoreStream.getUserSettings().setStoredToken(subcommand.substring(6));
return "CTC: Successfully changed token. Please restart application.";
} else if (subcommand.startsWith("token")) {
return StoreStream.getUserSettings().getStoredToken();
} else {
if (subcommand.startsWith("account ")) {
String trim = subcommand.substring(8).trim();
StoreUserSettings userSettings = StoreStream.getUserSettings();
String accountToken = userSettings.getAccountToken(trim);
if (accountToken.startsWith("none")) {
return "CTC: No such account found.";
}
userSettings.setStoredToken(accountToken);
return "CTC: Successfully changed accounts. Please restart application.";
} else if (subcommand.startsWith("addaccount ")) {
String substring2 = subcommand.substring(11);
String substring3 = substring2.substring(substring2.indexOf(" "));
String trim2 = substring2.replace(substring3, "").trim();
String trim3 = substring3.trim();
StoreUserSettings userSettings2 = StoreStream.getUserSettings();
if (trim2.startsWith("current")) {
trim2 = userSettings2.getStoredToken();
}
userSettings2.setAccountToken(trim2, trim3);
return "CTC: Added account.";
} else if (subcommand.startsWith("nodelete ")) {
StoreStream.getUserSettings().setNoDelete(subcommand.substring(9).startsWith("true"));
return "CTC: Successfully set nodelete state.";
} else if (!subcommand.startsWith("gifautoplay ")) {
return "CTC: No known command supplied. (available: token, showtyping, channelleak, addaccount, account, nodelete, gifautoplay. Everything except specified token needs to be lowercase)";
} else {
StoreStream.getUserSettings().setAutoplayGifs(subcommand.substring(12).startsWith("true"));
return "CTC: Successfully set gifautoplay state.";
}
}
}
@DexAdd
public static String slashFlip(String remaining) {
StringBuilder sb = new StringBuilder(remaining.toLowerCase());
sb.reverse();
return sb.toString().replace("a", "ɐ")
.replace("b", "q")
.replace("c", "ɔ")
.replace("d", "p")
.replace("e", "ǝ")
.replace("f", "ɟ")
.replace("g", "ƃ")
.replace("h", "ɥ")
.replace("i", "ı")
.replace("j", "ɾ")
.replace("k", "ʞ")
.replace("l", "ן")
.replace("m", "ɯ")
.replace("n", "u")
.replace("o", "o")
.replace("p", "d")
.replace("q", "b")
.replace("r", "ɹ")
.replace("s", "s")
.replace("t", "ʇ")
.replace("u", "n")
.replace("v", "ʌ")
.replace("w", "ʍ")
.replace("x", "x")
.replace("y", "ʎ")
.replace("z", "z");
}
@DexAdd
public static String slashFw(String remaining) {
return remaining.replace(" ", " ")
.replace("!", "")
.replace("#", "")
.replace("$", "")
.replace("%", "")
.replace("&", "")
.replace("'", "")
.replace("(", "")
.replace(")", "")
.replace("*", "")
.replace("+", "")
.replace(",", "")
.replace("-", "")
.replace(".", "")
.replace("/", "")
.replace("0", "")
.replace("1", "")
.replace("2", "")
.replace("3", "")
.replace("4", "")
.replace("5", "")
.replace("6", "")
.replace("7", "")
.replace("8", "")
.replace("9", "")
.replace(":", "")
.replace(";", "")
.replace("<", "")
.replace("=", "")
.replace(">", "")
.replace("?", "")
.replace("@", "")
.replace("A", "")
.replace("B", "")
.replace("C", "")
.replace("D", "")
.replace("E", "")
.replace("F", "")
.replace("G", "")
.replace("H", "")
.replace("I", "")
.replace("J", "")
.replace("K", "")
.replace("L", "")
.replace("M", "")
.replace("N", "")
.replace("O", "")
.replace("P", "")
.replace("Q", "")
.replace("R", "")
.replace("S", "")
.replace("T", "")
.replace("U", "")
.replace("V", "")
.replace("W", "")
.replace("X", "")
.replace("Y", "")
.replace("Z", "")
.replace("[", "")
.replace("]", "")
.replace("^", "")
.replace("_", "_")
.replace("`", "")
.replace("a", "")
.replace("b", "")
.replace("c", "")
.replace("d", "")
.replace("e", "")
.replace("f", "")
.replace("g", "")
.replace("h", "")
.replace("i", "")
.replace("j", "")
.replace("k", "")
.replace("l", "")
.replace("m", "")
.replace("n", "")
.replace("o", "")
.replace("p", "")
.replace("q", "")
.replace("r", "")
.replace("s", "")
.replace("t", "")
.replace("u", "")
.replace("v", "")
.replace("w", "")
.replace("x", "")
.replace("y", "")
.replace("z", "")
.replace("{", "")
.replace("|", "")
.replace("}", "")
.replace("~", "");
}
@DexAdd
public static String slashGordon(String remaining) {
return remaining.replace("a", "𝗮")
.replace("b", "𝗯")
.replace("c", "𝗰")
.replace("d", "𝗱")
.replace("e", "𝗲")
.replace("f", "𝗳")
.replace("g", "𝗴")
.replace("h", "𝗵")
.replace("i", "𝗶")
.replace("j", "𝗷")
.replace("k", "𝗸")
.replace("l", "𝗹")
.replace("m", "𝗺")
.replace("n", "𝗻")
.replace("o", "𝗼")
.replace("p", "𝗽")
.replace("q", "𝗾")
.replace("r", "𝗿")
.replace("s", "𝘀")
.replace("t", "𝘁")
.replace("u", "𝘂")
.replace("v", "𝘃")
.replace("w", "𝘄")
.replace("x", "𝘅")
.replace("y", "𝘆")
.replace("z", "𝘇")
.replace("A", "𝗔")
.replace("B", "𝗕")
.replace("C", "𝗖")
.replace("D", "𝗗")
.replace("E", "𝗘")
.replace("F", "𝗙")
.replace("G", "𝗚")
.replace("H", "𝗛")
.replace("I", "𝗜")
.replace("J", "𝗝")
.replace("K", "𝗞")
.replace("L", "𝗟")
.replace("M", "𝗠")
.replace("N", "𝗡")
.replace("O", "𝗢")
.replace("P", "𝗣")
.replace("Q", "𝗤")
.replace("R", "𝗥")
.replace("S", "𝗦")
.replace("T", "𝗧")
.replace("U", "𝗨")
.replace("V", "𝗩")
.replace("W", "𝗪")
.replace("X", "𝗫")
.replace("Y", "𝗬")
.replace("Z", "𝗭")
.replace("0", "𝟬")
.replace("1", "𝟭")
.replace("2", "𝟮")
.replace("3", "𝟯")
.replace("4", "𝟰")
.replace("5", "𝟱")
.replace("6", "𝟲")
.replace("7", "𝟳")
.replace("8", "𝟴")
.replace("9", "𝟵");
}
@DexAdd
public static String slashLenny(String remaining) {
return remaining + " ( ͡° ͜ʖ ͡°)";
}
@DexAdd
public static String slashLower(String remaining) {
return remaining.toLowerCase();
}
@DexAdd
public static String slashMe(String remaining) {
return "*" + remaining + "*";
}
@DexAdd
public static String slashMorse(String remaining) {
return remaining.toUpperCase().replace(" ", "/ ")
.replace(".", ".-.-.- ")
.replace(",", "--..-- ")
.replace(":", "---... ")
.replace("?", "..--.. ")
.replace("'", ".----. ")
.replace("-", "-....- ")
.replace("/", "-..-. ")
.replace("@", ".--.-. ")
.replace("=", "-...- ")
.replace("A", ".- ")
.replace("B", "-... ")
.replace("C", "-.-. ")
.replace("D", "-.. ")
.replace("E", ". ")
.replace("F", "..-. ")
.replace("G", "--. ")
.replace("H", ".... ")
.replace("I", ".. ")
.replace("J", ".--- ")
.replace("K", "-.- ")
.replace("L", ".-.. ")
.replace("M", "-- ")
.replace("N", "-. ")
.replace("O", "--- ")
.replace("P", ".--. ")
.replace("Q", "--.- ")
.replace("R", ".-. ")
.replace("S", "... ")
.replace("T", "- ")
.replace("U", "..- ")
.replace("V", "...- ")
.replace("W", ".-- ")
.replace("X", "-..- ")
.replace("Y", "-.-- ")
.replace("Z", "--.. ")
.replace("0", "----- ")
.replace("1", ".---- ")
.replace("2", "..--- ")
.replace("3", "...-- ")
.replace("4", "....- ")
.replace("5", "..... ")
.replace("6", "-.... ")
.replace("7", "--... ")
.replace("8", "---.. ")
.replace("9", "----. ");
}
@DexAdd
public static String slashOwo(String remaining) {
return remaining.replaceAll("(?:r|l)", "w")
.replaceAll("(?:R|L)", "W")
.replaceAll("n([aeiou])", "ny$1")
.replaceAll("N([aeiou])", "Ny$1")
.replaceAll("N([AEIOU])", "NY$1")
.replace("ove", "uv");
}
@DexAdd
public static String slashSmall(String remaining) {
return remaining.toLowerCase().replace("a", "").replace("b", "ʙ").replace("c", "").replace("d", "").replace("e", "").replace("f", "").replace("g", "ɢ").replace("h", "ʜ").replace("i", "ɪ").replace("j", "").replace("k", "").replace("l", "ʟ").replace("m", "").replace("n", "ɴ").replace("o", "").replace("p", "").replace("q", "ǫ").replace("r", "ʀ").replace("s", "s").replace("t", "").replace("u", "").replace("v", "").replace("w", "").replace("y", "ʏ").replace("z", "");
}
@DexAdd
public static String slashSmaller(String remaining) {
return remaining.toLowerCase().replace("a", "").replace("b", "").replace("c", "").replace("d", "").replace("e", "").replace("f", "").replace("g", "").replace("h", "ʰ").replace("i", "").replace("j", "ʲ").replace("k", "").replace("l", "ˡ").replace("m", "").replace("n", "").replace("o", "").replace("p", "").replace("q", "").replace("r", "ʳ").replace("s", "ˢ").replace("t", "").replace("u", "").replace("v", "").replace("w", "ʷ").replace("x", "ˣ").replace("y", "ʸ").replace("z", "");
}
@DexAdd
public static String slashSpoiler(String remaining) {
return "||" + remaining + "||";
}
@DexAdd
public static String slashSpoilerImg(String remaining) {
StoreStream.getUserSettings().setImageSpoiler(true);
return remaining;
}
@DexAdd
public static String slashSt(String remaining) {
return "~~" + remaining + "~~";
}
@DexAdd
public static String slashUpper(String remaining) {
return remaining.toUpperCase();
}
} }

View file

@ -0,0 +1,22 @@
package com.discord.stores;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.discord.models.domain.ModelMessage;
import java.util.List;
import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit
public class StoreMessagesHolder {
@DexIgnore
public void addMessages(@NonNull List<ModelMessage> list) {
}
}

View file

@ -24,6 +24,9 @@ public class StoreStream {
return null; return null;
} }
@DexIgnore
public final StoreMessages getMessages() { return null; }
} }
} }

View file

@ -0,0 +1,16 @@
package com.discord.stores;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface StoreThread {
}

View file

@ -6,7 +6,7 @@ import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
public class AnalyticsTracker { public final class AnalyticsTracker {
// notrack patches - TODO toggle // notrack patches - TODO toggle

View file

@ -12,7 +12,7 @@ import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
public class AnalyticsUtils { public final class AnalyticsUtils {
// start of notrack patches // start of notrack patches

View file

@ -6,7 +6,7 @@ import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
public class IconUtils { public final class IconUtils {
// hqaavatars patch // hqaavatars patch

View file

@ -10,7 +10,7 @@ import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
public class MessagePreprocessor implements f.a.k.b.c.a { public final class MessagePreprocessor implements f.a.k.b.c.a { // NodeProcessor in dex
// Interfaces // Interfaces
@DexIgnore @DexIgnore

View file

@ -8,28 +8,22 @@ import lanchon.dexpatcher.annotation.DexAdd;
import lanchon.dexpatcher.annotation.DexEdit; import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore//TODO @DexEdit
public class Rules { public final class Rules {
// pseudonitro-viewer patch // pseudonitro-viewer patch
@DexEdit @DexEdit
private static Pattern PATTERN_CUSTOM_EMOJI = ctc_getCustomEmojiPattern(); private static Pattern PATTERN_CUSTOM_EMOJI = ctc_getCustomEmojiPattern();
@DexAdd
private static final Pattern ctc_PATTERN_CUSTOM_EMOJI_ORIGINAL = Pattern.compile("^<(a)?:([a-zA-Z_0-9]+):(\\d+)>");
@DexAdd
private static final Pattern ctc_PATTERN_CUSTOM_EMOJI_PSEUDONITRO = Pattern.compile("^<&??(a)?:([a-zA-Z_0-9]+):(\\d+)>");
@DexAdd @DexAdd
private static Pattern ctc_getCustomEmojiPattern() { private static Pattern ctc_getCustomEmojiPattern() {
if (!PatchConfig.PSEUDONITRO_VIEWER_ENABLED) { if (!PatchConfig.PSEUDONITRO_VIEWER_ENABLED) {
// Patch not enabled // Patch not enabled
return ctc_PATTERN_CUSTOM_EMOJI_ORIGINAL; return Pattern.compile("^<(a)?:([a-zA-Z_0-9]+):(\\d+)>");
} }
return ctc_PATTERN_CUSTOM_EMOJI_PSEUDONITRO; return Pattern.compile("^<&??(a)?:([a-zA-Z_0-9]+):(\\d+)>");
} }
} }

View file

@ -0,0 +1,14 @@
package com.discord.utilities.textprocessing.node;
import android.content.Context;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface BasicRenderContext {
@DexIgnore
Context getContext();
}

View file

@ -1,14 +1,17 @@
package com.discord.utilities.textprocessing.node; package com.discord.utilities.textprocessing.node;
import com.PatchConfig; import com.PatchConfig;
import com.discord.simpleast.core.node.Node;
import com.discordtest.BuildConfig; import com.discordtest.BuildConfig;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import lanchon.dexpatcher.annotation.DexEdit; import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexIgnore//TODO @DexEdit
public class SpoilerNode { public final class SpoilerNode<T extends SpoilerNode.RenderContext> extends Node<T> implements Spoilerable {
// nospoiler patch // nospoiler patch
@ -25,4 +28,20 @@ public class SpoilerNode {
return true; return true;
} }
// end of nospoiler patch
// class setup stuff
@DexIgnore
public interface RenderContext extends BasicRenderContext {
@DexIgnore
int getSpoilerColorRes();
@DexIgnore
Function1<SpoilerNode<?>, Unit> getSpoilerOnClick();
@DexIgnore
int getSpoilerRevealedColorRes();
}
} }

View file

@ -0,0 +1,8 @@
package com.discord.utilities.textprocessing.node;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface Spoilerable {
}

View file

@ -0,0 +1,9 @@
package com.discord.utilities.time;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface Clock {
@DexIgnore
long currentTimeMillis();
}

View file

@ -0,0 +1,13 @@
package com.discord.utilities.time;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public final class TimeUtils {
@DexIgnore
public static final String currentTimeUTCDateString(Clock clock) {
return null;
}
}

View file

@ -7,7 +7,7 @@ import lanchon.dexpatcher.annotation.DexAdd;
import lanchon.dexpatcher.annotation.DexEdit; import lanchon.dexpatcher.annotation.DexEdit;
@DexEdit @DexEdit
public class WebSocket { public final class WebSocket {
// TODO can be done with wrap // TODO can be done with wrap

View file

@ -16,7 +16,7 @@ import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
@SuppressWarnings({"rawtypes", "unchecked", "ConstantConditions", "FinalPrivateMethod"}) @SuppressWarnings({"rawtypes", "unchecked", "ConstantConditions", "FinalPrivateMethod"})
public class WidgetAuthLogin extends AppFragment { public final class WidgetAuthLogin extends AppFragment {
@DexIgnore @DexIgnore
public WidgetAuthLogin() {} public WidgetAuthLogin() {}

View file

@ -0,0 +1,21 @@
package com.discord.widgets.chat.input;
import com.discord.utilities.mg_recycler.MGRecyclerDataPayload;
import java.util.regex.Pattern;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface TagObject extends MGRecyclerDataPayload {
@DexIgnore
String getDisplayTag();
@DexIgnore
String getTag();
@DexIgnore
Pattern getTagRegex();
}

View file

@ -0,0 +1,101 @@
package com.discord.widgets.chat.input;
import androidx.annotation.Nullable;
import com.PatchConfig;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit
public class WidgetChatInputCommandsModel implements TagObject, Comparable<WidgetChatInputCommandsModel> {
// slashcommands patch
@DexWrap
private static Collection<WidgetChatInputCommandsModel> createBuiltInSlashCommands() {
Collection<WidgetChatInputCommandsModel> commands = createBuiltInSlashCommands();
if (!PatchConfig.SLASH_COMMANDS_ENABLED) {
// Patch not enabled
return commands;
}
// Naughty workaround to get default slashaction
WidgetChatInputCommandsModel o = (WidgetChatInputCommandsModel) commands.toArray()[0];
WidgetChatInputSlashAction defaultSlashAction = o.slashAction;
// Register our info messages
for (Map.Entry<String, String> infoTexts : CommandHandler.getPopupInfo().entrySet()) {
// TODO fix
commands.add(createSlashCommand(infoTexts.getKey(), "{CTC_COMMAND}", infoTexts.getValue(), defaultSlashAction));
}
return commands;
}
// end of slashcommands patch
@DexIgnore
private static WidgetChatInputCommandsModel createSlashCommand(String cmd, String str2, @Nullable String info, WidgetChatInputSlashAction widgetChatInputSlashAction) {
return null;
}
@DexIgnore
@Nullable
private WidgetChatInputSlashAction slashAction;
// Interfaces....
@DexIgnore
@Override
public String getDisplayTag() {
return null;
}
@DexIgnore
@Override
public String getTag() {
return null;
}
@DexIgnore
@Override
public Pattern getTagRegex() {
return null;
}
@DexIgnore
@Override
public String getKey() {
return null;
}
@DexIgnore
@Override
public int getType() {
return 0;
}
@DexIgnore
@Override
public int compareTo(WidgetChatInputCommandsModel o) {
return 0;
}
// End of interfaces
// Other class methods
@DexIgnore
@Nullable
public String getSlashOutput() {
return null;
}
}

View file

@ -0,0 +1,9 @@
package com.discord.widgets.chat.input;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface WidgetChatInputSlashAction {
@DexIgnore
String call(String str, WidgetChatInputCommandsModel widgetChatInputCommandsModel);
}

View file

@ -12,7 +12,7 @@ import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexIgnore//TODO @DexIgnore
public class EmojiPickerViewModel { public class EmojiPickerViewModel {
@DexEdit @DexEdit
@ -20,9 +20,9 @@ public class EmojiPickerViewModel {
// hideunusableemoji patch // hideunusableemoji patch
// filter the list then pass it into the original method // filter the list then pass it into the original method
@SuppressWarnings("InfiniteRecursion") @SuppressWarnings({"FinalPrivateMethod"})
@DexWrap @DexWrap
private List<MGRecyclerDataPayload> buildEmojiListItems(List<? extends Emoji> list, String str, boolean z) { private final List<MGRecyclerDataPayload> buildEmojiListItems(List<? extends Emoji> list, String str, boolean z) {
if (!PatchConfig.HIDE_UNUSABLE_EMOJIS_ENABLED) { if (!PatchConfig.HIDE_UNUSABLE_EMOJIS_ENABLED) {
// Patch not enabled // Patch not enabled

View file

@ -7,7 +7,7 @@ import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexWrap; import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit @DexEdit
public class NearbyManager { public final class NearbyManager {
// nonearby patch // nonearby patch
@DexWrap @DexWrap

View file

@ -13,7 +13,7 @@ import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexIgnore; import lanchon.dexpatcher.annotation.DexIgnore;
@DexEdit @DexEdit
public class WidgetSettings extends AppFragment implements OnTabSelectedListener { public final class WidgetSettings extends AppFragment implements OnTabSelectedListener {
// customversion patch // customversion patch

View file

@ -0,0 +1,217 @@
package cutthecord.commands;
import androidx.annotation.Nullable;
import com.discord.models.domain.ModelUser;
import com.discord.stores.StoreMessages;
import com.discord.stores.StoreStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import cutthecord.commands.commands.CmdBold;
import cutthecord.commands.commands.CmdClap;
import cutthecord.commands.commands.CmdCtc;
import cutthecord.commands.commands.CmdFlip;
import cutthecord.commands.commands.CmdFullWidth;
import cutthecord.commands.commands.CmdGordon;
import cutthecord.commands.commands.CmdLenny;
import cutthecord.commands.commands.CmdLower;
import cutthecord.commands.commands.CmdMe;
import cutthecord.commands.commands.CmdMorse;
import cutthecord.commands.commands.CmdOwo;
import cutthecord.commands.commands.CmdSlap;
import cutthecord.commands.commands.CmdSmall;
import cutthecord.commands.commands.CmdSmaller;
import cutthecord.commands.commands.CmdSpoiler;
import cutthecord.commands.commands.CmdSpoilerImg;
import cutthecord.commands.commands.CmdStrikethrough;
import cutthecord.commands.commands.CmdUpper;
import lanchon.dexpatcher.annotation.DexAdd;
// Helper class for additional commands (slashcommands)
@DexAdd
public class CommandHandler {
@DexAdd
private static final HashMap<String, Command> commands = registerCommands();
@DexAdd
public abstract static class Command {
@DexAdd
private final HashMap<String, Command> subcommands = new HashMap<>();
@DexAdd
public void registerSubCommand(String subCmdName, Command command) {
subcommands.put(subCmdName, command);
}
@DexAdd
public Set<String> getSubCommandNames() {
return subcommands.keySet();
}
@DexAdd
public String process(String args) {
// Check for possible subcommands
if (!subcommands.isEmpty()) {
final String[] split = args.split(Pattern.quote(" "));
if (split.length > 0) {
final String possibleSubCmd = split[0].toLowerCase();
for (Map.Entry<String, Command> subCommand : subcommands.entrySet()) {
if (subCommand.getKey().equals(possibleSubCmd)) {
// Account for simple commands with no args
String newArgs = "";
int i = args.indexOf(" ");
if (i == -1) {
newArgs = "";
} else {
// Has args
int newSubPos = i + 1;
newArgs = args.substring(newSubPos);
}
return subCommand.getValue().process(newArgs);
}
}
}
}
// Handle command
return handleCommand(args);
}
@DexAdd
public abstract String handleCommand(String msg);
@DexAdd
@Nullable
public abstract String getPopupInfo();
}
// Like a normal command, but the output is only viewable to the sender
@DexAdd
public abstract static class PrivateCommand extends Command {
}
@DexAdd
public static HashMap<String, Command> registerCommands() {
HashMap<String, Command> cmds = new HashMap<>();
cmds.put("upper", new CmdUpper());
cmds.put("lower", new CmdLower());
cmds.put("bold", new CmdBold());
cmds.put("clap", new CmdClap());
cmds.put("flip", new CmdFlip());
cmds.put("slap", new CmdSlap());
cmds.put("fw", new CmdFullWidth());
cmds.put("gordon", new CmdGordon());
cmds.put("me", new CmdMe());
cmds.put("lenny", new CmdLenny());
cmds.put("morse", new CmdMorse());
cmds.put("owo", new CmdOwo());
cmds.put("spoiler", new CmdSpoiler());
cmds.put("spoilerimg", new CmdSpoilerImg());
cmds.put("small", new CmdSmall());
cmds.put("smaller", new CmdSmaller());
cmds.put("st", new CmdStrikethrough());
// TODO can we add an CTC user that responds for these?
Command ctcCommand = new CmdCtc();
ctcCommand.registerSubCommand("channelleak", new CmdCtc.CmdCtcChannelLeak());
ctcCommand.registerSubCommand("showtyping", new CmdCtc.CmdCtcShowTyping());
ctcCommand.registerSubCommand("token", new CmdCtc.CmdCtcToken());
ctcCommand.registerSubCommand("account", new CmdCtc.CmdCtcAccount());
ctcCommand.registerSubCommand("addaccount", new CmdCtc.CmdCtcAddAccount());
ctcCommand.registerSubCommand("nodelete", new CmdCtc.CmdCtcNoDelete());
ctcCommand.registerSubCommand("gifautoplay", new CmdCtc.CmdCtcGifAutoPlay());
cmds.put("ctc", ctcCommand);
return cmds;
}
@DexAdd
public static HashMap<String, String> getPopupInfo() {
HashMap<String, String> infoPopups = new HashMap<>(); // Static init order makes things a pain so init in here
for (Map.Entry<String, Command> command : commands.entrySet()) {
String name = command.getKey();
Command cmd = command.getValue();
infoPopups.put(name, cmd.getPopupInfo());
registerPopupInfoChildren(infoPopups, name, cmd);
}
return infoPopups;
}
@DexAdd
private static void registerPopupInfoChildren(HashMap<String, String> infoPopups, String parent, Command parentCmd) {
for (Map.Entry<String, Command> subCommand : parentCmd.subcommands.entrySet()) {
String name = parent+" "+subCommand.getKey();
infoPopups.put(name, subCommand.getValue().getPopupInfo());
registerPopupInfoChildren(infoPopups, name, subCommand.getValue());
}
}
@DexAdd
public static String slashCommands(StoreMessages storeMessages, long channelId, String str) {
String msg = str.trim();
// TODO check for edge cases like /meh parsing to /me
// TODO don't allow invalid commaands to end up in chat
// Trim off "/"
msg = msg.substring(1);
for (Map.Entry<String, Command> commandEntry : commands.entrySet()) {
if (msg.startsWith(commandEntry.getKey())) {
String newArgs = msg;
// Account for simple commands with no args
int i = msg.indexOf(" ");
if (i == -1) {
newArgs = "";
} else {
// Has args
int newSubPos = i + 1;
newArgs = msg.substring(newSubPos);
}
String output = commandEntry.getValue().process(newArgs);
if (commandEntry.getValue() instanceof PrivateCommand) {
// Show message from ctcbot
storeMessages.sendCTCBotMessageToChannel(channelId, output);
// This is naughty but discord handles it sanely
return null;
}
return output;
}
}
return str.trim();
}
@DexAdd
public static String interceptEditMessage(StoreMessages storeMessages, long channelId, String str) {
return str.startsWith("/") ? slashCommands(storeMessages, channelId, str) : str;
}
@DexAdd
public static String interceptSendMessage(StoreMessages storeMessages, long channelId, String str) {
StoreStream.getUserSettings().setImageSpoiler(false);
return str.startsWith("/") ? slashCommands(storeMessages, channelId, str) : str;
}
}

View file

@ -0,0 +1,21 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdBold extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return "**" + msg + "**";
}
@DexAdd
@Override
public final String getPopupInfo() {
return "Makes text bold";
}
}

View file

@ -0,0 +1,21 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdClap extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.replace(" ", " :clap: ");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Please \uD83D\uDC4F clap";
}
}

View file

@ -0,0 +1,174 @@
package cutthecord.commands.commands;
import androidx.annotation.Nullable;
import com.discord.stores.StoreStream;
import com.discord.stores.StoreUserSettings;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdCtc extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
// Command only has subcommands
return "CTC: No known command supplied. (available: "+ getSubCommandNames() +". Everything except specified token needs to be lowercase)";
}
@DexAdd
@Nullable
@Override
public String getPopupInfo() {
return null;
}
@DexAdd
public static class CmdCtcChannelLeak extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
StoreStream.getUserSettings().setLeakChannels(msg.startsWith("false"));
return "CTC: Successfully set channelleak state.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Shows all channels, even those you dont have permissions to view";
}
}
@DexAdd
public static class CmdCtcShowTyping extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
StoreStream.getUserSettings().setShowTyping(msg.startsWith("true"));
return "CTC: Successfully set showtyping state.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Change typing event so that its visible/not when you type";
}
}
@DexAdd
public static class CmdCtcToken extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
if (msg.isEmpty()) {
// Print token
return StoreStream.getUserSettings().getStoredToken();
}
// Set token
StoreStream.getUserSettings().setStoredToken(msg);
return "CTC: Successfully changed token. Please restart application.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Gives or sets token";
}
}
@DexAdd
public static class CmdCtcAccount extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
String trim = msg.trim();
StoreUserSettings userSettings = StoreStream.getUserSettings();
String accountToken = userSettings.getAccountToken(trim);
if (accountToken.startsWith("none")) {
return "CTC: No such account found.";
}
userSettings.setStoredToken(accountToken);
return "CTC: Successfully changed accounts. Please restart application.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Switches to the account specified";
}
}
@DexAdd
public static class CmdCtcAddAccount extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
String substring3 = msg.substring(msg.indexOf(" "));
String trim2 = msg.replace(substring3, "").trim();
String trim3 = substring3.trim();
StoreUserSettings userSettings2 = StoreStream.getUserSettings();
if (trim2.startsWith("current")) {
trim2 = userSettings2.getStoredToken();
}
userSettings2.setAccountToken(trim2, trim3);
return "CTC: Added account.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Adds an account to the account switcher";
}
}
@DexAdd
public static class CmdCtcNoDelete extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
StoreStream.getUserSettings().setNoDelete(msg.startsWith("true"));
return "CTC: Successfully set nodelete state.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Disables handling of message delete events";
}
}
@DexAdd
public static class CmdCtcGifAutoPlay extends CommandHandler.PrivateCommand {
@DexAdd
@Override
public String handleCommand(String msg) {
StoreStream.getUserSettings().setAutoplayGifs(msg.startsWith("true"));
return "CTC: Successfully set gifautoplay state.";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Disables auto play of GIFs";
}
}
}

View file

@ -0,0 +1,48 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdFlip extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
StringBuilder sb = new StringBuilder(msg.toLowerCase());
sb.reverse();
return sb.toString().replace("a", "ɐ")
.replace("b", "q")
.replace("c", "ɔ")
.replace("d", "p")
.replace("e", "ǝ")
.replace("f", "ɟ")
.replace("g", "ƃ")
.replace("h", "ɥ")
.replace("i", "ı")
.replace("j", "ɾ")
.replace("k", "ʞ")
.replace("l", "ן")
.replace("m", "ɯ")
.replace("n", "u")
//.replace("o", "o")
.replace("p", "d")
.replace("q", "b")
.replace("r", "ɹ")
//.replace("s", "s")
.replace("t", "ʇ")
.replace("u", "n")
.replace("v", "ʌ")
.replace("w", "ʍ")
//.replace("x", "x")
.replace("y", "ʎ");
//.replace("z", "z");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Flips text (like “ʇɥıs”)";
}
}

View file

@ -0,0 +1,113 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdFullWidth extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.replace(" ", " ")
.replace("!", "")
.replace("#", "")
.replace("$", "")
.replace("%", "")
.replace("&", "")
.replace("'", "")
.replace("(", "")
.replace(")", "")
.replace("*", "")
.replace("+", "")
.replace(",", "")
.replace("-", "")
.replace(".", "")
.replace("/", "")
.replace("0", "")
.replace("1", "")
.replace("2", "")
.replace("3", "")
.replace("4", "")
.replace("5", "")
.replace("6", "")
.replace("7", "")
.replace("8", "")
.replace("9", "")
.replace(":", "")
.replace(";", "")
.replace("<", "")
.replace("=", "")
.replace(">", "")
.replace("?", "")
.replace("@", "")
.replace("A", "")
.replace("B", "")
.replace("C", "")
.replace("D", "")
.replace("E", "")
.replace("F", "")
.replace("G", "")
.replace("H", "")
.replace("I", "")
.replace("J", "")
.replace("K", "")
.replace("L", "")
.replace("M", "")
.replace("N", "")
.replace("O", "")
.replace("P", "")
.replace("Q", "")
.replace("R", "")
.replace("S", "")
.replace("T", "")
.replace("U", "")
.replace("V", "")
.replace("W", "")
.replace("X", "")
.replace("Y", "")
.replace("Z", "")
.replace("[", "")
.replace("]", "")
.replace("^", "")
.replace("_", "_")
.replace("`", "")
.replace("a", "")
.replace("b", "")
.replace("c", "")
.replace("d", "")
.replace("e", "")
.replace("f", "")
.replace("g", "")
.replace("h", "")
.replace("i", "")
.replace("j", "")
.replace("k", "")
.replace("l", "")
.replace("m", "")
.replace("n", "")
.replace("o", "")
.replace("p", "")
.replace("q", "")
.replace("r", "")
.replace("s", "")
.replace("t", "")
.replace("u", "")
.replace("v", "")
.replace("w", "")
.replace("x", "")
.replace("y", "")
.replace("z", "")
.replace("{", "")
.replace("|", "")
.replace("}", "")
.replace("~", "");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Makes text fullwidth (like “Sent from my Android Device”)";
}
}

View file

@ -0,0 +1,82 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdGordon extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.replace("a", "𝗮")
.replace("b", "𝗯")
.replace("c", "𝗰")
.replace("d", "𝗱")
.replace("e", "𝗲")
.replace("f", "𝗳")
.replace("g", "𝗴")
.replace("h", "𝗵")
.replace("i", "𝗶")
.replace("j", "𝗷")
.replace("k", "𝗸")
.replace("l", "𝗹")
.replace("m", "𝗺")
.replace("n", "𝗻")
.replace("o", "𝗼")
.replace("p", "𝗽")
.replace("q", "𝗾")
.replace("r", "𝗿")
.replace("s", "𝘀")
.replace("t", "𝘁")
.replace("u", "𝘂")
.replace("v", "𝘃")
.replace("w", "𝘄")
.replace("x", "𝘅")
.replace("y", "𝘆")
.replace("z", "𝘇")
.replace("A", "𝗔")
.replace("B", "𝗕")
.replace("C", "𝗖")
.replace("D", "𝗗")
.replace("E", "𝗘")
.replace("F", "𝗙")
.replace("G", "𝗚")
.replace("H", "𝗛")
.replace("I", "𝗜")
.replace("J", "𝗝")
.replace("K", "𝗞")
.replace("L", "𝗟")
.replace("M", "𝗠")
.replace("N", "𝗡")
.replace("O", "𝗢")
.replace("P", "𝗣")
.replace("Q", "𝗤")
.replace("R", "𝗥")
.replace("S", "𝗦")
.replace("T", "𝗧")
.replace("U", "𝗨")
.replace("V", "𝗩")
.replace("W", "𝗪")
.replace("X", "𝗫")
.replace("Y", "𝗬")
.replace("Z", "𝗭")
.replace("0", "𝟬")
.replace("1", "𝟭")
.replace("2", "𝟮")
.replace("3", "𝟯")
.replace("4", "𝟰")
.replace("5", "𝟱")
.replace("6", "𝟲")
.replace("7", "𝟳")
.replace("8", "𝟴")
.replace("9", "𝟵");
}
@DexAdd
@Override
public String getPopupInfo() {
return "\uD835\uDDDB\uD835\uDDF2\uD835\uDDF9\uD835\uDDF9\uD835\uDDFC\uD835\uDDDA\uD835\uDDFC\uD835\uDDFF\uD835\uDDF1\uD835\uDDFC\uD835\uDDFB";
}
}

View file

@ -0,0 +1,24 @@
package cutthecord.commands.commands;
import androidx.annotation.Nullable;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdLenny extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg + " ( ͡° ͜ʖ ͡°)";
}
@DexAdd
@Nullable
@Override
public String getPopupInfo() {
return null;
}
}

View file

@ -0,0 +1,24 @@
package cutthecord.commands.commands;
import androidx.annotation.Nullable;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdLower extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.toLowerCase();
}
@DexAdd
@Nullable
@Override
public String getPopupInfo() {
return "Makes text lowercase";
}
}

View file

@ -0,0 +1,21 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdMe extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return "*" + msg + "*";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Display text with emphasis";
}
}

View file

@ -0,0 +1,66 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdMorse extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.toUpperCase().replace(" ", "/ ")
.replace(".", ".-.-.- ")
.replace(",", "--..-- ")
.replace(":", "---... ")
.replace("?", "..--.. ")
.replace("'", ".----. ")
.replace("-", "-....- ")
.replace("/", "-..-. ")
.replace("@", ".--.-. ")
.replace("=", "-...- ")
.replace("A", ".- ")
.replace("B", "-... ")
.replace("C", "-.-. ")
.replace("D", "-.. ")
.replace("E", ". ")
.replace("F", "..-. ")
.replace("G", "--. ")
.replace("H", ".... ")
.replace("I", ".. ")
.replace("J", ".--- ")
.replace("K", "-.- ")
.replace("L", ".-.. ")
.replace("M", "-- ")
.replace("N", "-. ")
.replace("O", "--- ")
.replace("P", ".--. ")
.replace("Q", "--.- ")
.replace("R", ".-. ")
.replace("S", "... ")
.replace("T", "- ")
.replace("U", "..- ")
.replace("V", "...- ")
.replace("W", ".-- ")
.replace("X", "-..- ")
.replace("Y", "-.-- ")
.replace("Z", "--.. ")
.replace("0", "----- ")
.replace("1", ".---- ")
.replace("2", "..--- ")
.replace("3", "...-- ")
.replace("4", "....- ")
.replace("5", "..... ")
.replace("6", "-.... ")
.replace("7", "--... ")
.replace("8", "---.. ")
.replace("9", "----. ");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Converts text into morse code";
}
}

View file

@ -0,0 +1,26 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdOwo extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.replaceAll("(?:r|l)", "w")
.replaceAll("(?:R|L)", "W")
.replaceAll("n([aeiou])", "ny$1")
.replaceAll("N([aeiou])", "Ny$1")
.replaceAll("N([AEIOU])", "NY$1")
.replace("ove", "uv");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Myakes tyext reawwy owo-ly, nya :3";
}
}

View file

@ -0,0 +1,21 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdSlap extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return "*Slaps "+msg+" around a bit with a large trout.*";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Slaps people with a large trout";
}
}

View file

@ -0,0 +1,46 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdSmall extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.toLowerCase()
.replace("a", "")
.replace("b", "ʙ")
.replace("c", "")
.replace("d", "")
.replace("e", "")
.replace("f", "")
.replace("g", "ɢ")
.replace("h", "ʜ")
.replace("i", "ɪ")
.replace("j", "")
.replace("k", "")
.replace("l", "ʟ")
.replace("m", "")
.replace("n", "ɴ")
.replace("o", "")
.replace("p", "")
.replace("q", "ǫ")
.replace("r", "ʀ")
//.replace("s", "s")
.replace("t", "")
.replace("u", "")
.replace("v", "")
.replace("w", "")
.replace("y", "ʏ")
.replace("z", "");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Makes text smaller (like “ᴛʜɪs”)";
}
}

View file

@ -0,0 +1,47 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdSmaller extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.toLowerCase()
.replace("a", "")
.replace("b", "")
.replace("c", "")
.replace("d", "")
.replace("e", "")
.replace("f", "")
.replace("g", "")
.replace("h", "ʰ")
.replace("i", "")
.replace("j", "ʲ")
.replace("k", "")
.replace("l", "ˡ")
.replace("m", "")
.replace("n", "")
.replace("o", "")
.replace("p", "")
.replace("q", "")
.replace("r", "ʳ")
.replace("s", "ˢ")
.replace("t", "")
.replace("u", "")
.replace("v", "")
.replace("w", "ʷ")
.replace("x", "ˣ")
.replace("y", "ʸ")
.replace("z", "");
}
@DexAdd
@Override
public String getPopupInfo() {
return "Makes text even smaller (like “ᵗʰvˢ”)";
}
}

View file

@ -0,0 +1,21 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdSpoiler extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return "||" + msg + "||";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Marks your message as a spoiler";
}
}

View file

@ -0,0 +1,24 @@
package cutthecord.commands.commands;
import com.discord.stores.StoreStream;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdSpoilerImg extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
StoreStream.getUserSettings().setImageSpoiler(true);
return msg;
}
@DexAdd
@Override
public String getPopupInfo() {
return "Prepends SPOILER_ to names of all images attached to the message that starts with this, causing them to get marked as spoiler";
}
}

View file

@ -0,0 +1,21 @@
package cutthecord.commands.commands;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdStrikethrough extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return "~~" + msg + "~~";
}
@DexAdd
@Override
public String getPopupInfo() {
return "Puts a strikethrough the message";
}
}

View file

@ -0,0 +1,24 @@
package cutthecord.commands.commands;
import androidx.annotation.Nullable;
import cutthecord.commands.CommandHandler;
import lanchon.dexpatcher.annotation.DexAdd;
@DexAdd
public class CmdUpper extends CommandHandler.Command {
@DexAdd
@Override
public String handleCommand(String msg) {
return msg.toUpperCase();
}
@DexAdd
@Nullable
@Override
public String getPopupInfo() {
return "Makes text uppercase";
}
}

View file

@ -0,0 +1,32 @@
package f.a.p.b.a;
import com.PatchConfig;
import com.discord.widgets.chat.input.WidgetChatInputCommandsModel;
import com.discord.widgets.chat.input.WidgetChatInputSlashAction;
import lanchon.dexpatcher.annotation.DexEdit;
import lanchon.dexpatcher.annotation.DexWrap;
@DexEdit
public final class u implements WidgetChatInputSlashAction {
// slashcommands patch
@DexWrap
@Override
public String call(String str, WidgetChatInputCommandsModel widgetChatInputCommandsModel) {
if (!PatchConfig.SLASH_COMMANDS_ENABLED) {
// Patch not enabled
return call(str, widgetChatInputCommandsModel);
}
// We handle our commands elswhere so bail out here.
if (widgetChatInputCommandsModel.getSlashOutput().equals("{CTC_COMMAND}")) {
return str;
}
String replaceAll = str.replaceAll(widgetChatInputCommandsModel.getTag(), "");
return replaceAll + ' ' + widgetChatInputCommandsModel.getSlashOutput();
}
}

View file

@ -0,0 +1,9 @@
package kotlin.jvm.functions;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface Function1<P1, R> {
@DexIgnore
R invoke(P1 p1);
}

View file

@ -0,0 +1,7 @@
package kotlin.jvm.functions;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface Function2<P1, P2, R> {
}

View file

@ -0,0 +1,7 @@
package x.m.c;
import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore
public interface g<R> {
}

View file

@ -0,0 +1,11 @@
package x.m.c;
import java.io.Serializable;
import lanchon.dexpatcher.annotation.DexIgnore;
// Lambda.kt
@DexIgnore
public abstract class k<R> implements g<R>, Serializable {
}

View file

@ -7,6 +7,8 @@ import lanchon.dexpatcher.annotation.DexIgnore;
@DexIgnore @DexIgnore
public interface a { public interface a {
@DexIgnore @DexIgnore
List<Annotation> getAnnotations(); List<Annotation> getAnnotations();
} }