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 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()