From ea27e2d6b9c8b89c58d4195646b60a7dfa16d674 Mon Sep 17 00:00:00 2001
From: welsir <1824379011@qq.com>
Date: Mon, 16 Oct 2023 00:08:22 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E6=A8=A1=E5=9D=97=E5=AE=8C?=
=?UTF-8?q?=E6=88=90=E8=A7=86=E9=A2=91=E8=B4=A6=E5=8F=B7=E9=80=9A=E9=81=93?=
=?UTF-8?q?=EF=BC=8C=E8=A7=86=E9=A2=91=E5=8F=91=E5=B8=83=E6=A8=A1=E5=9D=97?=
=?UTF-8?q?=E9=87=8D=E6=9E=84=E8=A7=86=E9=A2=91=E5=8F=91=E5=B8=83=E6=9E=B6?=
=?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=AE=8C=E6=88=90b=E7=AB=99=E5=92=8C?=
=?UTF-8?q?=E6=8A=96=E9=9F=B3=E7=9A=84=E8=A7=86=E9=A2=91=E5=8F=91=E5=B8=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/compiler.xml | 4 +-
chopperbot-account/pom.xml | 4 +
.../core/init/VideoPushGuardInitMachine.java | 27 +++
.../org/example/core/platform/Bilibili.java | 15 +-
.../org/example/core/platform/Douyin.java | 66 +++---
.../org/example/core/pojo/VideoToPublish.java | 108 ++++++++++
.../core/script/douyin/ConfirmLogin.py | 56 +++++
.../org/example/core/script/douyin/Login.py | 47 ++++
.../java/org/example/util/GetScriptPath.java | 19 ++
.../example/core/bgevnet/BarrageEvent.java | 92 +++++---
chopperbot-publish/pom.xml | 5 +
.../java/org/example/api/VedioPublishApi.java | 21 ++
.../BilibiliURL.java} | 11 +-
.../factory/platformSelectionFactory.java | 23 ++
.../publisher/PlatformVideoPublisher.java | 6 +-
.../impl/BilibiliVideoPublisher.java | 200 ++++++++++++++++--
.../publisher/impl/DouyinVideoPublisher.java | 44 ++++
.../core/script/douyin/DouyinVideoPublish.py | 74 +++++++
18 files changed, 738 insertions(+), 84 deletions(-)
create mode 100644 chopperbot-account/src/main/java/org/example/core/init/VideoPushGuardInitMachine.java
create mode 100644 chopperbot-account/src/main/java/org/example/core/pojo/VideoToPublish.java
create mode 100644 chopperbot-account/src/main/java/org/example/core/script/douyin/ConfirmLogin.py
create mode 100644 chopperbot-account/src/main/java/org/example/core/script/douyin/Login.py
create mode 100644 chopperbot-account/src/main/java/org/example/util/GetScriptPath.java
create mode 100644 chopperbot-publish/src/main/java/org/example/api/VedioPublishApi.java
rename chopperbot-publish/src/main/java/org/example/core/{apiUrl/BilibiliApiUrl.java => constpool/BilibiliURL.java} (89%)
create mode 100644 chopperbot-publish/src/main/java/org/example/core/factory/platformSelectionFactory.java
create mode 100644 chopperbot-publish/src/main/java/org/example/core/publisher/impl/DouyinVideoPublisher.java
create mode 100644 chopperbot-publish/src/main/java/org/example/core/script/douyin/DouyinVideoPublish.py
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 93225a1..c210c1f 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -38,7 +38,7 @@
-
\ No newline at end of file
+
diff --git a/chopperbot-account/pom.xml b/chopperbot-account/pom.xml
index ab1119b..80e498b 100644
--- a/chopperbot-account/pom.xml
+++ b/chopperbot-account/pom.xml
@@ -114,5 +114,9 @@
okio
3.2.0
+
+ junit
+ junit
+
diff --git a/chopperbot-account/src/main/java/org/example/core/init/VideoPushGuardInitMachine.java b/chopperbot-account/src/main/java/org/example/core/init/VideoPushGuardInitMachine.java
new file mode 100644
index 0000000..2320722
--- /dev/null
+++ b/chopperbot-account/src/main/java/org/example/core/init/VideoPushGuardInitMachine.java
@@ -0,0 +1,27 @@
+package org.example.core.init;
+
+import org.example.constpool.ModuleName;
+import org.example.constpool.PluginName;
+import org.example.core.guard.VideoPushGuard;
+import org.example.init.CommonInitMachine;
+import org.example.plugin.CommonPlugin;
+import org.example.plugin.annotation.Plugin;
+
+import java.util.List;
+
+/**
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/13 19:09
+ */
+@Plugin(moduleName = ModuleName.ACCOUNT,
+ pluginName = PluginName.VIDEO_PUSH_PLUGIN,
+ pluginName_CN = "视频推送插件",
+ pluginDescription = "用于将切片好的视频自动推送至对应类型账号",
+ needPlugin = {},
+ pluginClass= VideoPushGuard.class )
+public class VideoPushGuardInitMachine extends CommonInitMachine {
+ public VideoPushGuardInitMachine(List needPlugins, boolean isAutoStart, String moduleName, String name, Class extends CommonPlugin> clazz) {
+ super(needPlugins, isAutoStart, moduleName, name, clazz);
+ }
+}
diff --git a/chopperbot-account/src/main/java/org/example/core/platform/Bilibili.java b/chopperbot-account/src/main/java/org/example/core/platform/Bilibili.java
index 3f56c3a..4cb4043 100644
--- a/chopperbot-account/src/main/java/org/example/core/platform/Bilibili.java
+++ b/chopperbot-account/src/main/java/org/example/core/platform/Bilibili.java
@@ -4,6 +4,7 @@ import org.example.core.factory.PlatformOperation;
import org.example.mapper.AccountMapper;
import org.example.core.pojo.Account;
+import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebElement;
@@ -50,15 +51,17 @@ public class Bilibili implements PlatformOperation {
Thread.sleep(3000L);
WebElement avator = confirmLogin.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[1]/ul[2]/li[1]"));
if(avator!=null){
- Account user = new Account();
- user.setCookies(cookies.toString());
- user.setPlatformId(1);
- user.setUsername(username);
- user.setPassword(password);
- accountMapper.insert(user);
+// Account user = new Account();
+// user.setCookies(cookies.toString());
+// user.setPlatformId(1);
+// user.setUsername(username);
+// user.setPassword(password);
+// accountMapper.insert(user);
+ System.out.println("登陆成功!");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
+
}
diff --git a/chopperbot-account/src/main/java/org/example/core/platform/Douyin.java b/chopperbot-account/src/main/java/org/example/core/platform/Douyin.java
index 2e4d1f9..2867ad8 100644
--- a/chopperbot-account/src/main/java/org/example/core/platform/Douyin.java
+++ b/chopperbot-account/src/main/java/org/example/core/platform/Douyin.java
@@ -4,8 +4,8 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONReader;
import org.example.core.factory.PlatformOperation;
-import org.example.mapper.AccountMapper;
import org.example.core.pojo.Account;
+import org.example.mapper.AccountMapper;
import org.openqa.selenium.Cookie;
import javax.annotation.Resource;
@@ -15,6 +15,8 @@ import java.util.Date;
import java.util.HashSet;
import java.util.List;
+import static org.example.util.GetScriptPath.getScriptPath;
+
/**
* @Description
* @Author welsir
@@ -23,7 +25,9 @@ import java.util.List;
public class Douyin implements PlatformOperation {
final String FILE_PATH = "D:\\Douyincookies.txt";
+ final String LOGIN_SCRIPT_PATH = "org/example/core/script/douyin/Login.py";
+ final String CONFIRM_LOGIN_SCRIPT_PATH = "org/example/core/script/douyin/ConfirmLogin.py";
@Resource
AccountMapper accountMapper;
@Override
@@ -31,41 +35,49 @@ public class Douyin implements PlatformOperation {
try {
List command = new ArrayList<>();
command.add("python"); // Python 解释器
- command.add("D:\\code\\gitHubProject\\Text_select_captcha\\DouyinLogin.py"); // 要运行的 Python 脚本文件名
+ command.add(getScriptPath(LOGIN_SCRIPT_PATH).toString()); // 要运行的 Python 脚本文件名
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
- List command1 = new ArrayList<>();
- command1.add("python"); // Python 解释器
- command1.add("D:\\code\\gitHubProject\\Text_select_captcha\\Douyin.py");
- ProcessBuilder processBuilder1 = new ProcessBuilder(command1);
- Process process1 = processBuilder1.start();
- // 获取Python脚本的标准输出流
- InputStream inputStream1 = process1.getInputStream();
- BufferedReader reader1 = new BufferedReader(new InputStreamReader(inputStream1));
+ int backCode = process.waitFor();
+ System.out.println(backCode);
+ if(backCode==0){
+ List command1 = new ArrayList<>();
+ command1.add("python"); // Python 解释器
+ command1.add(getScriptPath(CONFIRM_LOGIN_SCRIPT_PATH).toString());
+ ProcessBuilder processBuilder1 = new ProcessBuilder(command1);
+ Process process1 = processBuilder1.start();
+ // 获取Python脚本的标准输出流
+ InputStream inputStream1 = process1.getInputStream();
+ BufferedReader reader1 = new BufferedReader(new InputStreamReader(inputStream1));
- String line1;
- StringBuilder callBack = new StringBuilder();
+ String line1;
+ StringBuilder callBack = new StringBuilder();
- // 读取Python脚本的输出
- while ((line1 = reader1.readLine()) != null) {
- callBack.append(line1).append("\n");
- }
- System.out.println("验证flag:" + callBack);
- // 等待Python脚本执行完成
- int exitCode = process1.waitFor();
- if (exitCode == 0) {
- System.out.println("抖音登录成功!");
- Account account = new Account();
- account.setUsername(username);
- account.setCookies(loadCookiesFromFile(FILE_PATH).toString());
- account.setPlatformId(2);
- accountMapper.insert(account);
+ // 读取Python脚本的输出
+ while ((line1 = reader1.readLine()) != null) {
+ callBack.append(line1).append("\n");
+ }
+ System.out.println("验证flag:" + callBack);
+ // 等待Python脚本执行完成
+ int exitCode = process1.waitFor();
+ if (exitCode == 0) {
+ System.out.println("抖音登录成功!");
+ Account account = new Account();
+ account.setUsername(username);
+ account.setCookies(loadCookiesFromFile(FILE_PATH).toString());
+ account.setPlatformId(2);
+ accountMapper.insert(account);
+ }
+ }else{
+ throw new RuntimeException("登陆失败!");
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
- public HashSet loadCookiesFromFile (String filePath) throws IOException {
+
+ //从本地文件获取cookie
+ private HashSet loadCookiesFromFile (String filePath) throws IOException {
HashSet cookies = new HashSet<>();
try (FileReader fileReader = new FileReader(filePath)) {
JSONReader reader = new JSONReader(fileReader);
diff --git a/chopperbot-account/src/main/java/org/example/core/pojo/VideoToPublish.java b/chopperbot-account/src/main/java/org/example/core/pojo/VideoToPublish.java
new file mode 100644
index 0000000..3383841
--- /dev/null
+++ b/chopperbot-account/src/main/java/org/example/core/pojo/VideoToPublish.java
@@ -0,0 +1,108 @@
+package org.example.core.pojo;
+
+import lombok.Data;
+
+/**
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/13 19:02
+ */
+
+@Data
+public class VideoToPublish {
+
+ private String videoPath;
+ private String cookies;
+ private PlatformType platform;
+ private String coverPath;
+ private String devicePath;
+ private String tag;
+ private String title;
+ private String type;
+
+ private VideoToPublish(Buider buider){
+ this.videoPath = buider.videoPath;
+ this.cookies = buider.cookies;
+ this.coverPath = buider.coverPath;
+ this.devicePath = buider.devicePath;
+ this.tag = buider.tag;
+ this.title = buider.title;
+ this.type = buider.type;
+ }
+
+ public static class Buider{
+ private String videoPath;
+ private String cookies;
+ private PlatformType platform;
+ private String coverPath;
+ private String devicePath;
+ private String tag;
+ private String title;
+ private String type;
+
+ public Buider(String videoPath,String cookies,int platform){
+ this.videoPath = videoPath;
+ this.cookies = cookies;
+ this.platform = PlatformType.getPlatform(platform);
+ }
+
+ public Buider setCoverPath(String coverPath) {
+ this.coverPath = coverPath;
+ return this;
+ }
+
+ public Buider setDevicePath(String devicePath) {
+ this.devicePath = devicePath;
+ return this;
+ }
+
+ public Buider setTag(String tag) {
+ this.tag = tag;
+ return this;
+ }
+
+ public Buider setTitle(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public Buider setType(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public String getVideoPath() {
+ return videoPath;
+ }
+
+ public String getCookies() {
+ return cookies;
+ }
+
+ public String getCoverPath() {
+ return coverPath;
+ }
+
+ public String getDevicePath() {
+ return devicePath;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public VideoToPublish build(){
+ return new VideoToPublish(this);
+ }
+
+ }
+
+}
diff --git a/chopperbot-account/src/main/java/org/example/core/script/douyin/ConfirmLogin.py b/chopperbot-account/src/main/java/org/example/core/script/douyin/ConfirmLogin.py
new file mode 100644
index 0000000..a22d48a
--- /dev/null
+++ b/chopperbot-account/src/main/java/org/example/core/script/douyin/ConfirmLogin.py
@@ -0,0 +1,56 @@
+import json
+import sys
+import time
+
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+
+class douyin(object):
+
+ def __init__(self):
+ chrome_options = self.options()
+ chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
+ # 解决报错,设置无界面运行
+ chrome_options.add_argument('--no-sandbox')
+ chrome_options.add_argument('--disable-dev-shm-usage')
+ chrome_options.add_argument('window-size=1920x1280') # 指定浏览器分辨率
+ chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
+ chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
+ self.browser = webdriver.Chrome(chrome_options)
+ self.wait = WebDriverWait(self.browser, 30)
+ self.url = "https://www.douyin.com/"
+
+ def options(self):
+ chrome_options = webdriver.ChromeOptions()
+ return chrome_options
+
+ def click(self, xpath):
+ self.wait.until(EC.presence_of_element_located(
+ (By.XPATH, xpath))).click()
+
+ def loadCookie(self):
+ f = open('D:\\Douyincookies.txt')
+ cookies = json.loads(f.read())
+ self.browser.get(self.url)
+ self.browser.delete_all_cookies()
+ for cookie in cookies:
+ self.browser.add_cookie(cookie)
+
+ self.browser.implicitly_wait(10)
+ time.sleep(2)
+ self.browser.refresh()
+ self.browser.get(self.url)
+ userMsg = '/html/body/div[2]/div[1]/div[4]/div[2]/div[1]/header/div/div/div[2]/div/div/div[6]/div/a'
+ loginFlag = self.browser.find_element(By.XPATH, userMsg)
+ if not loginFlag is None:
+ print("success")
+ else:
+ print("error")
+
+
+if __name__ == '__main__':
+ jd = douyin()
+ jd.loadCookie()
diff --git a/chopperbot-account/src/main/java/org/example/core/script/douyin/Login.py b/chopperbot-account/src/main/java/org/example/core/script/douyin/Login.py
new file mode 100644
index 0000000..503a93a
--- /dev/null
+++ b/chopperbot-account/src/main/java/org/example/core/script/douyin/Login.py
@@ -0,0 +1,47 @@
+import json
+import time
+
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+class dy(object):
+
+ def __init__(self):
+ chrome_options = self.options()
+ chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
+ # 解决报错,设置无界面运行
+ chrome_options.add_argument('--no-sandbox')
+ chrome_options.add_argument('--disable-dev-shm-usage')
+ chrome_options.add_argument('window-size=1920x1280') # 指定浏览器分辨率
+ chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
+ chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
+ self.browser = webdriver.Chrome(chrome_options)
+ self.wait = WebDriverWait(self.browser, 30)
+ self.url = "https://www.douyin.com/"
+
+ def options(self):
+ chrome_options = webdriver.ChromeOptions()
+ return chrome_options
+
+ def click(self, xpath):
+ self.wait.until(EC.presence_of_element_located(
+ (By.XPATH, xpath))).click()
+
+ def saveCookie(self):
+ # 打开浏览器
+ self.browser.get(self.url)
+ time.sleep(35)
+ # 读取cook
+ cook = self.browser.get_cookies()
+ # 保存cook
+ f = open('D:\\Douyincookies.txt', 'w')
+ f.write(json.dumps(cook, ensure_ascii=True)) # 格式转化,这不管你是学的那种语言都必须要知道的
+ f.close()
+ print("success")
+
+
+if __name__ == '__main__':
+ jd = dy()
+ jd.saveCookie()
diff --git a/chopperbot-account/src/main/java/org/example/util/GetScriptPath.java b/chopperbot-account/src/main/java/org/example/util/GetScriptPath.java
new file mode 100644
index 0000000..b261a61
--- /dev/null
+++ b/chopperbot-account/src/main/java/org/example/util/GetScriptPath.java
@@ -0,0 +1,19 @@
+package org.example.util;
+
+import java.io.File;
+import java.nio.file.Path;
+
+/**
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/15 20:43
+ */
+public class GetScriptPath {
+
+ public static Path getScriptPath(String path){
+ // 构建绝对路径
+ File scriptFile = new File(path);
+ return Path.of(scriptFile.getAbsolutePath());
+ }
+
+}
diff --git a/chopperbot-barrage/src/main/java/org/example/core/bgevnet/BarrageEvent.java b/chopperbot-barrage/src/main/java/org/example/core/bgevnet/BarrageEvent.java
index f5b2bf9..9321083 100644
--- a/chopperbot-barrage/src/main/java/org/example/core/bgevnet/BarrageEvent.java
+++ b/chopperbot-barrage/src/main/java/org/example/core/bgevnet/BarrageEvent.java
@@ -39,31 +39,6 @@ public class BarrageEvent {
private List barrages;
private boolean isSort = false;
- public BarrageEvent(String platform, String action, String liver, String date) {
- this.action = action;
- this.platform = platform;
- this.liver = liver;
- this.date = date;
- this.fileName = Paths.get(FileNameBuilder.buildBarrageFileName(liver,date)).toString();
- }
-
- public BarrageEvent(String platform, String action, String liver, String date, List barrages) {
- this.action = action;
- this.platform = platform;
- this.liver = liver;
- this.date = date;
- this.barrages = barrages;
- this.fileName = Paths.get(FileNameBuilder.buildBarrageFileName(liver,date)).toString();
- }
-
- public BarrageEvent(String platform, String action, String liver, String date, String fileName) {
- this.platform = platform;
- this.action = action;
- this.liver = liver;
- this.date = date;
- this.fileName = fileName;
- }
-
public String getBarrageFilePath(){
if(platform==null||action==null){
return fileName;
@@ -71,6 +46,14 @@ public class BarrageEvent {
return Paths.get(BarrageSaveFile.fileRoot(action,platform), fileName).toString();
}
+ private BarrageEvent(Builder builder){
+ this.action = builder.action;
+ this.date = builder.date;
+ this.fileName = builder.fileName;
+ this.liver = builder.liver;
+ this.platform = builder.platform;
+ }
+
public List getBarrages() {
if(barrages==null){
try {
@@ -87,4 +70,63 @@ public class BarrageEvent {
}
return barrages;
}
+ public static class Builder{
+ private String platform;
+
+ private String action;
+ private String liver;
+ private String date;
+
+ private String fileName;
+
+
+ public BarrageEvent build(){
+ return new BarrageEvent(this);
+ }
+
+ public Builder setPlatform(String platform){
+ this.platform = platform;
+ return this;
+ }
+
+ public Builder setAction(String action){
+ this.action = action;
+ return this;
+ }
+
+ public Builder setLiver(String liver){
+ this.liver = liver;
+ return this;
+ }
+
+ public Builder setDate(String date){
+ this.date = date;
+ return this;
+ }
+
+ public Builder setFilename(String fileName){
+ this.fileName = fileName;
+ return this;
+ }
+
+ public String getPlatform() {
+ return platform;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getLiver() {
+ return liver;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+ }
}
diff --git a/chopperbot-publish/pom.xml b/chopperbot-publish/pom.xml
index b0b00af..e7a6e7d 100644
--- a/chopperbot-publish/pom.xml
+++ b/chopperbot-publish/pom.xml
@@ -43,5 +43,10 @@
1.0-SNAPSHOT
compile
+
+ org.example
+ chopperbot-account
+ 1.0-SNAPSHOT
+
diff --git a/chopperbot-publish/src/main/java/org/example/api/VedioPublishApi.java b/chopperbot-publish/src/main/java/org/example/api/VedioPublishApi.java
new file mode 100644
index 0000000..d1691b2
--- /dev/null
+++ b/chopperbot-publish/src/main/java/org/example/api/VedioPublishApi.java
@@ -0,0 +1,21 @@
+package org.example.api;
+
+import org.example.core.factory.platformSelectionFactory;
+import org.example.core.pojo.VideoToPublish;
+import org.example.core.publisher.PlatformVideoPublisher;
+
+/**
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/13 17:14
+ */
+public class VedioPublishApi {
+
+ public static void publishVideo(VideoToPublish videoEntity){
+ PlatformVideoPublisher publisher = platformSelectionFactory.creatPlatformPublisher(videoEntity.getPlatform().getId());
+ publisher.publishVideo(videoEntity);
+ }
+
+
+
+}
diff --git a/chopperbot-publish/src/main/java/org/example/core/apiUrl/BilibiliApiUrl.java b/chopperbot-publish/src/main/java/org/example/core/constpool/BilibiliURL.java
similarity index 89%
rename from chopperbot-publish/src/main/java/org/example/core/apiUrl/BilibiliApiUrl.java
rename to chopperbot-publish/src/main/java/org/example/core/constpool/BilibiliURL.java
index cb51fcf..f5e6348 100644
--- a/chopperbot-publish/src/main/java/org/example/core/apiUrl/BilibiliApiUrl.java
+++ b/chopperbot-publish/src/main/java/org/example/core/constpool/BilibiliURL.java
@@ -1,10 +1,12 @@
-package org.example.core.apiUrl;
+package org.example.core.constpool;
/**
- * @author dhx
- * @date 2023/9/25 21:01
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/13 20:07
*/
-public class BilibiliApiUrl {
+public class BilibiliURL {
+
public final static String VIDEO_PREUPLOAD_URL = "https://member.bilibili.com/preupload?probe_version=20221109&upcdn=bda2&zone=cs&name=test.mp4&r=upos&profile=ugcfx%%2Fbup&ssl=0&version=2.14.0.0&build=2140000&size=%s&webVersion=2.14.0";
public final static String TXT_PREUPLOAD_URL= "https://member.bilibili.com/preupload?name=file_meta.txt&size=2000&r=upos&profile=fxmeta%2Fbup&ssl=0&version=2.14.0.0&build=2140000&webVersion=2.14.0";
@@ -18,4 +20,5 @@ public class BilibiliApiUrl {
public final static String COVER_UPLOAD_URL = "https://member.bilibili.com/x/vu/web/cover/up?t=";
public final static String SEND_MANUSCRIPT_URL = "https://member.bilibili.com/x/vu/web/add/v3?t=%s&csrf=%s";
+
}
diff --git a/chopperbot-publish/src/main/java/org/example/core/factory/platformSelectionFactory.java b/chopperbot-publish/src/main/java/org/example/core/factory/platformSelectionFactory.java
new file mode 100644
index 0000000..cf81807
--- /dev/null
+++ b/chopperbot-publish/src/main/java/org/example/core/factory/platformSelectionFactory.java
@@ -0,0 +1,23 @@
+package org.example.core.factory;
+
+import org.example.core.publisher.PlatformVideoPublisher;
+import org.example.core.publisher.impl.BilibiliVideoPublisher;
+import org.example.core.publisher.impl.DouyinVideoPublisher;
+
+/**
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/13 21:09
+ */
+public class platformSelectionFactory {
+ public static PlatformVideoPublisher creatPlatformPublisher(int platformId) {
+ switch (platformId){
+ case 2:
+ return new BilibiliVideoPublisher();
+ case 3:
+ return new DouyinVideoPublisher();
+ default:
+ throw new IllegalArgumentException("平台参数不正确!");
+ }
+ }
+}
diff --git a/chopperbot-publish/src/main/java/org/example/core/publisher/PlatformVideoPublisher.java b/chopperbot-publish/src/main/java/org/example/core/publisher/PlatformVideoPublisher.java
index 81a6fe2..a58419b 100644
--- a/chopperbot-publish/src/main/java/org/example/core/publisher/PlatformVideoPublisher.java
+++ b/chopperbot-publish/src/main/java/org/example/core/publisher/PlatformVideoPublisher.java
@@ -1,11 +1,11 @@
package org.example.core.publisher;
-import org.example.pojo.Uploader;
+import org.example.core.pojo.VideoToPublish;
/**
* @author dhx
* @date 2023/9/18 20:49
*/
-public interface PlatformVideoPublisher {
- void publishVideo(T uploader);
+public interface PlatformVideoPublisher {
+ void publishVideo(VideoToPublish video);
}
diff --git a/chopperbot-publish/src/main/java/org/example/core/publisher/impl/BilibiliVideoPublisher.java b/chopperbot-publish/src/main/java/org/example/core/publisher/impl/BilibiliVideoPublisher.java
index 842aaa8..39c4e78 100644
--- a/chopperbot-publish/src/main/java/org/example/core/publisher/impl/BilibiliVideoPublisher.java
+++ b/chopperbot-publish/src/main/java/org/example/core/publisher/impl/BilibiliVideoPublisher.java
@@ -10,7 +10,8 @@ import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
-import org.example.core.apiUrl.BilibiliApiUrl;
+import org.example.core.constpool.BilibiliURL;
+import org.example.core.pojo.VideoToPublish;
import org.example.core.publisher.PlatformVideoPublisher;
import org.example.exception.ChopperBotException;
import org.example.pojo.BilibiliUploader;
@@ -32,14 +33,15 @@ import static java.nio.charset.StandardCharsets.UTF_8;
* @author dhx
* @date 2023/9/18 20:49
*/
-public class BilibiliVideoPublisher implements PlatformVideoPublisher {
+public class BilibiliVideoPublisher implements PlatformVideoPublisher {
+
@Override
- public void publishVideo(BilibiliUploader bilibiliUploader) {
- Map header = bilibiliUploader.getHeader();
- String videoPath = bilibiliUploader.getVideoPath();
- String devicePath = bilibiliUploader.getDeviceVideoPath();
- String cookie = bilibiliUploader.getCookie();
- String coverPath = bilibiliUploader.getCoverPath();
+ public void publishVideo(VideoToPublish video) {
+ Map header = new HashMap<>();
+ String videoPath = video.getVideoPath();
+ String devicePath = video.getDevicePath();
+ String cookie = video.getCookies();
+ String coverPath = video.getCoverPath();
String csrf = CookieUtil.getParam(cookie,"bili_jct");
if(csrf == null){
throw new ChopperBotException("Cookie错误");
@@ -48,9 +50,8 @@ public class BilibiliVideoPublisher implements PlatformVideoPublisher header2 = new HashMap<>();
header2.put("X-Upos-Auth", auth);
String res3 = HttpClientUtil.post(preUploadUrl, "{}", header2);
@@ -78,7 +79,6 @@ public class BilibiliVideoPublisher implements PlatformVideoPublisher header = bilibiliUploader.getHeader();
+// String videoPath = bilibiliUploader.getVideoPath();
+// String devicePath = bilibiliUploader.getDeviceVideoPath();
+// String cookie = bilibiliUploader.getCookie();
+// String coverPath = bilibiliUploader.getCoverPath();
+// String csrf = CookieUtil.getParam(cookie,"bili_jct");
+// if(csrf == null){
+// throw new ChopperBotException("Cookie错误");
+// }
+// int filesize = FileUtil.getFilesize(videoPath);
+// if (filesize == -1) {
+// throw new ChopperBotException("获取文件大小失败");
+// }
+//
+// //申请上传
+// String res = HttpClientUtil.get(String.format(BilibiliURL.VIDEO_PREUPLOAD_URL,filesize)
+// , header);
+// JSONObject mp4Obj = JSONObject.parseObject(res);
+// String mp4_upos_uri = mp4Obj.getString("upos_uri");
+// String put_query = mp4Obj.getString("put_query");
+// String endpoint = mp4Obj.getString("endpoint");
+// Long chunk_size = mp4Obj.getLong("chunk_size");
+// Long biz_id = mp4Obj.getLong("biz_id");
+// String auth = mp4Obj.getString("auth");
+//
+//
+// String res2 = HttpClientUtil.get(BilibiliURL.TXT_PREUPLOAD_URL, header);
+// JSONObject txtObj = JSONObject.parseObject(res2);
+// String meta_upos_uri = txtObj.getString("upos_uri");
+// String preUploadUrl = String.format(BilibiliURL.PREUPLOAD_URL, endpoint, mp4_upos_uri.substring(mp4_upos_uri.indexOf('/') + 1), put_query.substring(put_query.indexOf('&')), String.valueOf(filesize), chunk_size, meta_upos_uri, biz_id);
+// Map header2 = new HashMap<>();
+// header2.put("X-Upos-Auth", auth);
+// String res3 = HttpClientUtil.post(preUploadUrl, "{}", header2);
+// JSONObject uploadObj = JSONObject.parseObject(res3);
+// String upload_id = uploadObj.getString("upload_id");
+//
+// //视频分片
+// int chunkNumber = VideoDeviceUtil.device(videoPath, devicePath, chunk_size);
+// if (chunkNumber != -1) {
+// chunkNumber--;
+// } else {
+// throw new ChopperBotException("分割视频失败");
+// }
+//
+// //上传视频
+// for (int i = 1; i <= chunkNumber; i++) {
+// long end = i == chunkNumber ? filesize : i * chunk_size;
+// long start = (i - 1) * chunk_size;
+// File file = new File(devicePath + "chunk_" + i + ".bin");
+// if (!file.exists()) {
+// throw new ChopperBotException(String.format("未找到视频片段%s", i));
+// }
+// try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+// HttpPut httpPut = new HttpPut(String.format(BilibiliURL.VIDEO_UPLOAD_URL,
+// endpoint, mp4_upos_uri.substring(mp4_upos_uri.indexOf('/') + 1), i, upload_id, i - 1, chunkNumber, end - start, start, end, filesize)); // 替换为实际的目标URL
+//
+// byte[] binaryData = new byte[(int) file.length()];
+// FileInputStream fileInputStream = new FileInputStream(file);
+// fileInputStream.read(binaryData);
+// fileInputStream.close();
+//
+// ByteArrayEntity entity = new ByteArrayEntity(binaryData);
+// httpPut.setEntity(entity);
+// httpPut.setHeader("Content-Type", "application/octet-stream");
+// httpPut.setHeader("X-Upos-Auth", auth);
+//
+// CloseableHttpResponse response = httpClient.execute(httpPut);
+// int statusCode = response.getStatusLine().getStatusCode();
+// if (statusCode == 200) {
+// System.out.println("上传中:" + i * 100 / chunkNumber + "%");
+// }
+// } catch (IOException e) {
+// e.printStackTrace();
+// }
+// }
+//
+// VideoDeviceUtil.deleteChunks(devicePath);
+//
+// //通知上传完成
+// JSONObject body = new JSONObject();
+// JSONArray parts = new JSONArray();
+// for (int i = 1; i <= chunkNumber; i++) {
+// JSONObject item = new JSONObject();
+// item.put("partNumber", i);
+// item.put("eTag", "etag");
+// parts.add(item);
+// }
+// body.put("parts", parts);
+// String res4 = HttpClientUtil.post(
+// String.format(
+// BilibiliURL.UPLOAD_FINISHI_URL,
+// endpoint, mp4_upos_uri.substring(mp4_upos_uri.indexOf('/') + 1), put_query.substring(put_query.indexOf('&')), upload_id, biz_id
+// ), body.toString(), header2
+// );
+//
+// //上传封面
+// String base64Image = "";
+// try {
+// File imageFile = new File(coverPath);
+// FileInputStream fileInputStream = new FileInputStream(imageFile);
+// byte[] imageData = new byte[(int) imageFile.length()];
+// fileInputStream.read(imageData);
+// fileInputStream.close();
+// base64Image = Base64.getEncoder().encodeToString(imageData);
+// base64Image = "data:image/jpeg;base64," + base64Image;
+// } catch (IOException e) {
+// e.printStackTrace();
+// }
+// List list = new ArrayList<>();
+// list.add(new BasicNameValuePair("cover", base64Image));
+// list.add(new BasicNameValuePair("csrf", csrf));
+// UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, UTF_8);
+// String res5 = HttpClientUtil.post(BilibiliURL.COVER_UPLOAD_URL + LocalTime.now(), urlEncodedFormEntity, header);
+// JSONObject cover = JSONObject.parseObject(res5);
+// JSONObject coverData = cover.getJSONObject("data");
+// if (coverData == null) return;
+// String coverUrl = coverData.getString("url");
+//
+// //发布视频
+// JSONObject body1 = new JSONObject();
+// JSONObject subtitle = new JSONObject();
+// JSONArray videos = new JSONArray();
+// subtitle.put("open", 0);
+// subtitle.put("lan", " ");
+// JSONObject param_video = new JSONObject();
+// param_video.put("filename", mp4_upos_uri.substring(mp4_upos_uri.lastIndexOf('/') + 1, mp4_upos_uri.indexOf('.')));
+// param_video.put("title", "test");
+// param_video.put("desc", "");
+// param_video.put("cid", biz_id);
+// videos.add(param_video);
+// body1.put("act_reserve_create", 0);
+// body1.put("copyright", 1);
+// body1.put("cover", coverUrl); //封面
+// body1.put("csrf", csrf);
+// body1.put("desc", "");
+// body1.put("desc_format_id", 0);
+// body1.put("dolby", 0);
+// body1.put("dynamic", "");
+// body1.put("interactive", 0);
+// body1.put("lossless_music", 0);
+// body1.put("no_disturbance", 0);
+// body1.put("no_reprint", 1);
+// body1.put("recreate", -1);
+// body1.put("tag", "助眠,音乐"); //视频标签
+// body1.put("tid", 130); //视频分区 130:音乐综合
+// body1.put("title", "test");
+// body1.put("up_close_danmu", false);
+// body1.put("up_close_reply", false);
+// body1.put("up_selection_reply", false);
+// body1.put("web_os", 1);
+// body1.put("subtitle", subtitle);
+// body1.put("videos", videos);
+// String res6 = HttpClientUtil.post(String.format(BilibiliURL.SEND_MANUSCRIPT_URL, LocalTime.now(), csrf), body1.toString(), header);
+// JSONObject res6Obj = JSONObject.parseObject(res6);
+// int code = res6Obj.getInteger("code");
+// if (code == 0) {
+// System.out.println("发布成功");
+// } else {
+// System.out.println(res6);
+// throw new ChopperBotException("发布失败,请手动发布");
+// }
+// }
+
}
diff --git a/chopperbot-publish/src/main/java/org/example/core/publisher/impl/DouyinVideoPublisher.java b/chopperbot-publish/src/main/java/org/example/core/publisher/impl/DouyinVideoPublisher.java
new file mode 100644
index 0000000..dc2d394
--- /dev/null
+++ b/chopperbot-publish/src/main/java/org/example/core/publisher/impl/DouyinVideoPublisher.java
@@ -0,0 +1,44 @@
+package org.example.core.publisher.impl;
+
+import org.example.core.pojo.VideoToPublish;
+import org.example.core.publisher.PlatformVideoPublisher;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.example.util.GetScriptPath.getScriptPath;
+
+/**
+ * @Description
+ * @Author welsir
+ * @Date 2023/10/13 20:11
+ */
+public class DouyinVideoPublisher implements PlatformVideoPublisher {
+
+ final String DOUYIN_PUBLISH_VIDEO = "org/example/core/script/douyin/DouyinVideoPublish.py";
+
+ @Override
+ public void publishVideo(VideoToPublish video) {
+ try {
+ List command = new ArrayList<>();
+ command.add("python"); // Python 解释器
+ command.add(getScriptPath(DOUYIN_PUBLISH_VIDEO).toString()); // 要运行的 Python 脚本文件名
+ //目前默认只有三个参数
+ command.add(video.getCookies());
+ command.add(video.getVideoPath());
+ command.add(video.getTitle());
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+ Process process;
+ process = processBuilder.start();
+ int backCode = process.waitFor();
+ if(backCode==0){
+ System.out.println("视频发布成功!");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/chopperbot-publish/src/main/java/org/example/core/script/douyin/DouyinVideoPublish.py b/chopperbot-publish/src/main/java/org/example/core/script/douyin/DouyinVideoPublish.py
new file mode 100644
index 0000000..03a078d
--- /dev/null
+++ b/chopperbot-publish/src/main/java/org/example/core/script/douyin/DouyinVideoPublish.py
@@ -0,0 +1,74 @@
+import sys
+
+import time
+
+from selenium.webdriver.chrome import webdriver
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+class douyin(object):
+
+ def __init__(self):
+ chrome_options = self.options()
+ chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
+ # 解决报错,设置无界面运行
+ chrome_options.add_argument('--no-sandbox')
+ chrome_options.add_argument('--disable-dev-shm-usage')
+ chrome_options.add_argument('window-size=1920x1280') # 指定浏览器分辨率
+ chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
+ chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
+ self.browser = webdriver.Chrome(chrome_options)
+ self.wait = WebDriverWait(self.browser, 30)
+ self.url = "https://www.douyin.com/"
+
+ def options(self):
+ chrome_options = webdriver.ChromeOptions()
+ return chrome_options
+
+ def click(self, xpath):
+ self.wait.until(EC.presence_of_element_located(
+ (By.XPATH, xpath))).click()
+
+ def puiblish(self):
+ cookies = sys.argv[0]
+ self.browser.get(self.url)
+ self.browser.delete_all_cookies()
+ for cookie in cookies:
+ self.browser.add_cookie(cookie)
+ self.browser.implicitly_wait(10)
+ time.sleep(2)
+ self.browser.refresh()
+ self.browser.get(self.url)
+ userMsg = '/html/body/div[2]/div[1]/div[4]/div[2]/div[1]/header/div/div/div[2]/div/div/div[6]/div/a'
+ loginFlag = self.wait.until(EC.presence_of_element_located(
+ (By.XPATH, userMsg)))
+ if not loginFlag is None:
+ self.click(userMsg)
+ time.sleep(2)
+ videoPage = '/html/body/div[2]/div[1]/div[3]/div[3]/div/div/div[3]/div[2]/div[2]/div[1]/div[2]/div/div[1]/a'
+ self.click(videoPage)
+ all_h = self.browser.window_handles
+ self.browser.switch_to.window(all_h[1])
+ h2 = self.browser.current_window_handle
+ send_video = "/html/body/div[1]/div/div[2]/div[2]/div/div/div/div[1]/button"
+ self.click(send_video)
+ time.sleep(2)
+ video_path = '/html/body/div[1]/div/div[2]/div[3]/div/div/div/div[2]/div/div/div/div[3]/div/div[1]/div/div[1]/div/label/input'
+ filePath = sys.argv[1]
+ self.wait.until(EC.presence_of_element_located((By.XPATH, video_path))).send_keys(filePath)
+ time.sleep(2)
+ video_title = '/html/body/div[1]/div/div[2]/div[3]/div/div/div/div[2]/div/div/div/div[2]/div[1]/div[2]/div/div/div/div[1]/div'
+ self.wait.until(EC.presence_of_element_located((By.XPATH, video_title))).send_keys(
+ sys.argv[2])
+ push_video = '/html/body/div[1]/div/div[2]/div[3]/div/div/div/div[2]/div/div/div/div[2]/div[1]/div[18]/button[1]'
+ time.sleep(2)
+ self.click(push_video)
+ time.sleep(2)
+ else:
+ print("error")
+
+if __name__ == '__main__':
+ jd = douyin()
+ jd.puiblish()