diff --git a/Dockerfile b/Dockerfile index 397063c..9c3ef47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,9 @@ FROM ubuntu:21.04 # Install needed packages RUN apt-get update RUN DEBIAN_FRONTEND=noninteractive apt-get -y install python3 android-sdk-build-tools wget unzip imagemagick git patch software-properties-common +# Mirror is being weird currently so install this seperatly +RUN apt-get update +RUN DEBIAN_FRONTEND=noninteractive apt-get -y install zipmerge # Install fdroid RUN add-apt-repository ppa:fdroid/fdroidserver @@ -20,6 +23,9 @@ RUN wget -O ${CTC_FOLDER}/tools/apktool.jar https://f001.backblazeb2.com/file/av # Grab xml-patch (https://github.com/dnault/xml-patch) RUN wget -O ${CTC_FOLDER}/tools/xml-patch.jar https://jcenter.bintray.com/com/github/dnault/xml-patch/0.3.1/xml-patch-0.3.1.jar +# Grab dex2jar (https://github.com/Aliucord/dex2jar) +RUN wget -O ${CTC_FOLDER}/tools/dex2jar.jar https://github.com/Aliucord/dex2jar/releases/download/v19-fork2/dex2jar.jar + # Grab emoji sets ENV EMOJI_PATH=${CTC_FOLDER}/emojis ENV EMOJI_MUTANT_PATH=${EMOJI_PATH}/mutant diff --git a/resources/patches/slashcommands/87202-pre.sh b/resources/patches/slashcommands/87202-pre.sh new file mode 100644 index 0000000..f6500a0 --- /dev/null +++ b/resources/patches/slashcommands/87202-pre.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd /opt/ctc/gitrepo/resources/patches/slashcommands/code +chmod +x gradlew +rm -rf build +./gradlew build +cd build/libs +/lib/android-sdk/build-tools/debian/dx --dex --output ctccommands.apk ctccommands-1.0-SNAPSHOT.jar +java -jar /opt/ctc/tools/apktool.jar d ctccommands.apk +cp -r ctccommands/smali/* ${DISTOK_EXTRACTED_DISCORD_PATH}/smali/ \ No newline at end of file diff --git a/resources/patches/slashcommands/87202.patch b/resources/patches/slashcommands/87202.patch new file mode 100644 index 0000000..45737aa --- /dev/null +++ b/resources/patches/slashcommands/87202.patch @@ -0,0 +1,13 @@ +diff -crB com.discord-base/smali/com/discord/stores/BuiltInCommands.smali com.discord/smali/com/discord/stores/BuiltInCommands.smali +*** com.discord-base/smali/com/discord/stores/BuiltInCommands.smali 2021-08-15 15:01:18.951758400 +0100 +--- com.discord/smali/com/discord/stores/BuiltInCommands.smali 2021-08-15 15:02:36.852775500 +0100 +*************** +*** 305,310 **** +--- 305,312 ---- + + iput-object v12, p0, Lcom/discord/stores/BuiltInCommands;->builtInApplication:Lcom/discord/models/commands/Application; + ++ invoke-static {p0}, Lcom/cutthecord/commands/CTCCommands;->CreateCTCCommands(Lcom/discord/stores/BuiltInCommands;)V ++ + return-void + .end method diff --git a/resources/patches/slashcommands/code/.gitignore b/resources/patches/slashcommands/code/.gitignore new file mode 100644 index 0000000..d124c18 --- /dev/null +++ b/resources/patches/slashcommands/code/.gitignore @@ -0,0 +1,6 @@ +.gradle +.idea +build +libs +out + diff --git a/resources/patches/slashcommands/code/build.gradle b/resources/patches/slashcommands/code/build.gradle new file mode 100644 index 0000000..28a7cbc --- /dev/null +++ b/resources/patches/slashcommands/code/build.gradle @@ -0,0 +1,28 @@ +plugins { + id 'java' +} + +group 'org.example' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +compileJava.options.encoding = 'UTF-8' + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +apply plugin: 'java' +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +dependencies { + implementation files('/tmp/cutthecord/discord-base-jar/discord-base.jar', 'libs/discord87202.jar') +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/resources/patches/slashcommands/code/gradle/wrapper/gradle-wrapper.jar b/resources/patches/slashcommands/code/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/resources/patches/slashcommands/code/gradle/wrapper/gradle-wrapper.jar differ diff --git a/resources/patches/slashcommands/code/gradle/wrapper/gradle-wrapper.properties b/resources/patches/slashcommands/code/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..be52383 --- /dev/null +++ b/resources/patches/slashcommands/code/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/resources/patches/slashcommands/code/gradlew b/resources/patches/slashcommands/code/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/resources/patches/slashcommands/code/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/resources/patches/slashcommands/code/gradlew.bat b/resources/patches/slashcommands/code/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/resources/patches/slashcommands/code/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/resources/patches/slashcommands/code/settings.gradle b/resources/patches/slashcommands/code/settings.gradle new file mode 100644 index 0000000..ecd818b --- /dev/null +++ b/resources/patches/slashcommands/code/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'ctccommands' + diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/CTCCommands.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/CTCCommands.java new file mode 100644 index 0000000..39e07e3 --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/CTCCommands.java @@ -0,0 +1,309 @@ +package com.cutthecord.commands; + +import com.cutthecord.commands.commands.CmdCtc; +import com.cutthecord.commands.commands.CmdEmojify; +import com.cutthecord.commands.commands.CmdOwo; +import com.cutthecord.commands.commands.CmdSpoilerImg; +import com.discord.api.commands.ApplicationCommandType; +import com.discord.api.commands.CommandChoice; +import com.discord.models.commands.ApplicationCommand; +import com.discord.models.commands.ApplicationCommandOption; +import com.discord.stores.BuiltInCommands; +import d0.z.d.m; +import d0.z.d.o; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.internal.DefaultConstructorMarker; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("SameParameterValue") +public class CTCCommands { + + static long ID = -100; + + // Helper class for replacements + public static class StrPair { + final String a; + final String b; + + public StrPair(String a, String b) { + this.a = a; + this.b = b; + } + } + + // Need to inject a call at end of init for p0 to this class in BuiltinCommands.smali + // Create commands + @SuppressWarnings({"unused"}) + public static void CreateCTCCommands(BuiltInCommands builtIn) { + // Used in command creation in BuiltinCommands, one more than the last reference + + // Add existing commands + ArrayList commands = new ArrayList<>(builtIn.getBuiltInCommands()); + + // Add our commands + commands.add(createWrappedSlashCommand("st", "Puts a strikethrough the message", "Message", "~~", "~~")); // Strikethrough + commands.add(createWrappedSlashCommand("bold", "Makes text bold", "Message", "**", "**")); // Bold + commands.add(createWrappedSlashCommand("slap", "Slaps people with a large trout", "Message", "*Slaps ", " around a bit with a large trout.*")); // Slap + + commands.add(createReplaceTextSlashCommand("clap", "Please \uD83D\uDC4F clap", "Message", Collections.singletonList(new StrPair(" ", ":clap:")))); // Clap + commands.add(createReplaceTextSlashCommand("flip", "Flips text (like “ʇɥıs”)", "Message", Replacements.FLIP)); // Flip + commands.add(createReplaceTextSlashCommand("fw", "Makes text fullwidth (like “Sent from my Android Device”)", "Message", Replacements.FULL_WIDTH)); // fw + commands.add(createReplaceTextSlashCommand("morse", "Converts text into morse code", "Message", Replacements.MORSE, Case.UPPER)); // morse + commands.add(createReplaceTextSlashCommand("gordon", "\uD835\uDDDB\uD835\uDDF2\uD835\uDDF9\uD835\uDDF9\uD835\uDDFC,\uD835\uDDDA\uD835\uDDFC\uD835\uDDFF\uD835\uDDF1\uD835\uDDFC\uD835\uDDFB!", "Message", Replacements.GORDON)); // gordon + commands.add(createReplaceTextSlashCommand("small", "Makes text smaller (like “ᴛʜɪs”)", "Message", Replacements.SMALL, Case.LOWER)); // small + commands.add(createReplaceTextSlashCommand("smaller", "Makes text even smaller (like “ᵗʰvˢ”)", "Message", Replacements.SMALLER, Case.LOWER)); // smaller + //noinspection unchecked + commands.add(createReplaceTextSlashCommand("upper", "Makes text uppercase", "Message", Collections.EMPTY_LIST, Case.UPPER)); // upper + //noinspection unchecked + commands.add(createReplaceTextSlashCommand("lower", "Makes text lowercase", "Message", Collections.EMPTY_LIST, Case.LOWER)); // lower + + commands.add(createAppendToEndCommand("lenny", "( ͡° ͜ʖ ͡°)", "Message", " ( \u0361\u00B0 \u035C\u0296 \u0361\u00B0)")); // lenny + + commands.add(createHandleRawMessageCommand("owo", "Myakes tyext reawwy owo-ly, nya :3", "Message", new CmdOwo())); // owo + commands.add(createHandleRawMessageCommand("emojify", "Emojify text", "Message", new CmdEmojify())); // emojify + commands.add(createHandleRawMessageCommand("spoilerimg", "Prepends SPOILER_ to names of all images attached to the message that starts with this, causing them to get marked as spoiler", "Message", new CmdSpoilerImg())); + + commands.add(createEnableDisableCommand("channelleak", "Shows all hidden channels", new CmdCtc.CmdCtcChannelLeak())); + commands.add(createEnableDisableCommand("showtyping", "Change typing event so that its visible/not when you type", new CmdCtc.CmdCtcShowTyping())); + commands.add(createEnableDisableCommand("nodelete", "Disables handling of message delete events", new CmdCtc.CmdCtcNoDelete())); + commands.add(createHandleRawMessageCommand("gettoken", "Get current token, DO NOT USE IN PUBLIC", null, new CmdCtc.CmdCtcGetToken())); + commands.add(createHandleRawMessageCommand("settoken", "Set current token, DO NOT USE IN PUBLIC", "Token", new CmdCtc.CmdCtcSetToken())); + commands.add(createHandleRawMessageCommand("switchaccount", "Switch to specified account, DO NOT USE IN PUBLIC", "Name", new CmdCtc.CmdCtcSwitchAccount())); + // TODO addaccount + + + // Builtin list is non modifiable, lets hijack it instead :) + try { + Field commandListField = BuiltInCommands.class.getDeclaredField("builtInCommands"); + commandListField.setAccessible(true); + commandListField.set(builtIn, commands); + } catch (Exception e) { + System.out.println("Failed to replace buildInCommands"); + e.printStackTrace(); + } + + } + + // Wrapper for naming + public static class CTCCommand extends ApplicationCommand { + public CTCCommand(String id, long applicationID, String name, String description, Integer descriptionRes, List options, boolean builtIn, Long guildId, String version, Boolean defaultPermissions, Map map, Function1 handler, int flags, DefaultConstructorMarker defaultConstructorMarker) { + super(id, applicationID, name, description, descriptionRes, options, builtIn, guildId, version, defaultPermissions, map, handler, flags, defaultConstructorMarker); + } + } + + // Wrapper for naming + public static ApplicationCommandOption makeOption(ApplicationCommandType type, String name, String description, Integer descriptionRes, boolean required, boolean defaultOpt, List choices, List options) { + return new ApplicationCommandOption(type, name, description, descriptionRes, required, defaultOpt, choices, options); + } + + // Wrapper for naming + public static ApplicationCommandOption makeOption(ApplicationCommandType type, String name, String description, Integer descriptionRes, boolean required, boolean defaultOpt, List choices, List options, int flags, DefaultConstructorMarker marker) { + return new ApplicationCommandOption(type, name, description, descriptionRes, required, defaultOpt, choices, options, flags, marker); + /* + Flags + 4 - description = null + 8 - descriptionRes = null + 64 - choices = null + 128 - options = null + */ + } + + // Wrapper for naming + public static ApplicationCommand makeCtcCommand(String name, String cmdDesc, List options, Function1, String> handler) { + m.checkNotNullParameter(name, "name"); + m.checkNotNullParameter(options, "options"); + return new CTCCommand(String.valueOf(ID--), -1L, name, cmdDesc, null, options, true, null, null, null, null, handler, 1936, null); + /* + Flags + 8 - description = null + 16 - descriptionRes = null + 64 - builtIn = false + 128 - guildID = null + 256 - version = null + 512 - defaultPermissions = false + 1024 - permissions = null + 2048 - handler = null + + 1928 = 1024, 512, 256, 128, 8 + // Lets try 1936 for out purposes + */ + } + + static final class WrapTextCommand extends o implements Function1, String> { + public final String prefix; + public final String suffix; + + public WrapTextCommand(String prefix, String suffix) { + super(1); + this.prefix = prefix; + this.suffix = suffix; + } + + public final String invoke(Map options) { + m.checkNotNullParameter(options, "commandOptions"); + StringBuilder newMessage = new StringBuilder(); + newMessage.append(this.prefix); + Object originalMessage = options.get("message"); + if (originalMessage == null) { + originalMessage = ""; + } + + newMessage.append(originalMessage); + newMessage.append(this.suffix); + return newMessage.toString(); + } + } + + @SuppressWarnings("SameParameterValue") + private static ApplicationCommand createWrappedSlashCommand(String name, String cmdDesc, String optionDesc, String prefix, String suffix) { + return makeCtcCommand(name, cmdDesc, Collections.singletonList( + makeOption(ApplicationCommandType.STRING, "message", optionDesc, null, true, false, null, null, 192, null) + ), new WrapTextCommand(prefix, suffix)); + } + + final static class AppendToEndCommand extends o implements Function1, String> { + public String suffix; + + public AppendToEndCommand(String suffix) { + super(1); + this.suffix = suffix; + } + + public final String invoke(Map options) { + m.checkNotNullParameter( options, "commandOptions"); + StringBuilder newMessage = new StringBuilder(); + Object originalMessage = options.get("message"); + if (originalMessage == null) { + originalMessage = ""; + } + + newMessage.append(originalMessage); + newMessage.append(' '); + newMessage.append(this.suffix); + return newMessage.toString(); + } + } + + @SuppressWarnings("SameParameterValue") + private static ApplicationCommand createAppendToEndCommand(String name, String cmdDesc, String optionDesc, String suffix) { + return makeCtcCommand(name, cmdDesc, Collections.singletonList( + makeOption(ApplicationCommandType.STRING, "message", optionDesc, null, false, false, null, null, 192, null) + ), new AppendToEndCommand(suffix)); + } + + final static class ReplaceMatchesCommand extends o implements Function1, String> { + public final List replacements; + public final Case c; + + public ReplaceMatchesCommand(List replacements, Case c) { + super(1); + this.replacements = replacements; + this.c = c; + } + + public final String invoke(Map options) { + m.checkNotNullParameter(options, "commandOptions"); + StringBuilder newMessage = new StringBuilder(); + Object originalMessage = options.get("message"); + if (originalMessage == null) { + originalMessage = ""; + } + + if (c == Case.UPPER) { + originalMessage = ((String)originalMessage).toUpperCase(); + } else if (c == Case.LOWER) { + originalMessage = ((String)originalMessage).toLowerCase(); + } + + for (StrPair replacement : replacements) { + originalMessage = ((String)originalMessage).replace(replacement.a, replacement.b); + } + + newMessage.append(originalMessage); + return newMessage.toString(); + } + } + + enum Case { + UPPER, + LOWER, + ORIGINAL + } + + private static ApplicationCommand createReplaceTextSlashCommand(String name, String cmdDesc, String optionDesc, List replaceList, Case c) { + return makeCtcCommand(name, cmdDesc, Collections.singletonList( + makeOption(ApplicationCommandType.STRING, "message", optionDesc, null, true, true, null, null, 192, null) + ), new ReplaceMatchesCommand(replaceList, c)); + } + + private static ApplicationCommand createReplaceTextSlashCommand(String name, String cmdDesc, String optionDesc, List replaceList) { + return createReplaceTextSlashCommand(name, cmdDesc, optionDesc, replaceList, Case.ORIGINAL); + } + + final static class RawMessageCommand extends o implements Function1, String> { + public final RawMsgHandler handler; + + public RawMessageCommand(RawMsgHandler handler) { + super(1); + this.handler = handler; + } + + public final String invoke(Map options) { + m.checkNotNullParameter(options, "commandOptions"); + StringBuilder newMessage = new StringBuilder(); + Object originalMessage = options.get("message"); + if (originalMessage == null) { + originalMessage = ""; + } + + newMessage.append(handler.processRawMessage((String) originalMessage)); + return newMessage.toString(); + } + } + + final static class EnableDisableCommand extends o implements Function1, String> { + public final EnableDisableHandler handler; + + public EnableDisableCommand(EnableDisableHandler handler) { + super(1); + this.handler = handler; + } + + public final String invoke(Map options) { + m.checkNotNullParameter(options, "commandOptions"); + StringBuilder newMessage = new StringBuilder(); + + boolean enabled = (boolean) options.get("enabled"); + + newMessage.append(handler.processEnableDisable(enabled)); + return newMessage.toString(); + } + } + + private static ApplicationCommand createHandleRawMessageCommand(String name, String cmdDesc, String optionDesc, RawMsgHandler handler) { + boolean required = true; + if (optionDesc == null) { + required = false; + } + return makeCtcCommand(name, cmdDesc, Collections.singletonList( + makeOption(ApplicationCommandType.STRING, "message", optionDesc, null, required, required, null, null, 192, null) + ), new RawMessageCommand(handler)); + } + + private static ApplicationCommand createEnableDisableCommand(String name, String cmdDesc, EnableDisableHandler handler) { + ArrayList truefalse = new ArrayList<>(); + truefalse.add(new CommandChoice("on", "true")); + truefalse.add(new CommandChoice("off", "false")); + + return makeCtcCommand(name, cmdDesc, Collections.singletonList( + makeOption(ApplicationCommandType.BOOLEAN, "enabled", "Enable/Disable", null, true, true, truefalse, null, 192, null) + ), new EnableDisableCommand(handler)); + } + + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/EnableDisableHandler.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/EnableDisableHandler.java new file mode 100644 index 0000000..e90a9e3 --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/EnableDisableHandler.java @@ -0,0 +1,7 @@ +package com.cutthecord.commands; + +public interface EnableDisableHandler { + + String processEnableDisable(boolean enabled); + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/RawMsgHandler.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/RawMsgHandler.java new file mode 100644 index 0000000..43537f3 --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/RawMsgHandler.java @@ -0,0 +1,7 @@ +package com.cutthecord.commands; + +public interface RawMsgHandler { + + String processRawMessage(String orig); + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/Replacements.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/Replacements.java new file mode 100644 index 0000000..20991eb --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/Replacements.java @@ -0,0 +1,304 @@ +package com.cutthecord.commands; + +import java.util.ArrayList; +import java.util.List; + +public class Replacements { + + public static final List FLIP = new ArrayList() {{ + add(new CTCCommands.StrPair("a", "ɐ")); + add(new CTCCommands.StrPair("b", "q")); + add(new CTCCommands.StrPair("c", "ɔ")); + add(new CTCCommands.StrPair("d", "p")); + add(new CTCCommands.StrPair("e", "ǝ")); + add(new CTCCommands.StrPair("f", "ɟ")); + add(new CTCCommands.StrPair("g", "ƃ")); + add(new CTCCommands.StrPair("h", "ɥ")); + add(new CTCCommands.StrPair("i", "ı")); + add(new CTCCommands.StrPair("j", "ɾ")); + add(new CTCCommands.StrPair("k", "ʞ")); + add(new CTCCommands.StrPair("l", "ן")); + add(new CTCCommands.StrPair("m", "ɯ")); + add(new CTCCommands.StrPair("n", "u")); + //add(new CTCCommands.StrPair("o", "o")); + add(new CTCCommands.StrPair("p", "d")); + add(new CTCCommands.StrPair("q", "b")); + add(new CTCCommands.StrPair("r", "ɹ")); + //add(new CTCCommands.StrPair("s", "s")); + add(new CTCCommands.StrPair("t", "ʇ")); + add(new CTCCommands.StrPair("u", "n")); + add(new CTCCommands.StrPair("v", "ʌ")); + add(new CTCCommands.StrPair("w", "ʍ")); + //add(new CTCCommands.StrPair("x", "x")); + add(new CTCCommands.StrPair("y", "ʎ")); + //add(new CTCCommands.StrPair("z", "z")); + }}; + + public static final List FULL_WIDTH = new ArrayList() {{ + add(new CTCCommands.StrPair(" ", " ")); + add(new CTCCommands.StrPair("!", "!")); + add(new CTCCommands.StrPair("#", "#")); + add(new CTCCommands.StrPair("$", "$")); + add(new CTCCommands.StrPair("%", "%")); + add(new CTCCommands.StrPair("&", "&")); + add(new CTCCommands.StrPair("'", "'")); + add(new CTCCommands.StrPair("(", "(")); + add(new CTCCommands.StrPair(")", ")")); + add(new CTCCommands.StrPair("*", "*")); + add(new CTCCommands.StrPair("+", "+")); + add(new CTCCommands.StrPair(",", ",")); + add(new CTCCommands.StrPair("-", "-")); + add(new CTCCommands.StrPair(".", ".")); + add(new CTCCommands.StrPair("/", "/")); + add(new CTCCommands.StrPair("0", "0")); + add(new CTCCommands.StrPair("1", "1")); + add(new CTCCommands.StrPair("2", "2")); + add(new CTCCommands.StrPair("3", "3")); + add(new CTCCommands.StrPair("4", "4")); + add(new CTCCommands.StrPair("5", "5")); + add(new CTCCommands.StrPair("6", "6")); + add(new CTCCommands.StrPair("7", "7")); + add(new CTCCommands.StrPair("8", "8")); + add(new CTCCommands.StrPair("9", "9")); + add(new CTCCommands.StrPair(":", ":")); + add(new CTCCommands.StrPair(";", ";")); + add(new CTCCommands.StrPair("<", "<")); + add(new CTCCommands.StrPair("=", "=")); + add(new CTCCommands.StrPair(">", ">")); + add(new CTCCommands.StrPair("?", "?")); + add(new CTCCommands.StrPair("@", "@")); + add(new CTCCommands.StrPair("A", "A")); + add(new CTCCommands.StrPair("B", "B")); + add(new CTCCommands.StrPair("C", "C")); + add(new CTCCommands.StrPair("D", "D")); + add(new CTCCommands.StrPair("E", "E")); + add(new CTCCommands.StrPair("F", "F")); + add(new CTCCommands.StrPair("G", "G")); + add(new CTCCommands.StrPair("H", "H")); + add(new CTCCommands.StrPair("I", "I")); + add(new CTCCommands.StrPair("J", "J")); + add(new CTCCommands.StrPair("K", "K")); + add(new CTCCommands.StrPair("L", "L")); + add(new CTCCommands.StrPair("M", "M")); + add(new CTCCommands.StrPair("N", "N")); + add(new CTCCommands.StrPair("O", "O")); + add(new CTCCommands.StrPair("P", "P")); + add(new CTCCommands.StrPair("Q", "Q")); + add(new CTCCommands.StrPair("R", "R")); + add(new CTCCommands.StrPair("S", "S")); + add(new CTCCommands.StrPair("T", "T")); + add(new CTCCommands.StrPair("U", "U")); + add(new CTCCommands.StrPair("V", "V")); + add(new CTCCommands.StrPair("W", "W")); + add(new CTCCommands.StrPair("X", "X")); + add(new CTCCommands.StrPair("Y", "Y")); + add(new CTCCommands.StrPair("Z", "Z")); + add(new CTCCommands.StrPair("[", "[")); + add(new CTCCommands.StrPair("]", "]")); + add(new CTCCommands.StrPair("^", "^")); + add(new CTCCommands.StrPair("_", "_")); + add(new CTCCommands.StrPair("`", "`")); + add(new CTCCommands.StrPair("a", "a")); + add(new CTCCommands.StrPair("b", "b")); + add(new CTCCommands.StrPair("c", "c")); + add(new CTCCommands.StrPair("d", "d")); + add(new CTCCommands.StrPair("e", "e")); + add(new CTCCommands.StrPair("f", "f")); + add(new CTCCommands.StrPair("g", "g")); + add(new CTCCommands.StrPair("h", "h")); + add(new CTCCommands.StrPair("i", "i")); + add(new CTCCommands.StrPair("j", "j")); + add(new CTCCommands.StrPair("k", "k")); + add(new CTCCommands.StrPair("l", "l")); + add(new CTCCommands.StrPair("m", "m")); + add(new CTCCommands.StrPair("n", "n")); + add(new CTCCommands.StrPair("o", "o")); + add(new CTCCommands.StrPair("p", "p")); + add(new CTCCommands.StrPair("q", "q")); + add(new CTCCommands.StrPair("r", "r")); + add(new CTCCommands.StrPair("s", "s")); + add(new CTCCommands.StrPair("t", "t")); + add(new CTCCommands.StrPair("u", "u")); + add(new CTCCommands.StrPair("v", "v")); + add(new CTCCommands.StrPair("w", "w")); + add(new CTCCommands.StrPair("x", "x")); + add(new CTCCommands.StrPair("y", "y")); + add(new CTCCommands.StrPair("z", "z")); + add(new CTCCommands.StrPair("{", "{")); + add(new CTCCommands.StrPair("|", "|")); + add(new CTCCommands.StrPair("}", "}")); + add(new CTCCommands.StrPair("~", "~")); + }}; + + public static final List MORSE = new ArrayList() {{ + add(new CTCCommands.StrPair(" ", "/ ")); + add(new CTCCommands.StrPair(".", ".-.-.- ")); + add(new CTCCommands.StrPair(",", "--..-- ")); + add(new CTCCommands.StrPair(":", "---... ")); + add(new CTCCommands.StrPair("?", "..--.. ")); + add(new CTCCommands.StrPair("'", ".----. ")); + add(new CTCCommands.StrPair("-", "-....- ")); + add(new CTCCommands.StrPair("/", "-..-. ")); + add(new CTCCommands.StrPair("@", ".--.-. ")); + add(new CTCCommands.StrPair("=", "-...- ")); + add(new CTCCommands.StrPair("A", ".- ")); + add(new CTCCommands.StrPair("B", "-... ")); + add(new CTCCommands.StrPair("C", "-.-. ")); + add(new CTCCommands.StrPair("D", "-.. ")); + add(new CTCCommands.StrPair("E", ". ")); + add(new CTCCommands.StrPair("F", "..-. ")); + add(new CTCCommands.StrPair("G", "--. ")); + add(new CTCCommands.StrPair("H", ".... ")); + add(new CTCCommands.StrPair("I", ".. ")); + add(new CTCCommands.StrPair("J", ".--- ")); + add(new CTCCommands.StrPair("K", "-.- ")); + add(new CTCCommands.StrPair("L", ".-.. ")); + add(new CTCCommands.StrPair("M", "-- ")); + add(new CTCCommands.StrPair("N", "-. ")); + add(new CTCCommands.StrPair("O", "--- ")); + add(new CTCCommands.StrPair("P", ".--. ")); + add(new CTCCommands.StrPair("Q", "--.- ")); + add(new CTCCommands.StrPair("R", ".-. ")); + add(new CTCCommands.StrPair("S", "... ")); + add(new CTCCommands.StrPair("T", "- ")); + add(new CTCCommands.StrPair("U", "..- ")); + add(new CTCCommands.StrPair("V", "...- ")); + add(new CTCCommands.StrPair("W", ".-- ")); + add(new CTCCommands.StrPair("X", "-..- ")); + add(new CTCCommands.StrPair("Y", "-.-- ")); + add(new CTCCommands.StrPair("Z", "--.. ")); + add(new CTCCommands.StrPair("0", "----- ")); + add(new CTCCommands.StrPair("1", ".---- ")); + add(new CTCCommands.StrPair("2", "..--- ")); + add(new CTCCommands.StrPair("3", "...-- ")); + add(new CTCCommands.StrPair("4", "....- ")); + add(new CTCCommands.StrPair("5", "..... ")); + add(new CTCCommands.StrPair("6", "-.... ")); + add(new CTCCommands.StrPair("7", "--... ")); + add(new CTCCommands.StrPair("8", "---.. ")); + add(new CTCCommands.StrPair("9", "----. ")); + }}; + + public static final List GORDON = new ArrayList() {{ + add(new CTCCommands.StrPair("a", "𝗮")); + add(new CTCCommands.StrPair("b", "𝗯")); + add(new CTCCommands.StrPair("c", "𝗰")); + add(new CTCCommands.StrPair("d", "𝗱")); + add(new CTCCommands.StrPair("e", "𝗲")); + add(new CTCCommands.StrPair("f", "𝗳")); + add(new CTCCommands.StrPair("g", "𝗴")); + add(new CTCCommands.StrPair("h", "𝗵")); + add(new CTCCommands.StrPair("i", "𝗶")); + add(new CTCCommands.StrPair("j", "𝗷")); + add(new CTCCommands.StrPair("k", "𝗸")); + add(new CTCCommands.StrPair("l", "𝗹")); + add(new CTCCommands.StrPair("m", "𝗺")); + add(new CTCCommands.StrPair("n", "𝗻")); + add(new CTCCommands.StrPair("o", "𝗼")); + add(new CTCCommands.StrPair("p", "𝗽")); + add(new CTCCommands.StrPair("q", "𝗾")); + add(new CTCCommands.StrPair("r", "𝗿")); + add(new CTCCommands.StrPair("s", "𝘀")); + add(new CTCCommands.StrPair("t", "𝘁")); + add(new CTCCommands.StrPair("u", "𝘂")); + add(new CTCCommands.StrPair("v", "𝘃")); + add(new CTCCommands.StrPair("w", "𝘄")); + add(new CTCCommands.StrPair("x", "𝘅")); + add(new CTCCommands.StrPair("y", "𝘆")); + add(new CTCCommands.StrPair("z", "𝘇")); + add(new CTCCommands.StrPair("A", "𝗔")); + add(new CTCCommands.StrPair("B", "𝗕")); + add(new CTCCommands.StrPair("C", "𝗖")); + add(new CTCCommands.StrPair("D", "𝗗")); + add(new CTCCommands.StrPair("E", "𝗘")); + add(new CTCCommands.StrPair("F", "𝗙")); + add(new CTCCommands.StrPair("G", "𝗚")); + add(new CTCCommands.StrPair("H", "𝗛")); + add(new CTCCommands.StrPair("I", "𝗜")); + add(new CTCCommands.StrPair("J", "𝗝")); + add(new CTCCommands.StrPair("K", "𝗞")); + add(new CTCCommands.StrPair("L", "𝗟")); + add(new CTCCommands.StrPair("M", "𝗠")); + add(new CTCCommands.StrPair("N", "𝗡")); + add(new CTCCommands.StrPair("O", "𝗢")); + add(new CTCCommands.StrPair("P", "𝗣")); + add(new CTCCommands.StrPair("Q", "𝗤")); + add(new CTCCommands.StrPair("R", "𝗥")); + add(new CTCCommands.StrPair("S", "𝗦")); + add(new CTCCommands.StrPair("T", "𝗧")); + add(new CTCCommands.StrPair("U", "𝗨")); + add(new CTCCommands.StrPair("V", "𝗩")); + add(new CTCCommands.StrPair("W", "𝗪")); + add(new CTCCommands.StrPair("X", "𝗫")); + add(new CTCCommands.StrPair("Y", "𝗬")); + add(new CTCCommands.StrPair("Z", "𝗭")); + add(new CTCCommands.StrPair("0", "𝟬")); + add(new CTCCommands.StrPair("1", "𝟭")); + add(new CTCCommands.StrPair("2", "𝟮")); + add(new CTCCommands.StrPair("3", "𝟯")); + add(new CTCCommands.StrPair("4", "𝟰")); + add(new CTCCommands.StrPair("5", "𝟱")); + add(new CTCCommands.StrPair("6", "𝟲")); + add(new CTCCommands.StrPair("7", "𝟳")); + add(new CTCCommands.StrPair("8", "𝟴")); + add(new CTCCommands.StrPair("9", "𝟵")); + }}; + + public static final List SMALL = new ArrayList() {{ + add(new CTCCommands.StrPair("a", "ᴀ")); + add(new CTCCommands.StrPair("b", "ʙ")); + add(new CTCCommands.StrPair("c", "ᴄ")); + add(new CTCCommands.StrPair("d", "ᴅ")); + add(new CTCCommands.StrPair("e", "ᴇ")); + add(new CTCCommands.StrPair("f", "ꜰ")); + add(new CTCCommands.StrPair("g", "ɢ")); + add(new CTCCommands.StrPair("h", "ʜ")); + add(new CTCCommands.StrPair("i", "ɪ")); + add(new CTCCommands.StrPair("j", "ᴊ")); + add(new CTCCommands.StrPair("k", "ᴋ")); + add(new CTCCommands.StrPair("l", "ʟ")); + add(new CTCCommands.StrPair("m", "ᴍ")); + add(new CTCCommands.StrPair("n", "ɴ")); + add(new CTCCommands.StrPair("o", "ᴏ")); + add(new CTCCommands.StrPair("p", "ᴘ")); + add(new CTCCommands.StrPair("q", "ǫ")); + add(new CTCCommands.StrPair("r", "ʀ")); + //add(new CTCCommands.StrPair("s", "s")); + add(new CTCCommands.StrPair("t", "ᴛ")); + add(new CTCCommands.StrPair("u", "ᴜ")); + add(new CTCCommands.StrPair("v", "ᴠ")); + add(new CTCCommands.StrPair("w", "ᴡ")); + add(new CTCCommands.StrPair("y", "ʏ")); + add(new CTCCommands.StrPair("z", "ᴢ")); + }}; + + public static final List SMALLER = new ArrayList() {{ + add(new CTCCommands.StrPair("a", "ᵃ")); + add(new CTCCommands.StrPair("b", "ᵇ")); + add(new CTCCommands.StrPair("c", "ᶜ")); + add(new CTCCommands.StrPair("d", "ᵈ")); + add(new CTCCommands.StrPair("e", "ᵉ")); + add(new CTCCommands.StrPair("f", "ᶠ")); + add(new CTCCommands.StrPair("g", "ᵍ")); + add(new CTCCommands.StrPair("h", "ʰ")); + add(new CTCCommands.StrPair("i", "ᶦ")); + add(new CTCCommands.StrPair("j", "ʲ")); + add(new CTCCommands.StrPair("k", "ᵏ")); + add(new CTCCommands.StrPair("l", "ˡ")); + add(new CTCCommands.StrPair("m", "ᵐ")); + add(new CTCCommands.StrPair("n", "ⁿ")); + add(new CTCCommands.StrPair("o", "ᵒ")); + add(new CTCCommands.StrPair("p", "ᵖ")); + add(new CTCCommands.StrPair("q", "ᑫ")); + add(new CTCCommands.StrPair("r", "ʳ")); + add(new CTCCommands.StrPair("s", "ˢ")); + add(new CTCCommands.StrPair("t", "ᵗ")); + add(new CTCCommands.StrPair("u", "ᵘ")); + add(new CTCCommands.StrPair("v", "ᵛ")); + add(new CTCCommands.StrPair("w", "ʷ")); + add(new CTCCommands.StrPair("x", "ˣ")); + add(new CTCCommands.StrPair("y", "ʸ")); + add(new CTCCommands.StrPair("z", "ᶻ")); + }}; + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdCtc.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdCtc.java new file mode 100644 index 0000000..9ad3002 --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdCtc.java @@ -0,0 +1,162 @@ +package com.cutthecord.commands.commands; + +import com.cutthecord.commands.EnableDisableHandler; +import com.cutthecord.commands.RawMsgHandler; +import com.discord.stores.StoreStream; +import com.discord.stores.StoreUserSettings; + +import java.lang.reflect.Method; + +public class CmdCtc { + + + // TODO make token calls write directly to clipboard + // TODO make supplemental inject a interface so we can just cast instead of using reflection + + public static class CmdCtcChannelLeak implements EnableDisableHandler { + + @Override + public String processEnableDisable(boolean enabled) { + try { + //noinspection JavaReflectionMemberAccess + final Method m = StoreStream.getUserSettings().getClass().getDeclaredMethod("setLeakChannels", Boolean.class); + m.invoke(StoreStream.getUserSettings(), enabled); + } catch (Exception e) { + System.out.println("Failed to call StoreStream.getUserSettings().setLeakChannels"); + e.printStackTrace(); + } + return "CTC: Successfully set channelleak state."; // TODO use notification + } + + } + + public static class CmdCtcShowTyping implements EnableDisableHandler { + + @Override + public String processEnableDisable(boolean enabled) { + + try { + //noinspection JavaReflectionMemberAccess + final Method m = StoreStream.getUserSettings().getClass().getDeclaredMethod("setShowTyping", Boolean.class); + m.invoke(StoreStream.getUserSettings(), enabled); + } catch (Exception e) { + System.out.println("Failed to call StoreStream.getUserSettings().setShowTyping"); + e.printStackTrace(); + } + + return "CTC: Successfully set showtyping state."; // TODO use notification + } + + } + + public static class CmdCtcNoDelete implements EnableDisableHandler { + + @Override + public String processEnableDisable(boolean enabled) { + + try { + //noinspection JavaReflectionMemberAccess + final Method m = StoreStream.getUserSettings().getClass().getDeclaredMethod("setNoDelete", Boolean.class); + m.invoke(StoreStream.getUserSettings(), enabled); + } catch (Exception e) { + System.out.println("Failed to call StoreStream.getUserSettings().setNoDelete"); + e.printStackTrace(); + } + + return "CTC: Successfully set nodelete state."; // TODO use notification + } + + } + + public static class CmdCtcGetToken implements RawMsgHandler { + + @Override + public String processRawMessage(String orig) { + try { + //noinspection JavaReflectionMemberAccess + final Method m = StoreStream.getUserSettings().getClass().getDeclaredMethod("getStoredToken"); + return (String) m.invoke(StoreStream.getUserSettings()); // TODO notification + } catch (Exception e) { + System.out.println("Failed to call StoreStream.getUserSettings().getStoredToken()"); + e.printStackTrace(); + } + + return ""; + } + + } + + public static class CmdCtcSetToken implements RawMsgHandler { + + @Override + public String processRawMessage(String msg) { + + try { + //noinspection JavaReflectionMemberAccess + final Method m = StoreStream.getUserSettings().getClass().getDeclaredMethod("setStoredToken", String.class); + m.invoke(StoreStream.getUserSettings(), msg); + } catch (Exception e) { + System.out.println("Failed to call StoreStream.getUserSettings().setStoredToken()"); + e.printStackTrace(); + } + + return "CTC: Successfully changed token. Please restart application."; + } + + } + + public static class CmdCtcSwitchAccount implements RawMsgHandler { + + @Override + public String processRawMessage(String msg) { + String trim = msg.trim(); + StoreUserSettings userSettings = StoreStream.getUserSettings(); + + try { + //noinspection JavaReflectionMemberAccess + final Method m1 = userSettings.getClass().getDeclaredMethod("getAccountToken", String.class); + String accountToken = (String) m1.invoke(userSettings, trim); + if (accountToken.startsWith("none")) { + return "CTC: No such account found."; + } + + //noinspection JavaReflectionMemberAccess + final Method m2 = userSettings.getClass().getDeclaredMethod("setStoredToken", String.class); + m2.invoke(userSettings, accountToken); + return "CTC: Successfully changed accounts. Please restart application."; + } catch (Exception e) { + e.printStackTrace(); + } + + return ""; + } + + } + + public static class CmdCtcAddAccount implements RawMsgHandler {//TODO + + @Override + public String processRawMessage(String msg) { + String substring3 = msg.substring(msg.indexOf(" ")); + String accName = msg.replace(substring3, "").trim(); + String accToken = substring3.trim(); + + StoreUserSettings userSettings = StoreStream.getUserSettings(); + if (accName.startsWith("current")) { + accName = StoreStream.getUsers().getMe().getUsername(); + accToken = StoreStream.getUsers().getMe().getToken(); + } + + try { + final Method m = userSettings.getClass().getDeclaredMethod("setAccountToken", String.class, String.class); + m.invoke(userSettings, accName, accToken); + } catch (Exception e) { + e.printStackTrace(); + } + + return "CTC: Added account."; + } + + } + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdEmojify.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdEmojify.java new file mode 100644 index 0000000..a931bcc --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdEmojify.java @@ -0,0 +1,44 @@ +package com.cutthecord.commands.commands; + +import com.cutthecord.commands.RawMsgHandler; + +public class CmdEmojify implements RawMsgHandler { + + @Override + public String processRawMessage(String msg) { + + StringBuilder s = new StringBuilder(); + for (char c : msg.toCharArray()) { + s.append(emojifyChar(c)); + } + + return s.toString(); + } + + final String[] numbers = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; + + public String emojifyChar(char c) { + if (Character.isDigit(c)) { + int i = Integer.parseInt(Character.toString(c)); + return ":" + numbers[i] + ":"; + } + + if (Character.isAlphabetic(c)) { + + if (c == 'b') { + return ":b:"; + } + + return ":regional_indicator_" + String.valueOf(c).toLowerCase() + ":"; + } + + switch (c) { + case '.': return ":record_button"; + case '?': return ":grey_question:"; + case '!': return ":grey_exclamation:"; + } + + return Character.toString(c); + } + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdOwo.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdOwo.java new file mode 100644 index 0000000..fc2be33 --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdOwo.java @@ -0,0 +1,26 @@ +package com.cutthecord.commands.commands; + +import com.cutthecord.commands.RawMsgHandler; + +public class CmdOwo implements RawMsgHandler { + + static final String[] expressions = { + ">_<", ":3", "ʕʘ‿ʘʔ", ":D", "._.", + ";3", "xD", "ㅇㅅㅇ", "(人◕ω◕)", + ">_>", "ÙωÙ", "UwU", "OwO", ":P", + "(◠‿◠✿)", "^_^", ";_;", "XDDD", + "x3", "(• o •)", "<_<", "(・`ω´・)", + ";;w;;", ">w<", "^w^" + }; + + public String processRawMessage(String msg) { + return msg.replaceAll("[rl]", "w") + .replaceAll("[RL]", "W") + .replaceAll("n([aeiou])", "ny$1") + .replaceAll("N([aeiou])", "Ny$1") + .replaceAll("N([AEIOU])", "NY$1") + .replace("ove", "uv") + .replaceAll("!+", " "+ expressions[(int) Math.floor(Math.random()*expressions.length)]+ " "); + } + +} diff --git a/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdSpoilerImg.java b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdSpoilerImg.java new file mode 100644 index 0000000..f01e617 --- /dev/null +++ b/resources/patches/slashcommands/code/src/main/java/com/cutthecord/commands/commands/CmdSpoilerImg.java @@ -0,0 +1,25 @@ +package com.cutthecord.commands.commands; + +import com.cutthecord.commands.RawMsgHandler; +import com.discord.stores.StoreStream; + +import java.lang.reflect.Method; + + +public class CmdSpoilerImg implements RawMsgHandler { + + @Override + public String processRawMessage(String orig) { + try { + // Added by Supplemental patch + //noinspection JavaReflectionMemberAccess + final Method m = StoreStream.getUserSettings().getClass().getDeclaredMethod("setImageSpoiler", Boolean.class); + m.invoke(StoreStream.getUserSettings(), true); + } catch (Exception e) { + System.out.println("Failed to call StoreStream.getUserSettings().setImageSpoiler(true)"); + e.printStackTrace(); + } + return orig; + } + +} diff --git a/resources/scripts/ctcci/ctcci.py b/resources/scripts/ctcci/ctcci.py index 73a987d..124d2ae 100644 --- a/resources/scripts/ctcci/ctcci.py +++ b/resources/scripts/ctcci/ctcci.py @@ -48,6 +48,10 @@ with open(os.path.join(REPO_FOLDER, "resources/patchport-state.json")) as f: VERSION = STATE["versioncode"] BASE_APK_PATH = os.path.join(WORK_FOLDER, f"discord-base-{VERSION}") +BASE_JAR_PATH = os.path.join(WORK_FOLDER, f"discord-base-jar") +# Wipe and recreate the base jar folder +if os.path.exists(BASE_JAR_PATH): + shutil.rmtree(BASE_JAR_PATH) # Prepare names of input and output APKs INPUT_FILE = os.path.join(DISTOK_FOLDER, "android", @@ -79,6 +83,13 @@ if not os.path.exists(BASE_APK_PATH): shell=True, cwd=WORK_FOLDER) +# Convert the dexs to a jar (for slashcommands etc) TODO versionise gradle/this +if not os.path.exists(BASE_JAR_PATH): + subprocess.run(f"unzip -j {INPUT_FILE} *.dex -d {BASE_JAR_PATH}", shell=True, cwd=WORK_FOLDER) + subprocess.run(f"{DEX2JAR_BIN} *.dex", shell=True, cwd=BASE_JAR_PATH) + subprocess.run(f"zipmerge discord-base.jar classes*dex2jar.jar", shell=True, cwd=BASE_JAR_PATH) + subprocess.run(f"rm classes*dex2jar.jar *.dex", shell=True, cwd=BASE_JAR_PATH) + # Copy the base cache to work on it shutil.copytree(BASE_APK_PATH, WORK_APK_PATH)