A Mixin messenger bot will be created in this tutorial. The bot is powered by Java and echo message and Bitcoin from user.
Full Mixin network resource index
- How to create bot in Mixin messenger and reply message to user | Chinese
- How to receive Bitcoin and send Bitcoin in Mixin Messenger | Chinese
- How to create a Bitcoin wallet based on Mixin Network API | Chinese
- How to trade bitcoin through Java: Pay to ExinCore | Chinese
- How to trade bitcoin through Java: List your order on Ocean.One | Chinese
- How to trade ERC-20 compliant coins on OceanOne through Java | Chinese
On macOS, download java jdk from here,double click jdk-11.0.2_osx-x64_bin.dmg, then click on JDK 11.0.2.pkg in popup window, follow the instruction to install java, java could be installed in /Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/bin/ directory, add this path to environment variable $PATH
echo 'export PATH=/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/bin/:$PATH' >> ~/.bash_profile
source ~/.bash_profile
Run command java --version to check the installation
wenewzha:mixin_labs-java-bot wenewzhang$ java --version
java 11.0.2 2019-01-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.2+9-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+9-LTS, mixed mode)
on Ubuntu
apt update
apt upgrade
apt install unzip
java --version
On Ubuntu 16.04, the openjdk java has been installed. run command java --version to check installation
root@ubuntu:~# java --version
openjdk 10.0.2 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)
OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4, mixed mode)
This tutorial use Gradle to build whole project. You can download the latest gradle here
macOS
brew update
brew install gradle
Ubuntu: The gradle is too old, we need to update it.
cd ~/Downloads
wget https://services.gradle.org/distributions/gradle-5.1.1-bin.zip
unzip gradle-5.1.1-bin.zip
After unzip the gradle-5.1.1-bin.zip, Add the path to $PATH environment variable
echo 'export PATH=/root/gradle-5.1.1/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
Run gradle -v to check gradle installation
root@ubuntu:~# gradle -v
------------------------------------------------------------
Gradle 5.1.1
------------------------------------------------------------
...
You need to create an app in dashboard. This tutorial can help you.
After app is created in dashboard, you need to generate parameter and write down required content, these content will be written into config.java file.
Go to your workspace, create the project mixin_labs-java-bot directory by running gradle init.
gradle init --dsl kotlin --type java-application --test-framework junit --project-name mixin_labs-java-bot
Goto src/main/java/mixin_labs/java/bot, create a file called Config.java. Copy the following content into it.
Config.java
package mixin_labs.java.bot;
import mixin.java.sdk.MixinUtil;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.Base64;
import mixin.java.sdk.PrivateKeyReader;
public class Config {
public static final String CLIENT_ID = "b1ce2967-a534-417d-bf12-c86571e4eefa";
public static final String CLIENT_SECRET = "e6b14c6bbb20a43c603c468e225e6e4c666c940792cde43e41b34c3f1dd45713";
public static final String PIN = "536071";
public static final String SESSION_ID = "2f1c44a3-d4d2-4dd2-bdb6-8eda67694b91";
public static final String PIN_TOKEN = "ajJJngHmWgIfH3S2mgH4bAsoPeoXV6hI1KoTZW9AvFUK1R8e28X1zVRCcrOMVeXkvBKQeEMgRdX1kRgH3ksITTBm2mgK5eUnfBHUuRC85oKoQGB9e2Bp4O4ZKGg/6bqLeD66pnBPcO2s7VtgLSAK0tHa2jMzmGlWuxsO6Wo5JHE=";
private static RSAPrivateKey loadPrivateKey() {
try {
PrivateKey key =
new PrivateKeyReader(Config.class.getClassLoader().getResourceAsStream("rsa_private_key.txt"))
.getPrivateKey();
System.out.println(key);
return (RSAPrivateKey) key;
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
return null;
}
}
public static final RSAPrivateKey RSA_PRIVATE_KEY = loadPrivateKey();
public static final byte[] PAY_KEY = MixinUtil.decrypt(RSA_PRIVATE_KEY, PIN_TOKEN, SESSION_ID);
}
Replace the value with content generated in dashboard.
App.java
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package mixin_labs.java.bot;
import mixin.java.sdk.MixinBot;
import mixin.java.sdk.MixinUtil;
import mixin.java.sdk.MIXIN_Category;
import mixin.java.sdk.MIXIN_Action;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateKey;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
// import java.util.Base64;
import org.apache.commons.codec.binary.Base64;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class App {
public static void main(String[] args) {
MixinBot.connectToRemoteMixin(new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
System.out.println("[onOpen !!!]");
System.out.println("request header:" + response.request().headers());
System.out.println("response header:" + response.headers());
System.out.println("response:" + response);
// Request unread messages
MixinBot.sendListPendingMessages(webSocket);
}
@Override
public void onMessage(WebSocket webSocket, String text) {
System.out.println("[onMessage !!!]");
System.out.println("text: " + text);
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
try {
System.out.println("[onMessage !!!]");
String msgIn = MixinUtil.bytesToJsonStr(bytes);
System.out.println("json: " + msgIn);
JsonObject obj = new JsonParser().parse(msgIn).getAsJsonObject();
MIXIN_Action action = MIXIN_Action.parseFrom(obj);
System.out.println(action);
MIXIN_Category category = MIXIN_Category.parseFrom(obj);
System.out.println(category);
if (action == MIXIN_Action.CREATE_MESSAGE && obj.get("data") != null &&
category != null ) {
String userId;
String messageId = obj.get("data").getAsJsonObject().get("message_id").getAsString();
MixinBot.sendMessageAck(webSocket, messageId);
switch (category) {
case PLAIN_TEXT:
String conversationId =
obj.get("data").getAsJsonObject().get("conversation_id").getAsString();
userId =
obj.get("data").getAsJsonObject().get("user_id").getAsString();
byte[] msgData = Base64.decodeBase64(obj.get("data").getAsJsonObject().get("data").getAsString());
MixinBot.sendText(webSocket,conversationId,userId,new String(msgData,"UTF-8"));
break;
default:
System.out.println("Category: " + category);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
System.out.println("[onClosing !!!]");
System.out.println("code: " + code);
System.out.println("reason: " + reason);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
System.out.println("[onClosed !!!]");
System.out.println("code: " + code);
System.out.println("reason: " + reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
System.out.println("[onFailure !!!]");
System.out.println("throwable: " + t);
System.out.println("response: " + response);
}
}, Config.RSA_PRIVATE_KEY, Config.CLIENT_ID, Config.SESSION_ID);
}
}
Goto src/main/resources, create a file: rsa_private_key.txt, fill the private key content which you have already generated in dashboard.
rsa_private_key.txt
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
Go to the project directory, download the mixin-java-sdk from github,
mkdir libs
cd libs
wget https://github.com/wenewzhang/mixin-java-sdk/releases/download/v5.0/mixin-java-sdk.jar
Add dependencies package info into build.gradle.kts
dependencies {
// This dependency is found on compile classpath of this component and consumers.
implementation("com.google.guava:guava:26.0-jre")
// dependent on mixin-java-sdk, copy it to libs directory
compile(files("libs/mixin-java-sdk.jar"))
implementation("commons-codec:commons-codec:1.11")
implementation("com.auth0:java-jwt:3.5.0")
implementation("com.squareup.okio:okio:2.2.1")
implementation("com.squareup.okhttp3:okhttp:3.12.1")
implementation("com.google.code.gson:gson:2.8.5")
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.3.20")
// Use JUnit test framework
testImplementation("junit:junit:4.12")
}
Goto the directory src/test/java/mixin_labs/java/bot, comment the test code,
AppTest.java
// assertNotNull("app should have a greeting", classUnderTest.getGreeting());
The last step, go back in mixin_labs-java-bot directory, build it and run,
gradle build
gradle run
Console will output:
response:Response{protocol=http/1.1, code=101, message=Switching Protocols, url=https://blaze.mixin.one/}
[onMessage !!!]
json: {"id":"4ee01b68-817e-4f29-bcb4-b40f7c163f61","action":"LIST_PENDING_MESSAGES"}
LIST_PENDING_MESSAGES
Add the bot(for example, this bot id is 7000101639) as your friend in Mixin Messenger and send your messages.
MixinBot.connectToRemoteMixin(new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
MixinBot.sendListPendingMessages(webSocket);
}
Send message "LISTPENDINGMESSAGES" to Mixin Messenger server and server will send unread messages to your bot.
public void onMessage(WebSocket webSocket, ByteString bytes) {
try {
System.out.println("[onMessage !!!]");
String msgIn = MixinUtil.bytesToJsonStr(bytes);
onMessage func will be called when server push message to bot
String messageId = obj.get("data").getAsJsonObject().get("message_id").getAsString();
MixinBot.sendMessageAck(webSocket, messageId);
Send a READ operation message to the server let it knows this message has been read. The bot will receive the duplicated message when the bot connected to server again if bot don't send response.
switch (category) {
case PLAIN_TEXT:
String conversationId =
obj.get("data").getAsJsonObject().get("conversation_id").getAsString();
userId =
obj.get("data").getAsJsonObject().get("user_id").getAsString();
byte[] msgData = Base64.decodeBase64(obj.get("data").getAsJsonObject().get("data").getAsString());
MixinBot.sendText(webSocket,conversationId,userId,new String(msgData,"UTF-8"));
Not only texts, images and other type message will be pushed to your bot. You can find more details about Messenger message.
Now your bot worked. You can hack it.
Full code is here