Merge branch 'develop' into develop

pull/1409/head
Simon 2 years ago committed by GitHub
commit 4eeacc9754
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -369,6 +369,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-2">
<label for="tiktok_sessionid" class="col-4">TikTok SessionId</label>
<div class="col-8">
<div class="input-group">
<div class="input-group-text">
<i class="bi bi-mic-fill"></i>
</div>
<input value="{{ data.tiktok_sessionid }}" name="tiktok_sessionid" type="text" class="form-control"
data-toggle="tooltip"
data-original-title="TikTok sessionid needed for the TTS API request. Check documentation if you don't know how to obtain it.">
</div>
</div>
</div>
<div class="row mb-2"> <div class="row mb-2">
<label for="python_voice" class="col-4">Python Voice</label> <label for="python_voice" class="col-4">Python Voice</label>
<div class="col-8"> <div class="col-8">

@ -81,6 +81,8 @@ I have tried to simplify the code so anyone can read it and start contributing a
Please read our [contributing guidelines](CONTRIBUTING.md) for more detailed information. Please read our [contributing guidelines](CONTRIBUTING.md) for more detailed information.
### For any questions or support join the [Discord](https://discord.com/channels/897666935708352582/) server
## Developers and maintainers. ## Developers and maintainers.
Elebumm (Lewis#6305) - https://github.com/elebumm (Founder) Elebumm (Lewis#6305) - https://github.com/elebumm (Founder)
@ -96,3 +98,9 @@ Verq (Verq#2338) - https://github.com/CordlessCoder
LukaHietala (Pix.#0001) - https://github.com/LukaHietala LukaHietala (Pix.#0001) - https://github.com/LukaHietala
Freebiell (Freebie#3263) - https://github.com/FreebieII Freebiell (Freebie#3263) - https://github.com/FreebieII
Aman Raza (electro199#8130) - https://github.com/electro199
## LICENSE
[Roboto Fonts](https://fonts.google.com/specimen/Roboto/about) are licensed under [Apache License V2](https://www.apache.org/licenses/LICENSE-2.0)

@ -1,26 +1,28 @@
# documentation for tiktok api: https://github.com/oscie57/tiktok-voice/wiki
import base64 import base64
import random import random
import time
from typing import Optional, Final
import requests import requests
from requests.adapters import HTTPAdapter, Retry
from utils import settings from utils import settings
# from profanity_filter import ProfanityFilter __all__ = ["TikTok", "TikTokTTSException"]
# pf = ProfanityFilter()
# Code by @JasonLovesDoggo
# https://twitter.com/scanlime/status/1512598559769702406
nonhuman = [ # DISNEY VOICES disney_voices: Final[tuple] = (
"en_us_ghostface", # Ghost Face "en_us_ghostface", # Ghost Face
"en_us_chewbacca", # Chewbacca "en_us_chewbacca", # Chewbacca
"en_us_c3po", # C3PO "en_us_c3po", # C3PO
"en_us_stitch", # Stitch "en_us_stitch", # Stitch
"en_us_stormtrooper", # Stormtrooper "en_us_stormtrooper", # Stormtrooper
"en_us_rocket", # Rocket "en_us_rocket", # Rocket
# ENGLISH VOICES "en_female_madam_leota", # Madame Leota
] "en_male_ghosthost", # Ghost Host
human = [ "en_male_pirate", # pirate
)
eng_voices: Final[tuple] = (
"en_au_001", # English AU - Female "en_au_001", # English AU - Female
"en_au_002", # English AU - Male "en_au_002", # English AU - Male
"en_uk_001", # English UK - Male 1 "en_uk_001", # English UK - Male 1
@ -30,23 +32,28 @@ human = [
"en_us_006", # English US - Male 1 "en_us_006", # English US - Male 1
"en_us_007", # English US - Male 2 "en_us_007", # English US - Male 2
"en_us_009", # English US - Male 3 "en_us_009", # English US - Male 3
"en_us_010", "en_us_010", # English US - Male 4
] "en_male_narration", # Narrator
voices = nonhuman + human "en_male_funny", # Funny
"en_female_emotional", # Peaceful
"en_male_cody", # Serious
)
noneng = [ non_eng_voices: Final[tuple] = (
# Western European voices
"fr_001", # French - Male 1 "fr_001", # French - Male 1
"fr_002", # French - Male 2 "fr_002", # French - Male 2
"de_001", # German - Female "de_001", # German - Female
"de_002", # German - Male "de_002", # German - Male
"es_002", # Spanish - Male "es_002", # Spanish - Male
# AMERICA VOICES "it_male_m18" # Italian - Male
# South american voices
"es_mx_002", # Spanish MX - Male "es_mx_002", # Spanish MX - Male
"br_001", # Portuguese BR - Female 1 "br_001", # Portuguese BR - Female 1
"br_003", # Portuguese BR - Female 2 "br_003", # Portuguese BR - Female 2
"br_004", # Portuguese BR - Female 3 "br_004", # Portuguese BR - Female 3
"br_005", # Portuguese BR - Male "br_005", # Portuguese BR - Male
# ASIA VOICES # asian voices
"id_001", # Indonesian - Female "id_001", # Indonesian - Female
"jp_001", # Japanese - Female 1 "jp_001", # Japanese - Female 1
"jp_003", # Japanese - Female 2 "jp_003", # Japanese - Female 2
@ -55,51 +62,106 @@ noneng = [
"kr_002", # Korean - Male 1 "kr_002", # Korean - Male 1
"kr_003", # Korean - Female "kr_003", # Korean - Female
"kr_004", # Korean - Male 2 "kr_004", # Korean - Male 2
] )
# good_voices = {'good': ['en_us_002', 'en_us_006'], vocals: Final[tuple] = (
# 'ok': ['en_au_002', 'en_uk_001']} # less en_us_stormtrooper more less en_us_rocket en_us_ghostface "en_female_f08_salut_damour", # Alto
"en_male_m03_lobby", # Tenor
"en_male_m03_sunshine_soon", # Sunshine Soon
"en_female_f08_warmy_breeze", # Warmy Breeze
"en_female_ht_f08_glorious", # Glorious
"en_male_sing_funny_it_goes_up", # It Goes Up
"en_male_m2_xhxs_m03_silly", # Chipmunk
"en_female_ht_f08_wonderful_world", # Dramatic
)
class TikTok: # TikTok Text-to-Speech Wrapper class TikTok:
"""TikTok Text-to-Speech Wrapper"""
def __init__(self): def __init__(self):
self.URI_BASE = "https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/?text_speaker=" if not settings.config['settings']['tts']['tiktok_sessionid']:
raise TikTokTTSException(5)
headers = {
"User-Agent": "com.zhiliaoapp.musically/2022600030 (Linux; U; Android 7.1.2; es_ES; SM-G988N; "
"Build/NRD90M;tt-ok/3.12.13.1)",
"Cookie": f"sessionid={settings.config['settings']['tts']['tiktok_sessionid']}",
}
self.URI_BASE = "https://api16-normal-c-useast1a.tiktokv.com/media/api/text/speech/invoke/"
self.max_chars = 300 self.max_chars = 300
self.voices = {"human": human, "nonhuman": nonhuman, "noneng": noneng}
self._session = requests.Session()
def run(self, text, filepath, random_voice: bool = False): # set the headers to the session, so we don't have to do it for every request
# if censor: self._session.headers = headers
# req_text = pf.censor(req_text)
# pass def run(self, text: str, filepath: str, random_voice: bool = False):
voice = ( if random_voice:
self.randomvoice() voice = self.random_voice()
if random_voice else:
else ( # if tiktok_voice is not set in the config file, then use a random voice
settings.config["settings"]["tts"]["tiktok_voice"] voice = settings.config["settings"]["tts"].get("tiktok_voice", None)
or random.choice(self.voices["human"])
) # get the audio from the TikTok API
) data = self.get_voices(voice=voice, text=text)
# check if there was an error in the request
status_code = data["status_code"]
if status_code != 0:
raise TikTokTTSException(status_code, data["message"])
# decode data from base64 to binary
try: try:
r = requests.post( raw_voices = data["data"]["v_str"]
f"{self.URI_BASE}{voice}&req_text={text}&speaker_map_type=0" except:
) print("The TikTok TTS returned an invalid response. Please try again later, and report this bug.")
except requests.exceptions.SSLError: raise TikTokTTSException(0, "Invalid response")
# https://stackoverflow.com/a/47475019/18516611 decoded_voices = base64.b64decode(raw_voices)
session = requests.Session()
retry = Retry(connect=3, backoff_factor=0.5)
adapter = HTTPAdapter(max_retries=retry)
session.mount("http://", adapter)
session.mount("https://", adapter)
r = session.post(
f"{self.URI_BASE}{voice}&req_text={text}&speaker_map_type=0"
)
# print(r.text)
vstr = [r.json()["data"]["v_str"]][0]
b64d = base64.b64decode(vstr)
# write voices to specified filepath
with open(filepath, "wb") as out: with open(filepath, "wb") as out:
out.write(b64d) out.write(decoded_voices)
def get_voices(self, text: str, voice: Optional[str] = None) -> dict:
"""If voice is not passed, the API will try to use the most fitting voice"""
# sanitize text
text = text.replace("+", "plus").replace("&", "and").replace("r/", "")
# prepare url request
params = {"req_text": text, "speaker_map_type": 0, "aid": 1233}
if voice is not None:
params["text_speaker"] = voice
# send request
try:
response = self._session.post(self.URI_BASE, params=params)
except ConnectionError:
time.sleep(random.randrange(1, 7))
response = self._session.post(self.URI_BASE, params=params)
return response.json()
@staticmethod
def random_voice() -> str:
return random.choice(eng_voices)
class TikTokTTSException(Exception):
def __init__(self, code: int, message: str):
self._code = code
self._message = message
def __str__(self) -> str:
if self._code == 1:
return f"Code: {self._code}, reason: probably the aid value isn't correct, message: {self._message}"
if self._code == 2:
return f"Code: {self._code}, reason: the text is too long, message: {self._message}"
if self._code == 4:
return f"Code: {self._code}, reason: the speaker doesn't exist, message: {self._message}"
if self._code == 5:
return f"You have to add session id in config to use titok TTS"
def randomvoice(self): return f"Code: {self._message}, reason: unknown, message: {self._message}"
return random.choice(self.voices["human"])

@ -23,7 +23,7 @@ from video_creation.final_video import make_final_video
from video_creation.screenshot_downloader import get_screenshots_of_reddit_posts from video_creation.screenshot_downloader import get_screenshots_of_reddit_posts
from video_creation.voices import save_text_to_mp3 from video_creation.voices import save_text_to_mp3
__VERSION__ = "2.5.0" __VERSION__ = "3.0.1"
print( print(
""" """
@ -109,7 +109,7 @@ if __name__ == "__main__":
shutdown() shutdown()
except Exception as err: except Exception as err:
print_step(f''' print_step(f'''
Sorry, something went wrong with this test version! Try again, and feel free to report this issue at GitHub or the Discord community.\n Sorry, something went wrong with this version! Try again, and feel free to report this issue at GitHub or the Discord community.\n
Version: {__VERSION__} \n Version: {__VERSION__} \n
Story mode: {str(config["settings"]["storymode"])} \n Story mode: {str(config["settings"]["storymode"])} \n
Story mode method: {str(config["settings"]["storymodemethod"])} Story mode method: {str(config["settings"]["storymodemethod"])}

@ -134,6 +134,7 @@ def get_subreddit_threads(POST_ID: str):
content["thread_url"] = threadurl content["thread_url"] = threadurl
content["thread_title"] = submission.title content["thread_title"] = submission.title
content["thread_id"] = submission.id content["thread_id"] = submission.id
content["is_nsfw"] = submission.over_18
content["comments"] = [] content["comments"] = []
if settings.config["settings"]["storymode"]: if settings.config["settings"]["storymode"]:
if settings.config["settings"]["storymodemethod"] == 1: if settings.config["settings"]["storymodemethod"] == 1:

@ -7,11 +7,11 @@ praw==7.6.1
prawcore~=2.3.0 prawcore~=2.3.0
pytube==12.1.0 pytube==12.1.0
requests==2.28.1 requests==2.28.1
rich==12.5.1 rich==13.3.1
toml==0.10.2 toml==0.10.2
translators==5.3.1 translators==5.3.1
pyttsx3==2.90 pyttsx3==2.90
Pillow~=9.3.0 Pillow~=9.4.0
tomlkit==0.11.4 tomlkit==0.11.4
Flask==2.2.2 Flask==2.2.2
clean-text==0.6.0 clean-text==0.6.0

@ -43,11 +43,12 @@ background_thumbnail_font_size = { optional = true, type = "int", default = 96,
background_thumbnail_font_color = { optional = true, default = "255,255,255", example = "255,255,255", explanation = "Font color in RGB format for the thumbnail text" } background_thumbnail_font_color = { optional = true, default = "255,255,255", example = "255,255,255", explanation = "Font color in RGB format for the thumbnail text" }
[settings.tts] [settings.tts]
voice_choice = { optional = false, default = "googletranslate", options = ["streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. This can be left blank and you will be prompted to choose at runtime." } voice_choice = { optional = false, default = "tiktok", options = ["streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. This can be left blank and you will be prompted to choose at runtime." }
aws_polly_voice = { optional = true, default = "Matthew", example = "Matthew", explanation = "The voice used for AWS Polly" } aws_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for AWS Polly" }
streamlabs_polly_voice = { optional = true, default = "Matthew", example = "Matthew", explanation = "The voice used for Streamlabs Polly" } streamlabs_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for Streamlabs Polly" }
tiktok_voice = { optional = true, default = "en_us_006", example = "en_us_006", explanation = "The voice used for TikTok TTS" } tiktok_voice = { optional = true, default = "en_us_001", example = "en_us_006", explanation = "The voice used for TikTok TTS" }
python_voice = { optional = true, default = "1", example = "1", explanation = "The index of the system tts voices (can be downloaded externally, run ptt.py to find value, start from zero)" } tiktok_sessionid = { optional = true, example = "c76bcc3a7625abcc27b508c7db457ff1", explanation = "TikTok sessionid needed for the TTS API request. Check documentation if you don't know how to obtain it." }
py_voice_num = { optional = true, default = "2", example = "2", explanation = "The number of system voices (2 are pre-installed in Windows)" } python_voice = { optional = false, default = "1", example = "1", explanation = "The index of the system tts voices (can be downloaded externally, run ptt.py to find value, start from zero)" }
py_voice_num = { optional = false, default = "2", example = "2", explanation = "The number of system voices (2 are pre-installed in Windows)" }
silence_duration = { optional = true, example = "0.1", explanation = "Time in seconds between TTS comments", default = 0.3, type = "float" } silence_duration = { optional = true, example = "0.1", explanation = "Time in seconds between TTS comments", default = 0.3, type = "float" }
no_emojis = { optional = false, type = "bool", default = false, example = false, options = [true, false,], explanation = "Whether to remove emojis from the comments" } no_emojis = { optional = false, type = "bool", default = false, example = false, options = [true, false,], explanation = "Whether to remove emojis from the comments" }

@ -4,13 +4,13 @@
"https://www.youtube.com/watch?v=vw5L4xCPy9Q", "https://www.youtube.com/watch?v=vw5L4xCPy9Q",
"bike-parkour-gta.mp4", "bike-parkour-gta.mp4",
"Achy Gaming", "Achy Gaming",
480 "center"
], ],
"rocket-league": [ "rocket-league": [
"https://www.youtube.com/watch?v=2X9QGY__0II", "https://www.youtube.com/watch?v=2X9QGY__0II",
"rocket_league.mp4", "rocket_league.mp4",
"Orbital Gameplay", "Orbital Gameplay",
200 "center"
], ],
"minecraft": [ "minecraft": [
"https://www.youtube.com/watch?v=n_Dv4JMiwK8", "https://www.youtube.com/watch?v=n_Dv4JMiwK8",
@ -22,7 +22,7 @@
"https://www.youtube.com/watch?v=qGa9kWREOnE", "https://www.youtube.com/watch?v=qGa9kWREOnE",
"gta-stunt-race.mp4", "gta-stunt-race.mp4",
"Achy Gaming", "Achy Gaming",
480 "center"
], ],
"csgo-surf": [ "csgo-surf": [
"https://www.youtube.com/watch?v=E-8JlyO59Io", "https://www.youtube.com/watch?v=E-8JlyO59Io",
@ -34,7 +34,7 @@
"https://www.youtube.com/watch?v=uVKxtdMgJVU", "https://www.youtube.com/watch?v=uVKxtdMgJVU",
"cluster_truck.mp4", "cluster_truck.mp4",
"No Copyright Gameplay", "No Copyright Gameplay",
480 "center"
], ],
"minecraft-2": [ "minecraft-2": [
"https://www.youtube.com/watch?v=Pt5_GSKIWQM", "https://www.youtube.com/watch?v=Pt5_GSKIWQM",

@ -162,7 +162,7 @@ def delete_background(key):
# Add background video # Add background video
def add_background(youtube_uri, filename, citation, position): def add_background(youtube_uri, filename, citation, position):
# Validate YouTube URI # Validate YouTube URI
regex = re.compile(r"(?:\/|%3D|v=|vi=)([0-9A-z-_]{11})(?:[%#?&]|$)").search( regex = re.compile(r"(?:\/|%3D|v=|vi=)([0-9A-z\-_]{11})(?:[%#?&]|$)").search(
youtube_uri youtube_uri
) )

@ -1,11 +1,12 @@
import re import re
import textwrap import textwrap
import os
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from rich.progress import track from rich.progress import track
from TTS.engine_wrapper import process_text from TTS.engine_wrapper import process_text
def draw_multiple_line_text(image, text, font, text_color, padding, wrap=50): def draw_multiple_line_text(image, text, font, text_color, padding, wrap=50) -> None:
""" """
Draw multiline text over given image Draw multiline text over given image
""" """
@ -23,7 +24,7 @@ def draw_multiple_line_text(image, text, font, text_color, padding, wrap=50):
# theme=bgcolor,reddit_obj=reddit_object,txtclr=txtcolor # theme=bgcolor,reddit_obj=reddit_object,txtclr=txtcolor
def imagemaker(theme, reddit_obj: dict, txtclr, padding=5): def imagemaker(theme, reddit_obj: dict, txtclr, padding=5) -> None:
""" """
Render Images for video Render Images for video
""" """
@ -31,9 +32,9 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5):
texts = reddit_obj["thread_post"] texts = reddit_obj["thread_post"]
id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"])
tfont = ImageFont.truetype("fonts\\Roboto-Bold.ttf", 27) # for title tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 27) # for title
font = ImageFont.truetype( font = ImageFont.truetype(
"fonts\\Roboto-Regular.ttf", 20 os.path.join("fonts", "Roboto-Regular.ttf"), 20
) # for despcription|comments ) # for despcription|comments
size = (500, 176) size = (500, 176)

@ -13,7 +13,7 @@ if sys.version_info[0] >= 3:
from datetime import timezone from datetime import timezone
def check_ratelimit(response: Response): def check_ratelimit(response: Response) -> bool:
""" """
Checks if the response is a ratelimit response. Checks if the response is a ratelimit response.
If it is, it sleeps for the time specified in the response. If it is, it sleeps for the time specified in the response.
@ -30,7 +30,7 @@ def check_ratelimit(response: Response):
return True return True
def sleep_until(time): def sleep_until(time) -> None:
""" """
Pause your program until a specific end time. Pause your program until a specific end time.
'time' is either a valid datetime object or unix timestamp in seconds (i.e. seconds since Unix epoch) 'time' is either a valid datetime object or unix timestamp in seconds (i.e. seconds since Unix epoch)

@ -13,7 +13,7 @@ from utils import settings
from utils.console import print_step, print_substep from utils.console import print_step, print_substep
# Load background videos # Load background videos
with open("utils/backgrounds.json") as json_file: with open("./utils/backgrounds.json") as json_file:
background_options = json.load(json_file) background_options = json.load(json_file)
# Remove "__comment" from backgrounds # Remove "__comment" from backgrounds

@ -4,7 +4,6 @@ from pathlib import Path
from typing import Dict, Final from typing import Dict, Final
import translators as ts import translators as ts
from playwright.async_api import async_playwright # pylint: disable=unused-import
from playwright.sync_api import ViewportSize, sync_playwright from playwright.sync_api import ViewportSize, sync_playwright
from rich.progress import track from rich.progress import track
@ -12,9 +11,11 @@ from utils import settings
from utils.console import print_step, print_substep from utils.console import print_step, print_substep
from utils.imagenarator import imagemaker from utils.imagenarator import imagemaker
from utils.videos import save_data
__all__ = ["download_screenshots_of_reddit_posts"] __all__ = ["download_screenshots_of_reddit_posts"]
def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
"""Downloads screenshots of reddit posts as seen on the web. Downloads to assets/temp/png """Downloads screenshots of reddit posts as seen on the web. Downloads to assets/temp/png
@ -37,7 +38,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
with sync_playwright() as p: with sync_playwright() as p:
print_substep("Launching Headless Browser...") print_substep("Launching Headless Browser...")
browser = p.chromium.launch() # headless=False #to check for chrome view browser = p.chromium.launch() # headless=False for debugging
context = browser.new_context() context = browser.new_context()
# Device scale factor (or dsf for short) allows us to increase the resolution of the screenshots # Device scale factor (or dsf for short) allows us to increase the resolution of the screenshots
# When the dsf is 1, the width of the screenshot is 600 pixels # When the dsf is 1, the width of the screenshot is 600 pixels
@ -71,6 +72,20 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
context.add_cookies(cookies) # load preference cookies context.add_cookies(cookies) # load preference cookies
# Login to Reddit
print_substep("Logging in to Reddit...")
page = context.new_page()
page.goto("https://www.reddit.com/login", timeout=0)
page.set_viewport_size(ViewportSize(width=1920, height=1080))
page.wait_for_load_state()
page.locator('[name="username"]').fill(settings.config["reddit"]["creds"]["username"])
page.locator('[name="password"]').fill(settings.config["reddit"]["creds"]["password"])
page.locator("button:has-text('Log In')").click()
page.wait_for_load_state() # Wait for page to fully load and add 5 seconds
page.wait_for_timeout(5000)
# Get the thread screenshot # Get the thread screenshot
page = context.new_page() page = context.new_page()
page.goto(reddit_object["thread_url"], timeout=0) page.goto(reddit_object["thread_url"], timeout=0)
@ -105,7 +120,23 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
print_substep("Skipping translation...") print_substep("Skipping translation...")
postcontentpath = f"assets/temp/{reddit_id}/png/title.png" postcontentpath = f"assets/temp/{reddit_id}/png/title.png"
page.locator('[data-test-id="post-content"]').screenshot(path=postcontentpath) try:
page.locator('[data-test-id="post-content"]').screenshot(path=postcontentpath)
except Exception as e:
OKGREEN = '\033[92m'
WARNING = '\033[93m'
ENDC = '\033[0m'
print_step(f"{WARNING}Something went wrong!{ENDC}")
resp = input("Something went wrong with making the screenshots! Do you want to skip the post? (y/n) ")
if resp.casefold().startswith("y"):
save_data("", "", "skipped", reddit_id, "")
print(f"{OKGREEN}The post is successfully skipped! You can now restart the program and this post will skipped.{ENDC}")
resp = input("Do you want the error traceback for debugging purposes? (y/n)")
if resp.casefold().startswith("y"):
print(e)
exit()
else:
exit()
if storymode: if storymode:
page.locator('[data-click-id="text"]').first.screenshot( page.locator('[data-click-id="text"]').first.screenshot(
@ -151,6 +182,4 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
# close browser instance when we are done using it # close browser instance when we are done using it
browser.close() browser.close()
print_substep("Screenshots downloaded Successfully.", style="bold green")
print_substep("Screenshots downloaded Successfully.", style="bold green")

Loading…
Cancel
Save