From fc429e506fd8f982bf3683356317351e6b085038 Mon Sep 17 00:00:00 2001
From: pq9azftxn <2725155082@qq.com>
Date: Sat, 2 Nov 2024 20:53:29 +0800
Subject: [PATCH] Update README.md
---
README.md | 542 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 541 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 651add6..eb19738 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,542 @@
-# LittleRedBook
+组长博客链接:
+代码库链接:
+
+视频链接:
+
+
+
+# 一、思维导图
+
+![小红书自动化脚本](小红书自动化脚本.png)
+
+# 二、整体架构
+
+通过这个脚本,我们可以实现小红书的**自动打开**、**进入随机直播间**、**自动滑屏切换**、**点赞**、**关注**、**评论**以及**发布帖子**等功能。该脚本尤其适合那些需要频繁进行直播互动操作的人群,接下来,我们将逐步分析这段代码中的关键实现部分。
+
+---
+
+#### 1. 初始化及权限检查
+
+首先,我们的代码会检查应用的悬浮窗权限。如果没有权限,则会通过悬浮窗提示用户授权,并立即退出脚本,以确保之后的界面显示功能能够正常工作。
+
+```javascript
+if (!floaty.checkPermission()) {
+ toast("请授予悬浮窗权限");
+ floaty.requestPermission();
+ exit();
+}
+```
+
+`floaty.checkPermission()` 用于检查悬浮窗权限;如果没有授权,则`floaty.requestPermission()` 会请求权限,并提示用户。
+
+---
+
+
+
+#### 2. 创建悬浮窗组件
+
+接下来,我们通过 `floaty.window` 创建一个包含按钮、滑动条、复选框和输入框的悬浮窗界面,以期为用户提供丰富的控制选项,这些控件允许用户开启与关闭点赞、设置点赞速度、切换评论模式、开启与关闭评论、开启与关闭自动滑屏与自动关注以及输入帖子内容等,我们使用XML 结构定义界面布局,这样可以使得用户看到的界面整洁,且功能齐全。
+
+```javascript
+let window = floaty.window(
+
+
+
+
+);
+```
+
+---
+
+
+
+#### 3. 悬浮窗拖动与收起功能
+
+为增强用户体验,我们的脚本实现了悬浮窗的拖动和展开/收起功能,以便在不需要的时候收起,免得占用太多屏幕控件。`window.toggle.setOnTouchListener` 方法实现了拖动逻辑,通过判断按下时间来识别用户是拖动还是点击操作。
+
+```javascript
+window.toggle.setOnTouchListener(function(view, event) {
+ switch (event.getAction()) {
+ case event.ACTION_DOWN:
+ x = event.getRawX();
+ y = event.getRawY();
+ windowX = window.getX();
+ windowY = window.getY();
+ downTime = new Date().getTime();
+ return true;
+ case event.ACTION_MOVE:
+ window.setPosition(windowX + (event.getRawX() - x), windowY + (event.getRawY() - y));
+ return true;
+ case event.ACTION_UP:
+ if (new Date().getTime() - downTime < 200) {
+ window.toggle.performClick();
+ }
+ return true;
+ }
+ return true;
+});
+```
+
+通过这种方式,用户可以自由拖动悬浮窗位置,并通过点击展开或收起控制面板以节省屏幕空间。
+
+---
+
+
+
+#### 4. 自动点赞功能
+
+点赞是直播互动中的关键操作,我们的脚本通过 `window.likeButton.click` 事件监听来实现点赞的开关控制,用户可以点击按钮来启动或停止点赞,并通过滑动条来调节点赞速度。
+
+```javascript
+function startLiking() {
+ stopLiking(); // 先停止之前的点赞定时器,防止重复
+ toast("开始点赞");
+ likingInterval = setInterval(() => {
+ likePost();
+ }, likeSpeed);
+}
+```
+
+点赞是通过 `click()`来模拟点击屏幕右侧的指定位置实现的,其频率由 `likeSpeed` 控制,`window.speedControl.setOnSeekBarChangeListener` 用于监听滑动条变动,以实时调整点赞速度。
+
+---
+
+
+
+#### 5. 评论功能:静态与动态评论
+
+评论功能允许用户选择发送静态或者动态评论,静态评论是从我们预先设置的 `staticComments` 数组中随机抽取的,而动态评论则允许用户自定义输入内容(之后会重复发送用户的自定义内容), `getStaticComment()` 函数负责从预设数组中随机选择评论。
+
+```javascript
+function getStaticComment() {
+ return staticComments[Math.floor(Math.random() * staticComments.length)];
+}
+```
+
+评论功能的逻辑由 `startLiveOrComment` 函数实现。该函数根据用户选择的模式(静态/动态)来生成评论,并自动输入到评论框中。
+
+---
+
+
+
+#### 6. 自动关注和自动滑屏
+
+我们的脚本中提供了自动关注主播和自动滑屏切换直播间的功能,开启这两个功能后,脚本会自动检测并点击屏幕中的“关注”按钮(通过查找id和关键字同时实现,如果找不到id就找关键字),同时通过模拟滑动操作,实现了在观看一定时间后(自定义的)自动切换下一个直播的功能。
+
+```javascript
+// 自动关注按钮
+window.follow.click(() => {
+ if (!isAutoFollowing) {
+ autoFollowThread = threads.start(() => {
+ while (isAutoFollowing) {
+ let followButton = id("fv").findOne(2000);
+ if (followButton) followButton.click();
+ sleep(1000);
+ }
+ });
+ }
+});
+```
+
+`swipe(device.width / 3, device.Height / 2, device.width / 2, device.Height / 4, 100);` 模拟向上滑动的功能,切换视频内容。
+
+---
+
+
+
+#### 7. 自动发帖功能
+
+最后,我们脚本提供了一个简易的发帖功能。用户可以发布图文或纯文字帖子,通过 `createPost(content, isImagePost)` 函数来实现发帖操作,函数可以模拟一系列点击操作,输入用户指定的内容,并选择添加图片或是不添加图片(根据选择的模式)并发布帖子。
+
+```javascript
+function createPost(content, isImagePost) {
+ click(539.5, 2338); // 定位并点击发帖按钮
+ if (isImagePost) {
+ click(307, 395); // 选择图片区域
+ setText(content); // 输入帖子内容
+ click(964.5, 173.5); // 点击发布
+ }
+}
+```
+
+`isImagePost` 参数决定是图文发布还是文字发布。这种模拟操作实现了简单的发帖功能,便于自动化管理发布内容。
+
+---
+
+###
+
+# 三、完整代码解释
+
+```javascript
+const staticComments = [ /* 静态评论内容数组,用于随机选择评论内容 */ ];
+const deviceW = 1080; // 设备宽度(可用device.width代替,但该函数有时会出现返回值为0的情况)
+const deviceH = 2400; // 设备高度(可用device.height代替,但该函数有时会出现返回值为0的情况)
+let isLiking = false; // 控制点赞开关
+let iscomment = false; // 控制评论开关
+let likeSpeed = 1000; // 初始点赞速度(毫秒)
+let likingInterval; // 存储点赞的定时器
+
+// 检查悬浮窗权限,如果没有则请求权限并退出脚本
+if (!floaty.checkPermission()) {
+ toast("请授予悬浮窗权限");
+ floaty.requestPermission();
+ exit();
+}
+
+// 创建悬浮窗
+let window = floaty.window(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+setTimeout(() => {
+ ui.run(() => {
+ window.liveCommentInput.setHintTextColor(colors.parseColor("#ffffff")); // 设置提示文字颜色为白色
+ window.postContentInput.setHintTextColor(colors.parseColor("#ffffff"));
+ });
+}, 500); // 延迟 500 毫秒
+
+// 设置初始位置和拖动
+window.setPosition(100, 100);
+window.setSize(-2, -2);
+
+// 监听触摸事件以实现拖动功能
+window.toggle.setOnTouchListener(function(view, event) {
+ switch (event.getAction()) {
+ case event.ACTION_DOWN:
+ x = event.getRawX();
+ y = event.getRawY();
+ windowX = window.getX();
+ windowY = window.getY();
+ downTime = new Date().getTime();
+ return true;
+ case event.ACTION_MOVE:
+ window.setPosition(windowX + (event.getRawX() - x), windowY + (event.getRawY() - y));
+ return true;
+ case event.ACTION_UP:
+ if (new Date().getTime() - downTime < 200) {
+ window.toggle.performClick();
+ }
+ return true;
+ }
+ return true;
+});
+
+// 切换悬浮窗的展开和收起状态
+window.toggle.click(function() {
+ if (window.controls.visibility === 0) {
+ window.controls.visibility = 8; // 收回
+ window.toggle.setText("展开");
+ } else {
+ window.controls.visibility = 0; // 展开
+ window.toggle.setText("爱猫的悬浮窗");
+ }
+});
+
+// 打开直播按钮事件
+window.openButton.click(() => {
+ toast("开始运行");
+ threads.start(function() {
+ startLiveOrSignIn(); // 在新线程中调用,避免阻塞 UI 线程
+ });
+});
+
+// 停止按钮事件
+window.stopButton.click(() => {
+ toast("停止运行");
+ window.close(); // 关闭悬浮窗
+ exit(); // 停止脚本运行
+});
+
+// 点赞按钮的点击事件
+window.likeButton.click(() => {
+ isLiking = !isLiking; // 切换点赞状态
+ if (isLiking) {
+ window.likeButton.setText("停止点赞");
+ startLiking(); // 开始点赞
+ } else {
+ window.likeButton.setText("开始点赞");
+ stopLiking(); // 停止点赞
+ }
+});
+
+// 发布帖子按钮事件
+window.publishPostButton.click(() => {
+ let postContent = window.postContentInput.text(); // 获取帖子内容
+ let isImagePost = window.isImagePost.isChecked(); // 获取是否图文发布
+ if (postContent) {
+ threads.start(() => {
+ createPost(postContent, isImagePost); // 调用发帖函数
+ });
+ toast("正在发布帖子...");
+ } else {
+ toast("请输入发帖内容!");
+ }
+});
+
+// 滑动条控制点赞速度
+window.speedControl.setOnSeekBarChangeListener({
+ onProgressChanged: function(seekBar, progress, fromUser) {
+ likeSpeed = 2500 - progress; // 调整点赞速度
+ toast("当前速度: " + likeSpeed + " 毫秒");
+ if (isLiking) {
+ stopLiking();
+ startLiking();
+ }
+ }
+});
+
+// 点赞功能
+function startLiking() {
+ stopLiking(); // 确保之前的定时器被清除,避免重复
+ toast("开始点赞");
+ likingInterval = setInterval(() => {
+ likePost();
+ }, likeSpeed);
+}
+
+// 停止点赞功能
+function stopLiking() {
+ toast("停止点赞");
+ if (typeof likingInterval !== 'undefined') {
+ clearInterval(likingInterval); // 清除定时器
+ likingInterval = undefined; // 重置 likingInterval
+ }
+}
+
+// 点赞操作
+function likePost() {
+ console.log("执行点赞操作");
+ click(900, 1000);
+ sleep(50);
+ click(900, 1000);
+ sleep(50);
+}
+
+// 保持脚本运行
+setInterval(() => {}, 1000);
+
+// 打开直播功能
+function startLiveOrSignIn() {
+ launchApp('小红书');
+ sleep(6000);
+ swipe(1080 / 2, 2400 / 4, 1080 / 2, 2400 * 3 / 4, 500);
+ sleep(1000);
+ click(273.5, 682);
+ sleep(5000);
+}
+
+// 自动直播或评论
+function startLiveOrComment(enableComment, enableStaticComment, dynamicCommentText) {
+ while (true) {
+ if (enableComment && !iscomment) {
+ let commentBox = desc("评论输入框").clickable(true).findOne(5000);
+ if (commentBox) {
+ commentBox.click();
+ sleep(1000);
+ enableStaticComment = window.enableStaticComment.checked;
+ dynamicCommentText = getDynamicCommentText();
+ let commentText = enableStaticComment ? getStaticComment() : dynamicCommentText;
+ input(commentText);
+ sleep(500);
+
+ let sendButton = text("发送").findOne(3000);
+ if (sendButton) {
+ sendButton.click();
+ console.log("评论发送成功:" + commentText);
+ } else {
+ console.log("未找到发送按钮");
+ }
+ sleep(3000);
+ } else {
+ console.log("未找到评论框,无法发送评论");
+ }
+ }
+ }
+}
+
+// 获取静态评论
+function getStaticComment() {
+ return staticComments[Math.floor(Math.random() * staticComments.length)];
+}
+
+// 开始评论按钮事件
+window.startLiveButton.click(() => {
+ iscomment = !iscomment;
+ if (iscomment) {
+ window.startLiveButton.setText("开始评论");
+ } else {
+ window.startLiveButton.setText("停止评论");
+ }
+ let commentEnabled = window.enableComment.checked;
+ let useStaticComment = window.enableStaticComment.checked;
+ let liveCommentText = window.liveCommentInput.text();
+
+ threads.start(() => {
+ startLiveOrComment(commentEnabled, useStaticComment, liveCommentText);
+ });
+
+ if (commentEnabled && (useStaticComment || liveCommentText)) {
+ toast("开始看直播并发送评论");
+ } else {
+ toast("开始看直播,不发送评论");
+ }
+});
+
+// 动态评论输入
+window.liveCommentInput.click(() => {
+ dialogs.rawInput("输入动态评论内容").then(input => {
+ if (input) {
+ window.liveCommentInput.setText(input);
+ }
+ });
+});
+
+// 获取动态评论内容
+function getDynamicCommentText() {
+ return window.liveCommentInput.getText();
+}
+
+// 自动刷新和关注功能
+let isAutoRefreshing = false;
+let isAutoFollowing = false;
+let autoRefreshThread;
+let autoFollowThread;
+
+// 自动关注按钮事件
+window.follow.click(() => {
+ if (!isAutoFollowing) {
+ isAutoFollowing = true;
+ autoFollowThread = threads.start(() => {
+ while (isAutoFollowing) {
+ let followButton = id("fv").findOne(2000);
+ if (followButton) {
+ followButton.click(); // 点击关注按钮
+ console.log("已点击关注(通过ID)");
+ } else {
+ // 如果通过 ID 找不到按钮,尝试通过文本查找
+ followButton = text("关注").findOne(2000);
+ if (followButton) {
+ followButton.click(); // 点击关注按钮
+ console.log("已点击关注 (通过文本)");
+ } else {
+ console.log("未找到关注按钮 (通过ID和文本)");
+ }
+ }
+ sleep(1000); // 等待 1 秒再进行下一次操作
+ }
+ });
+
+ // 更新按钮文本
+ window.follow.setText("停止关注");
+ } else {
+ // 如果已经在自动关注状态,则停止自动关注
+ console.log("停止自动关注");
+
+ isAutoFollowing = false;
+ if (autoFollowThread) {
+ autoFollowThread.interrupt(); // 停止线程
+ }
+
+ // 恢复按钮文本
+ window.follow.setText("关注");
+ }
+});
+
+// 自动刷按钮事件
+window.autoRefresh.click(() => {
+ if (!isAutoRefreshing) {
+ isAutoRefreshing = true;
+ console.log("开始自动刷");
+
+ // 创建一个新线程进行自动刷操作
+ autoRefreshThread = threads.start(function() {
+ while (isAutoRefreshing) {
+ swipe(deviceW / 3, deviceH / 2, deviceW / 2, deviceH / 4, 100); // 模拟向上滑动
+ console.log("切换到下一个视频");
+ sleep(5000); // 等待 5 秒再执行下一个滑动
+ }
+ });
+
+ // 更新按钮文本
+ window.autoRefresh.setText("停止自动刷");
+ } else {
+ // 如果已经在自动刷状态,则停止自动刷
+ isAutoRefreshing = false;
+ if (autoRefreshThread) {
+ autoRefreshThread.interrupt(); // 停止线程
+ }
+
+ console.log("停止自动刷");
+ window.autoRefresh.setText("自动刷"); // 恢复按钮文本
+ }
+});
+
+// 发帖功能实现
+function createPost(content, isImagePost) {
+ click(539.5, 2338); // 点击发帖按钮位置
+ sleep(3000);
+
+ if (isImagePost) {
+ console.log("图文发帖");
+ click(307, 395); // 选择图片区域
+ let nextBox = desc("下一步").clickable(true).findOne(3000);
+ if (nextBox) {
+ nextBox.click();
+ }
+ sleep(1500);
+ click(926, 2323); // 点击继续按钮
+ sleep(2000);
+ click(540, 796); // 选择图片的描述框
+ sleep(1000);
+ setText(content); // 输入内容
+ sleep(1000);
+ click(964.5, 173.5); // 发布帖子
+ sleep(1000);
+ } else {
+ console.log("仅文字发帖");
+ click(341, 2336.5); // 选择文字发帖区域
+ sleep(1500);
+ click(374, 1088); // 点击输入框
+ sleep(1500);
+ setText(content); // 输入内容
+ sleep(1000);
+ let nextBox = desc("下一步").clickable(true).findOne(3000);
+ if (nextBox) {
+ nextBox.click();
+ }
+ sleep(9000);
+ nextBox = desc("下一步").clickable(true).findOne(3000);
+ nextBox.click();
+ sleep(2000);
+ click(675, 2271); // 发布帖子
+ }
+ console.log("发帖完成");
+}
+
+// 监听发帖内容输入点击事件
+window.postContentInput.click(() => {
+ dialogs.rawInput("请输入发帖内容").then(input => {
+ if (input) {
+ window.postContentInput.setText(input); // 显示输入内容
+ }
+ });
+});
+```
\ No newline at end of file