feat(box): 升级版本号并优化代码执行功能
-将版本号从 0.0.2 修改为 0.1.2 - 移除了异常时抛出的 RuntimeException - 新增了 C 语言和 Java代码的执行功能 - 优化了 Python 代码的执行方式- 添加了代码编辑器的前端界面 - 新增了 QQ音乐文件解密工具的 UI 界面 - 添加了 C++ 解密库的框架
This commit is contained in:
96
src/main/java/org/QQdecryption/QQMusicAutoDecryptor.java
Normal file
96
src/main/java/org/QQdecryption/QQMusicAutoDecryptor.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package org.QQdecryption;
|
||||
|
||||
import com.axis.innovators.box.tools.FolderCreator;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class QQMusicAutoDecryptor {
|
||||
|
||||
/**
|
||||
* 解密QQ加密的文件
|
||||
* @param inputPath 源文件路径
|
||||
* @param outputDir 标准输出目录路径
|
||||
*/
|
||||
public static void decrypt(String inputPath, String outputDir) {
|
||||
try {
|
||||
// 构建UnlockQQ.exe路径
|
||||
String unlockExe = FolderCreator.getLibraryFolder() + File.separator + "UnlockQQ.exe";
|
||||
|
||||
// 处理输出文件名和路径
|
||||
File inputFile = new File(inputPath);
|
||||
String originalName = inputFile.getName();
|
||||
|
||||
// 创建扩展名映射表(可根据需要扩展)
|
||||
Map<String, String> formatMap = new HashMap<>() {{
|
||||
put(".mflac", ".flac");
|
||||
put(".mgg", ".ogg");
|
||||
put(".qmc0", ".mp3");
|
||||
put(".qmc3", ".mp3");
|
||||
put(".qmcflac", ".flac");
|
||||
put(".qmcogg", ".ogg");
|
||||
put(".tkm", ".mp3");
|
||||
put(".qmc2", ".mp3");
|
||||
put(".bkcmp3", ".mp3");
|
||||
put(".bkcflac", ".flac");
|
||||
put(".ogg", ".ogg");
|
||||
}};
|
||||
|
||||
// 自动识别并转换文件格式
|
||||
String outputFileName = originalName;
|
||||
int lastDotIndex = originalName.lastIndexOf('.');
|
||||
if (lastDotIndex > 0) {
|
||||
String ext = originalName.substring(lastDotIndex).toLowerCase();
|
||||
if (formatMap.containsKey(ext)) {
|
||||
outputFileName = originalName.substring(0, lastDotIndex)
|
||||
+ formatMap.get(ext);
|
||||
} else {
|
||||
throw new RuntimeException("未知文件格式: " + ext);
|
||||
}
|
||||
}
|
||||
|
||||
File outputFile = new File(outputDir, outputFileName);
|
||||
|
||||
// 构建命令参数(处理带空格的路径)
|
||||
String[] cmd = {
|
||||
unlockExe,
|
||||
"\"" + inputFile.getAbsolutePath() + "\"",
|
||||
"\"" + outputFile.getAbsolutePath() + "\""
|
||||
};
|
||||
|
||||
// 执行解密命令
|
||||
Process process = Runtime.getRuntime().exec(cmd);
|
||||
int exitCode = process.waitFor();
|
||||
|
||||
// 检查执行结果
|
||||
if (exitCode == 0) {
|
||||
System.out.println("解密成功: " + outputFile.getAbsolutePath());
|
||||
|
||||
} else {
|
||||
System.err.println("解密失败,错误码: " + exitCode);
|
||||
printProcessError(process);
|
||||
}
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.err.println("解密过程中出现异常: ");
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("解密过程中出现异常: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加错误流打印方法
|
||||
private static void printProcessError(Process process) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(process.getErrorStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.err.println("[EXE ERROR] " + line);
|
||||
throw new RuntimeException("解密失败: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
167
src/main/java/org/QQdecryption/ui/DecryptionUI.java
Normal file
167
src/main/java/org/QQdecryption/ui/DecryptionUI.java
Normal file
@@ -0,0 +1,167 @@
|
||||
package org.QQdecryption.ui;
|
||||
|
||||
import org.QQdecryption.QQMusicAutoDecryptor;
|
||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.dnd.DropTargetAdapter;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class DecryptionUI extends JFrame {
|
||||
private JProgressBar progressBar;
|
||||
private JTextArea logArea;
|
||||
|
||||
public DecryptionUI() {
|
||||
initUI();
|
||||
setupDnD();
|
||||
}
|
||||
|
||||
private void initUI() {
|
||||
setTitle("QQ音乐文件解锁工具 v2.1");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setSize(800, 600);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
setupModernLookAndFeel();
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
// 拖放区域
|
||||
JPanel dropZone = createDropZone();
|
||||
mainPanel.add(dropZone, BorderLayout.CENTER);
|
||||
|
||||
// 控制面板
|
||||
JPanel controlPanel = createControlPanel();
|
||||
mainPanel.add(controlPanel, BorderLayout.SOUTH);
|
||||
|
||||
// 日志区域
|
||||
logArea = new JTextArea();
|
||||
logArea.setEditable(false);
|
||||
JScrollPane scrollPane = new JScrollPane(logArea);
|
||||
scrollPane.setPreferredSize(new Dimension(0, 150));
|
||||
mainPanel.add(scrollPane, BorderLayout.SOUTH);
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private void setupModernLookAndFeel() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(new FlatIntelliJLaf());
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private JPanel createDropZone() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createDashedBorder(null, 3, 5));
|
||||
panel.setBackground(UIManager.getColor("Panel.background").darker());
|
||||
|
||||
JLabel dropLabel = new JLabel("拖放QQ音乐文件到此区域", SwingConstants.CENTER);
|
||||
dropLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
|
||||
dropLabel.setForeground(new Color(0x666666));
|
||||
panel.add(dropLabel);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel createControlPanel() {
|
||||
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));
|
||||
|
||||
// 进度条
|
||||
progressBar = new JProgressBar();
|
||||
progressBar.setPreferredSize(new Dimension(200, 20));
|
||||
progressBar.setStringPainted(true);
|
||||
panel.add(progressBar);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void setupDnD() {
|
||||
new DropTarget(this, new DropTargetAdapter() {
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent dtde) {
|
||||
try {
|
||||
dtde.acceptDrop(DnDConstants.ACTION_COPY);
|
||||
List<File> files = (List<File>) dtde.getTransferable()
|
||||
.getTransferData(DataFlavor.javaFileListFlavor);
|
||||
processFiles(files);
|
||||
} catch (Exception ex) {
|
||||
logError("文件拖放错误: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processFiles(List<File> files) {
|
||||
SwingWorker<Void, Void> worker = new SwingWorker<>() {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
progressBar.setIndeterminate(true);
|
||||
for (File file : files) {
|
||||
decryptFile(file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
progressBar.setIndeterminate(false);
|
||||
JOptionPane.showMessageDialog(DecryptionUI.this,
|
||||
"处理完成!",
|
||||
"完成",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
};
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
private void decryptFile(File inputFile) {
|
||||
try {
|
||||
logMessage("开始处理: " + inputFile.getName());
|
||||
|
||||
// 自动获取源文件所在目录
|
||||
File outputDir = inputFile.getParentFile();
|
||||
|
||||
QQMusicAutoDecryptor.decrypt(
|
||||
inputFile.getAbsolutePath(),
|
||||
outputDir.getAbsolutePath()
|
||||
);
|
||||
|
||||
logMessage("✓ 成功解密保存到: " + outputDir.getAbsolutePath());
|
||||
} catch (Exception ex) {
|
||||
logError("解密失败: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void logMessage(String message) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
logArea.append("[INFO] " + message + "\n");
|
||||
logArea.setCaretPosition(logArea.getDocument().getLength());
|
||||
});
|
||||
}
|
||||
|
||||
private void logError(String error) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
logArea.append("[ERROR] " + error + "\n");
|
||||
logArea.setCaretPosition(logArea.getDocument().getLength());
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
try {
|
||||
UIManager.setLookAndFeel(new FlatIntelliJLaf());
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
new DecryptionUI().setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user