-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
373 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,3 +127,5 @@ dmypy.json | |
|
||
# Pyre type checker | ||
.pyre/ | ||
|
||
thumbnails |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,16 @@ | ||
# reddit-publisher | ||
# reddit-publisher | ||
|
||
## Requirements | ||
- ffmpeg | ||
- tkinter | ||
|
||
``` | ||
apt install python3-tk ffmpeg | ||
``` | ||
|
||
## Setup | ||
``` | ||
python3 -m venv .venv | ||
source .venv/bin/activate | ||
pip install praw | ||
``` |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import string, random | ||
import mimetypes | ||
mimetypes.init() | ||
|
||
|
||
def get_extensions_for_type(general_type): | ||
for ext in mimetypes.types_map: | ||
if mimetypes.types_map[ext].split('/')[0] == general_type: | ||
yield ext | ||
|
||
|
||
VIDEO_EXTENSIONS = tuple(get_extensions_for_type('video')) | ||
AUDIO_EXTENSIONS = tuple(get_extensions_for_type('audio')) | ||
IMAGE_EXTENSIONS = tuple(get_extensions_for_type('image')) | ||
|
||
|
||
def read_subreddits(file_name='subreddits.txt'): | ||
file = open(file_name, 'r') | ||
return file.read().splitlines() | ||
|
||
|
||
def read_files(dir='input'): | ||
from os import listdir | ||
from os.path import isfile, join | ||
files = [join(dir, f) for f in listdir(dir) if isfile(join(dir, f))] | ||
return files | ||
|
||
|
||
def random_text_generator(size=10, chars=string.ascii_letters + string.digits): | ||
return ''.join(random.choice(chars) for _ in range(size)) | ||
|
||
|
||
def get_thumbnail(file_path): | ||
import subprocess | ||
##get thumbnail for the video | ||
##once in a while delete the contents of the thumbnail folders, BUT REMEMBER NEVER DELETE THE FOLDER "thumbnails" | ||
thumbnailPath = "thumbnails/thumbnail_" + random_text_generator() + ".jpg" | ||
subprocess.call(['ffmpeg', '-i', file_path, '-ss', '00:00:02.000', '-vframes', '1', thumbnailPath], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | ||
##if you want to see the output of the ffmpeg in the terminal(delete the one above and uncomment this): | ||
##subprocess.call(['ffmpeg', '-i', video, '-ss', '00:00:02.000', '-vframes', '1', thumbnailPath]) | ||
return thumbnailPath |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import os | ||
from pathlib import Path | ||
import tkinter as tk | ||
from tkinter import ttk | ||
from tkinter import filedialog as fd | ||
from tkinter.messagebox import showinfo | ||
from turtle import title | ||
import posting | ||
|
||
|
||
class Window: | ||
def __init__(self, root): | ||
# root.configure(bg='black') | ||
self.root = root | ||
self.home_dir = str(Path.home()) | ||
self.reddit = posting.authenticate() | ||
|
||
# self.init_subreddits_list() | ||
self.init_files_list() | ||
self.init_title_entry() | ||
|
||
def init_subreddits_list(self): | ||
subreddits_frame = tk.Frame(self.root, bd='5') | ||
subreddits_frame.pack() | ||
subreddits_list = tk.Listbox(subreddits_frame, selectmode='extended', width=54) | ||
subreddits_list.pack() | ||
self.subreddits_list = subreddits_list | ||
|
||
def init_files_list(self): | ||
root = self.root | ||
files_frame = tk.Frame(root, bd='5') | ||
files_frame.pack() | ||
left_frame = tk.Frame(files_frame, bd='5') | ||
left_frame.pack(side=tk.LEFT) | ||
right_frame = tk.Frame(files_frame, bd='5') | ||
right_frame.pack(side=tk.RIGHT) | ||
label = tk.Label(left_frame, text = 'List of selected Files', justify='left') | ||
label.pack() | ||
files_list = tk.Listbox(left_frame, selectmode='extended', width=54) | ||
files_list.pack() | ||
self.files_list = files_list | ||
|
||
select_button = ttk.Button( | ||
right_frame, | ||
text='Select Files', | ||
command=self.select_files | ||
) | ||
select_button.pack(expand=True) | ||
|
||
remove_button = ttk.Button( | ||
right_frame, | ||
text='Remove Selected', | ||
command=self.remove_selected | ||
) | ||
remove_button.pack(expand=True) | ||
|
||
|
||
def init_title_entry(self): | ||
root = self.root | ||
frame = tk.Frame(root, bd='5') | ||
frame.pack(expand=True, fill=tk.BOTH, side=tk.LEFT) | ||
left_frame = tk.Frame(frame, bd='5') | ||
left_frame.pack(side=tk.LEFT) | ||
label = tk.Label(frame, text = 'Title', justify='left') | ||
label.pack(side=tk.LEFT, fill=tk.BOTH) | ||
title_entry = tk.Entry(frame, width = 20) | ||
title_entry.insert(0,'title') | ||
title_entry.pack(side=tk.LEFT) | ||
self.title_entry = title_entry | ||
|
||
frame = tk.Frame(root, bd='5') | ||
frame.pack(expand=True, fill=tk.BOTH, side=tk.LEFT) | ||
left_frame = tk.Frame(frame, bd='5') | ||
left_frame.pack(side=tk.LEFT) | ||
submit_button = ttk.Button( | ||
left_frame, | ||
text='Submit Files', | ||
command=self.submit_files | ||
) | ||
submit_button.pack() | ||
|
||
def submit_files(self): | ||
files = self.files_list.get(0, tk.END) | ||
print('Submitting:', files) | ||
showinfo( | ||
title='Submitting', | ||
message='Click Ok to confirm' | ||
) | ||
post_data = posting.process_files(files, self.title_entry.get(), True) | ||
posting.post(self.reddit, post_data) | ||
showinfo( | ||
title='Done', | ||
message='The files has been submitted' | ||
) | ||
|
||
|
||
def select_files(self): | ||
filetypes = ( | ||
('All files', '*.*'), | ||
('text files', '*.txt'), | ||
) | ||
filenames = fd.askopenfilenames( | ||
title='Select files', | ||
initialdir=os.getcwd(), | ||
filetypes=filetypes | ||
) | ||
for filename in filenames: | ||
try: | ||
index = self.files_list.get(0, tk.END).index(filename) | ||
except: | ||
self.files_list.insert(tk.END, filename) | ||
|
||
|
||
def remove_selected(self): | ||
selection = self.files_list.curselection() | ||
if not selection: | ||
showinfo(message='No selection') | ||
return | ||
for index in reversed(selection): | ||
self.files_list.delete(index) | ||
|
||
|
||
if __name__ == '__main__': | ||
# create the root window | ||
root = tk.Tk() | ||
root.title('Reddit Publisher') | ||
# root.resizable(False, False) | ||
root.geometry('620x420') | ||
window = Window(root) | ||
root.mainloop() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# run: pip3 install praw | ||
# and install ffmpeg from here https://www.ffmpeg.org/ | ||
|
||
import praw, praw.models, time | ||
from prawcore.exceptions import ResponseException | ||
import lib | ||
|
||
|
||
# Read subreddits from file | ||
subreddits = lib.read_subreddits() | ||
print('Subreddits:', subreddits) | ||
|
||
TITLE_POST = 'title' | ||
TITLE_URL_POST = 'title_url' | ||
TITLE_TEXT_POST = 'title_text' | ||
IMAGE_POST = 'image' | ||
GALLERY_POST = 'gallery' | ||
VIDEO_POST = 'video' | ||
POST_TYPES = [TITLE_POST, TITLE_URL_POST, TITLE_TEXT_POST, IMAGE_POST, GALLERY_POST, VIDEO_POST] | ||
|
||
|
||
# TODO: mark as nsfw | ||
# TODO: clear thumbnails folder | ||
def process_files(files, title, thumbnail=True): | ||
post_data = [] | ||
file_types = {'image': [], 'video': []} | ||
|
||
for file in files: | ||
[_, extension] = file.rsplit('.', 1) | ||
extension = f'.{extension}' | ||
if extension in lib.IMAGE_EXTENSIONS: | ||
file_types['image'].append(file) | ||
elif extension in lib.VIDEO_EXTENSIONS: | ||
file_types['video'].append(file) | ||
|
||
if len(file_types['image']) == 1: | ||
post_data.append({ | ||
'type': IMAGE_POST, | ||
'title': title, | ||
'image_path': file_types['image'][0], | ||
}) | ||
elif len(file_types['image']) > 1: | ||
post_data.append({ | ||
'type': GALLERY_POST, | ||
'title': title, | ||
'gallery': [ | ||
{'image_path': file} for file in file_types['image'] | ||
] | ||
}) | ||
|
||
for file in file_types['video']: | ||
data = { | ||
'type': VIDEO_POST, | ||
'title': title, | ||
'video_path': file, | ||
} | ||
if thumbnail: | ||
data['thumbnail'] = lib.get_thumbnail(file) | ||
post_data.append(data) | ||
|
||
return post_data | ||
|
||
|
||
def submit_post(subreddit, post_data): | ||
post_type = post_data['type'] | ||
title = post_data['title'] | ||
|
||
if post_type == "title": | ||
subreddit.submit(title, selftext="") | ||
elif post_type == "titleurl": | ||
subreddit.submit(title, url=post_data['url']) | ||
elif post_type == "titletext": | ||
subreddit.submit(title, selftext=post_data['text']) | ||
elif post_type == "image": | ||
subreddit.submit_image(title, post_data['image_path']) | ||
elif post_type == "video": | ||
if post_data.get('thumbnail'): | ||
subreddit.submit_video(title, post_data['video_path'], thumbnail_path=post_data['thumbnail']) | ||
else: | ||
subreddit.submit_video(title, post_data['video_path']) | ||
elif post_type == "gallery": | ||
subreddit.submit_gallery(title, post_data['gallery']) | ||
|
||
|
||
def authenticate(): | ||
reddit = praw.Reddit() | ||
reddit.validate_on_submit = True | ||
|
||
try: | ||
print("Authenticated as {}".format(reddit.user.me())) | ||
return reddit | ||
except ResponseException as error: | ||
print("Something went wrong during authentication") | ||
print(error) | ||
|
||
|
||
def post(reddit, post_data_list, subreddits=subreddits): | ||
print("Posting...") | ||
for subred in subreddits: | ||
subreddit = reddit.subreddit(subred) | ||
for post_data in post_data_list: | ||
submit_post(subreddit, post_data) | ||
print(f'Posting {post_data} on {subreddit}') | ||
time.sleep(1) | ||
print("Posted!") | ||
|
||
|
||
def input_post_data(thumbnail=True): | ||
title = input('Insert the title: ') | ||
print('available post types: {allowed_post_types}') | ||
post_type = input('Insert the post type: ') or 'title' | ||
|
||
if post_type not in POST_TYPES: | ||
print('ERROR: invalid post type') | ||
exit() | ||
if post_type == TITLE_TEXT_POST: | ||
text = input('Insert text: \n') | ||
return {'title': title, 'text': text} | ||
elif post_type == TITLE_URL_POST: | ||
url = input('Insert url: ') | ||
return {'title': title, 'url': url} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[DEFAULT] | ||
user_agent=publishscript by u/ | ||
client_id= | ||
client_secret= | ||
username= | ||
password= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
api_tests_for_all | ||
api_tests_for_all_two |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import unittest | ||
|
||
from lib import read_files | ||
import posting | ||
|
||
expected_post_data = [ | ||
{ | ||
'type': posting.GALLERY_POST, | ||
'title': 'Test', | ||
'gallery': [ | ||
{"image_path":"input/test.gif"}, | ||
{"image_path":"input/seen.png"}, | ||
{"image_path":"input/test.jpg"}, | ||
] | ||
}, | ||
{ | ||
'type': posting.VIDEO_POST, | ||
'title': 'Test', | ||
'video_path': 'input/test.mp4', | ||
# 'thumbnail': 'thumbnails/frfrfr.png' | ||
}, | ||
] | ||
|
||
test_post_data = [ | ||
{ | ||
'type': posting.TITLE_TEXT_POST, | ||
'title': 'Test title', | ||
'text': 'testing', | ||
}, | ||
{ | ||
'type': posting.TITLE_URL_POST, | ||
'title': 'Test title', | ||
'url': 'https://testing.site/', | ||
}, | ||
{ | ||
'type': posting.IMAGE_POST, | ||
'title': 'Test image', | ||
'image_path': 'input/seen.png', | ||
}, | ||
{ | ||
'type': posting.IMAGE_POST, | ||
'title': 'Test image', | ||
'image_path': 'input/test.gif', | ||
}, | ||
] + expected_post_data | ||
|
||
class TestPosting(unittest.TestCase): | ||
|
||
def test_posting_data_formatter(self): | ||
post_data = posting.process_files(read_files('input'), 'Test', False) | ||
print(post_data) | ||
self.assertEqual(expected_post_data, post_data) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |