mirror of
https://github.com/Paillat-dev/viralfactory.git
synced 2026-01-02 09:16:19 +00:00
Add UploadEngine and its dependencies
This commit is contained in:
12
src/engines/UploadEngine/BaseUploadEngine.py
Normal file
12
src/engines/UploadEngine/BaseUploadEngine.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from abc import abstractmethod
|
||||
|
||||
from .. import BaseEngine
|
||||
|
||||
|
||||
class BaseUploadEngine(BaseEngine):
|
||||
def __init__(self, **kwargs) -> None:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def upload(self):
|
||||
...
|
||||
75
src/engines/UploadEngine/TikTokUploadEngine.py
Normal file
75
src/engines/UploadEngine/TikTokUploadEngine.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import gradio as gr
|
||||
|
||||
from tiktok_uploader.upload import upload_video
|
||||
|
||||
from .BaseUploadEngine import BaseUploadEngine
|
||||
|
||||
|
||||
class TikTokUploadEngine(BaseUploadEngine):
|
||||
name = "TikTokUpload"
|
||||
description = "Upload to TikTok"
|
||||
|
||||
num_options = 1
|
||||
|
||||
def __init__(self, options) -> None:
|
||||
self.hashtags = options[0]
|
||||
super().__init__()
|
||||
|
||||
def upload(self):
|
||||
cookies = self.get_setting(type="cookies")["cookies"]
|
||||
if cookies == None:
|
||||
gr.Warning(
|
||||
"Skipping upload to TikTok because no cookies were provided. Please provide cookies in the settings."
|
||||
)
|
||||
return
|
||||
title: str = self.ctx.title
|
||||
description: str = self.ctx.description
|
||||
hastags = self.hashtags.strip().split(" ")
|
||||
|
||||
# extract any hashtags from the description / title and remove them from the description
|
||||
for word in title.split():
|
||||
if word.startswith("#"):
|
||||
hastags.append(word)
|
||||
title = title.replace(word, "")
|
||||
for word in description.split():
|
||||
if word.startswith("#"):
|
||||
hastags.append(word)
|
||||
description = description.replace(word, "")
|
||||
|
||||
title = title.strip()
|
||||
description = description.strip()
|
||||
hastags_str = " ".join(hastags) + " " if hastags else ""
|
||||
failed = upload_video(
|
||||
filename=self.ctx.get_file_path("final.mp4"),
|
||||
description=f"{title} {description} {hastags_str}",
|
||||
cookies_str=cookies,
|
||||
browser="firefox",
|
||||
)
|
||||
for _ in failed:
|
||||
gr.Error(f"Failed to upload to TikTok")
|
||||
|
||||
@classmethod
|
||||
def get_options(cls):
|
||||
hashtags = gr.Textbox(label="hashtags", type="text", value="#fyp #foryou")
|
||||
return [hashtags]
|
||||
|
||||
@classmethod
|
||||
def get_settings(cls):
|
||||
current_settings = cls.get_setting(type="cookies") or {"cookies": ""}
|
||||
gr.Markdown(
|
||||
"Input your TikTok session cookies. You can get them as shown [here](https://github.com/wkaisertexas/tiktok-uploader?tab=readme-ov-file#authentication)."
|
||||
)
|
||||
cookies_input = gr.Textbox(
|
||||
lines=20,
|
||||
max_lines=50,
|
||||
label="cookies",
|
||||
type="text",
|
||||
value=current_settings["cookies"],
|
||||
)
|
||||
cookies_save_btn = gr.Button("Save")
|
||||
|
||||
def save(cookies: str):
|
||||
cls.store_setting(type="cookies", data={"cookies": cookies})
|
||||
gr.Info("Cookies saved successfully")
|
||||
|
||||
cookies_save_btn.click(save, inputs=[cookies_input])
|
||||
115
src/engines/UploadEngine/YouTubeUploadEngine.py
Normal file
115
src/engines/UploadEngine/YouTubeUploadEngine.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import gradio as gr
|
||||
import orjson
|
||||
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
|
||||
from . import BaseUploadEngine
|
||||
from ...utils import youtube_uploading
|
||||
|
||||
class YouTubeUploadEngine(BaseUploadEngine):
|
||||
name = "YouTube"
|
||||
description = "Upload videos to YouTube"
|
||||
|
||||
num_options = 2
|
||||
|
||||
def __init__(self, options: list):
|
||||
self.oauth_name = options[0]
|
||||
self.oauth = self.retrieve_setting(type="oauth_credentials")[self.oauth_name]
|
||||
self.credentials = self.retrieve_setting(type="youtube_client_secrets")[self.oauth["client_secret"]]
|
||||
|
||||
self.hashtags = options[1]
|
||||
|
||||
@classmethod
|
||||
def __oauth(cls, credentials):
|
||||
flow = InstalledAppFlow.from_client_config(
|
||||
credentials, scopes=["https://www.googleapis.com/auth/youtube.upload"]
|
||||
)
|
||||
user_credentials = flow.run_local_server(
|
||||
success_message="Heyy, yippie, you're authenticated ! You can close this window now !",
|
||||
authorization_prompt_message="Please authorize this app to upload videos on your YouTube account !",
|
||||
)
|
||||
|
||||
result = user_credentials.to_json()
|
||||
if isinstance(result, str):
|
||||
result = orjson.loads(result)
|
||||
return result
|
||||
|
||||
def upload(self):
|
||||
options = {
|
||||
"file": self.ctx.get_file_path("final.mp4"),
|
||||
"title": self.ctx.title + " | " + self.hashtags,
|
||||
"description": self.ctx.description,
|
||||
"privacyStatus": "private",
|
||||
"category": 28,
|
||||
}
|
||||
try:
|
||||
youtube_uploading.upload(self.oauth["credentials"], options)
|
||||
except Exception as e:
|
||||
#this means we need to re-authenticate likely
|
||||
# use self.__oauth to re-authenticate
|
||||
new_oauth = self.__oauth(self.credentials)
|
||||
#also update the credentials in the settings
|
||||
current_oauths = self.retrieve_setting(type="oauth_credentials") or {}
|
||||
current_oauths[self.oauth_name] = {
|
||||
"client_secret": self.oauth["client_secret"],
|
||||
"credentials": new_oauth
|
||||
}
|
||||
self.store_setting(
|
||||
type="oauth_credentials",
|
||||
data=current_oauths,
|
||||
)
|
||||
self.oauth = current_oauths[self.oauth_name]
|
||||
youtube_uploading.upload(self.oauth["credentials"], options)
|
||||
|
||||
@classmethod
|
||||
def get_options(cls):
|
||||
choices = cls.retrieve_setting(type="oauth_credentials") or {}
|
||||
choices = list(choices.keys())
|
||||
return [
|
||||
gr.Dropdown(
|
||||
choices=choices, label="Choose Channel", value=choices[0] if choices else "No channels available !"
|
||||
),
|
||||
gr.Textbox(label="Hashtags", value="#shorts", max_lines=1),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get_settings(cls):
|
||||
with gr.Row():
|
||||
with gr.Column() as ytb_secret:
|
||||
clien_secret_name = gr.Textbox(label="Name", max_lines=1)
|
||||
client_secret_file = gr.File(
|
||||
label="Client Secret File", file_types=["json"], type="binary"
|
||||
)
|
||||
submit_button = gr.Button("Save")
|
||||
def save(binary, clien_secret_name):
|
||||
current_client_secrets = cls.retrieve_setting(type="youtube_client_secrets") or {}
|
||||
client_secret_json = orjson.loads(binary)
|
||||
current_client_secrets[clien_secret_name] = client_secret_json
|
||||
cls.store_setting(
|
||||
type="youtube_client_secrets",
|
||||
data=current_client_secrets,
|
||||
)
|
||||
gr.Info(f"{clien_secret_name} saved successfully !")
|
||||
|
||||
submit_button.click(save, inputs=[client_secret_file, clien_secret_name])
|
||||
|
||||
with gr.Column() as ytb_oauth:
|
||||
possible_client_secrets = cls.retrieve_setting(type="youtube_client_secrets") or {}
|
||||
possible_client_secrets = list(possible_client_secrets.keys())
|
||||
choosen_client_secret = gr.Dropdown(label="Login secret", choices=possible_client_secrets)
|
||||
name = gr.Textbox(label="Name", max_lines=1)
|
||||
login_button = gr.Button("Login", variant="primary")
|
||||
def login(choosen_client_secret, name):
|
||||
choosen_secret_data = cls.retrieve_setting(type="youtube_client_secrets")[choosen_client_secret]
|
||||
new_oauth_entry = cls.__oauth(choosen_secret_data)
|
||||
current_oauths = cls.retrieve_setting(type="oauth_credentials") or {}
|
||||
current_oauths[name] = {
|
||||
"client_secret": choosen_client_secret,
|
||||
"credentials": new_oauth_entry
|
||||
}
|
||||
cls.store_setting(
|
||||
type="oauth_credentials",
|
||||
data=current_oauths,
|
||||
)
|
||||
gr.Info(f"{name} saved successfully !")
|
||||
login_button.click(login, inputs=[choosen_client_secret, name])
|
||||
3
src/engines/UploadEngine/__init__.py
Normal file
3
src/engines/UploadEngine/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .BaseUploadEngine import BaseUploadEngine
|
||||
from .TikTokUploadEngine import TikTokUploadEngine
|
||||
from .YouTubeUploadEngine import YouTubeUploadEngine
|
||||
@@ -9,6 +9,7 @@ from . import AssetsEngine
|
||||
from . import SettingsEngine
|
||||
from . import BackgroundEngine
|
||||
from . import MetadataEngine
|
||||
from . import UploadEngine
|
||||
|
||||
|
||||
class EngineDict(TypedDict):
|
||||
@@ -38,7 +39,7 @@ ENGINES: dict[str, EngineDict] = {
|
||||
"multiple": False,
|
||||
},
|
||||
"TTSEngine": {
|
||||
"classes": [TTSEngine.CoquiTTSEngine, TTSEngine.ElevenLabsTTSEngine],
|
||||
"classes": [TTSEngine.CoquiTTSEngine],
|
||||
"multiple": False,
|
||||
},
|
||||
"CaptioningEngine": {
|
||||
@@ -46,7 +47,11 @@ ENGINES: dict[str, EngineDict] = {
|
||||
"multiple": False,
|
||||
},
|
||||
"AssetsEngine": {
|
||||
"classes": [AssetsEngine.DallEAssetsEngine, NoneEngine],
|
||||
"classes": [
|
||||
AssetsEngine.DallEAssetsEngine,
|
||||
AssetsEngine.GoogleAssetsEngine,
|
||||
NoneEngine,
|
||||
],
|
||||
"multiple": True,
|
||||
},
|
||||
"BackgroundEngine": {
|
||||
@@ -57,4 +62,8 @@ ENGINES: dict[str, EngineDict] = {
|
||||
"classes": [MetadataEngine.ShortsMetadataEngine],
|
||||
"multiple": False,
|
||||
},
|
||||
"UploadEngine": {
|
||||
"classes": [UploadEngine.TikTokUploadEngine, UploadEngine.YouTubeUploadEngine, NoneEngine],
|
||||
"multiple": True,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user