320 lines
14 KiB
Python
320 lines
14 KiB
Python
import os
|
|
import random
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from threading import Thread
|
|
import time
|
|
import traceback
|
|
|
|
from modules.logging import logWrite
|
|
from modules.utils import configGet, jsonLoad, jsonSave
|
|
|
|
# Args =====================================================================================================================================
|
|
if "--move-sent" in sys.argv:
|
|
for entry in jsonLoad(configGet("index", "locations"))["sent"]:
|
|
try:
|
|
shutil.move(configGet("queue", "locations")+os.sep+entry, configGet("sent", "locations")+os.sep+entry)
|
|
except FileNotFoundError:
|
|
logWrite(f"File '{entry}' is already moved or does not exist")
|
|
except Exception as exp:
|
|
logWrite(f"Could not move sent file '{entry}' to '{configGet('sent', 'locations')}' due to {exp}")
|
|
logWrite(f"Moved all sent files to the sent folder")
|
|
|
|
if "--cleanup" in sys.argv:
|
|
if "--confirm" in sys.argv:
|
|
index = jsonLoad(configGet("index", "locations"))
|
|
for entry in index["sent"]:
|
|
try:
|
|
try:
|
|
os.remove(configGet("queue", "locations")+os.sep+entry)
|
|
except FileNotFoundError:
|
|
pass
|
|
try:
|
|
os.remove(configGet("sent", "locations")+os.sep+entry)
|
|
except FileNotFoundError:
|
|
pass
|
|
except Exception as exp:
|
|
logWrite(f"Could not remove '{entry}' due to {exp}")
|
|
jsonSave(index, jsonLoad(configGet("index", "locations")))
|
|
logWrite(f"Performed cleanup of the sent files")
|
|
else:
|
|
logWrite(f"Requested cleanup of sent files but not authorized. Please pass '--confirm' to perform that")
|
|
|
|
if "--cleanup-index" in sys.argv:
|
|
if "--confirm" in sys.argv:
|
|
index = jsonLoad(configGet("index", "locations"))
|
|
index["sent"] = []
|
|
jsonSave(index, jsonLoad(configGet("index", "locations")))
|
|
logWrite(f"Performed cleanup of sent files index")
|
|
else:
|
|
logWrite(f"Requested cleanup of sent files index but not authorized. Please pass '--confirm' to perform that")
|
|
|
|
if "--norun" in sys.argv:
|
|
logWrite("Argument --norun passed, not running the main script")
|
|
sys.exit()
|
|
#===========================================================================================================================================
|
|
|
|
|
|
# Import ===================================================================================================================================
|
|
try:
|
|
import schedule # type: ignore
|
|
from pyrogram import Client, filters, idle # type: ignore
|
|
from pyrogram.types import ChatPermissions, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton, BotCommand, BotCommandScopeChat # type: ignore
|
|
except ModuleNotFoundError:
|
|
print(f"Required modules are not installed. Run 'pip3 install -r requirements.txt' and restart the program.", flush=True)
|
|
sys.exit()
|
|
#===========================================================================================================================================
|
|
|
|
|
|
pid = os.getpid()
|
|
app = Client("duptsiaposter", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))
|
|
|
|
|
|
def send_content():
|
|
|
|
try:
|
|
|
|
list_sent = jsonLoad(configGet("index", "locations"))
|
|
list_queue = os.listdir(configGet("queue", "locations"))
|
|
|
|
for file in list_queue:
|
|
|
|
if not file in list_sent["sent"]:
|
|
|
|
ext_match = False
|
|
|
|
for ext in configGet("photo", "posting", "extensions"):
|
|
if file.endswith(ext):
|
|
ext_match = True
|
|
ext_type = "photo"
|
|
break
|
|
|
|
for ext in configGet("video", "posting", "extensions"):
|
|
if file.endswith(ext):
|
|
ext_match = True
|
|
ext_type = "video"
|
|
break
|
|
|
|
if not ext_match:
|
|
list_queue.remove(file)
|
|
|
|
else:
|
|
list_queue.remove(file)
|
|
|
|
if len(list_queue) > 0:
|
|
candidate_file = random.choice(list_queue)
|
|
candidate = configGet("queue", "locations")+os.sep+candidate_file
|
|
else:
|
|
logWrite(f"Could not send content due to queue folder empty with allowed extensions")
|
|
if configGet("error", "reports"):
|
|
app.send_message(configGet("admin", "reports"), f"Could not send content: `Queue folder is empty or contains only unsupported or already sent files.`") # type: ignore
|
|
return
|
|
|
|
if ext_type == "photo": # type: ignore
|
|
|
|
if configGet("enabled", "caption"):
|
|
if configGet("link", "caption") != None:
|
|
sent = app.send_photo(configGet("channel", "posting"), candidate, caption=f"[{configGet('text', 'caption')}]({configGet('link', 'caption')})", disable_notification=configGet("silent", "posting")) # type: ignore
|
|
else:
|
|
sent = app.send_photo(configGet("channel", "posting"), candidate, caption=configGet('text', 'caption'), disable_notification=configGet("silent", "posting")) # type: ignore
|
|
else:
|
|
sent = app.send_photo(configGet("channel", "posting"), candidate, disable_notification=configGet("silent", "posting")) # type: ignore
|
|
|
|
elif ext_type == "video": # type: ignore
|
|
|
|
if configGet("enabled", "caption"):
|
|
if configGet("link", "caption") != None:
|
|
sent = app.send_video(configGet("channel", "posting"), candidate, caption=f"[{configGet('text', 'caption')}]({configGet('link', 'caption')})", disable_notification=configGet("silent", "posting")) # type: ignore
|
|
else:
|
|
sent = app.send_video(configGet("channel", "posting"), candidate, caption=configGet('text', 'caption'), disable_notification=configGet("silent", "posting")) # type: ignore
|
|
else:
|
|
sent = app.send_video(configGet("channel", "posting"), candidate, disable_notification=configGet("silent", "posting")) # type: ignore
|
|
|
|
list_sent["sent"].append(candidate_file)
|
|
jsonSave(list_sent, configGet("index", "locations"))
|
|
|
|
if configGet("move_sent", "posting"):
|
|
shutil.move(candidate, configGet("sent", "locations")+os.sep+candidate_file)
|
|
|
|
if configGet("sent", "reports"):
|
|
app.send_message(configGet("admin", "reports"), f"Posted `{candidate_file}`", disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup([
|
|
[InlineKeyboardButton("View in channel", url=sent.link)] # type: ignore
|
|
])) # type: ignore
|
|
|
|
except Exception as exp:
|
|
logWrite(f"Could not send content due to {exp}")
|
|
if configGet("error", "reports"):
|
|
app.send_message(configGet("admin", "reports"), f"Could not send content due to `{exp}`\n\nTraceback:\n```{traceback.format_exc()}```") # type: ignore
|
|
|
|
|
|
@app.on_message(~ filters.scheduled & filters.command(["start", "help"], prefixes="/"))
|
|
def start(app, msg):
|
|
if msg.from_user.id not in jsonLoad(configGet("blocked", "locations")):
|
|
msg.reply_text(f"Hi and welcome!\n\nYou can submit your pictures and videos here. We'll review and add them, if we like them. Make sure you send your stuff one at a time and have chosen media that corresponds to our rules.\n\nYou can also write something to us in the description field. We'll send it with the submission itself, if needed.\n\nHave fun and happy submitting!")
|
|
|
|
@app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"]))
|
|
def kill(app, msg):
|
|
|
|
if msg.from_user.id == configGet("admin", "reports"):
|
|
msg.reply_text(f"Shutting down bot with pid `{pid}`")
|
|
os.system('kill -9 '+str(pid))
|
|
|
|
|
|
# Submission =====================================================================================================================================
|
|
def subLimit(user):
|
|
submit = jsonLoad(configGet("submit", "locations"))
|
|
submit[str(user.id)] = time.time()
|
|
jsonSave(submit, configGet("submit", "locations"))
|
|
|
|
def subLimited(user):
|
|
if user.id == configGet("admin", "reports"):
|
|
return False
|
|
else:
|
|
submit = jsonLoad(configGet("submit", "locations"))
|
|
if str(user.id) in submit:
|
|
if (time.time() - submit[str(user.id)]) < configGet("timeout", "submission"):
|
|
return True
|
|
else:
|
|
return False
|
|
else:
|
|
return False
|
|
|
|
def subBlock(user):
|
|
blocked = jsonLoad(configGet("blocked", "locations"))
|
|
if user not in blocked:
|
|
blocked.append(user)
|
|
jsonSave(blocked, configGet("blocked", "locations"))
|
|
|
|
def subUnblock(user):
|
|
blocked = jsonLoad(configGet("blocked", "locations"))
|
|
if user in blocked:
|
|
blocked.remove(user)
|
|
jsonSave(blocked, configGet("blocked", "locations"))
|
|
|
|
@app.on_message(~ filters.scheduled & filters.photo | filters.video | filters.animation)
|
|
def get_submission(_, msg):
|
|
if msg.from_user.id not in jsonLoad(configGet("blocked", "locations")):
|
|
if not subLimited(msg.from_user):
|
|
|
|
if msg.caption != None:
|
|
caption = str(msg.caption)
|
|
else:
|
|
caption = ""
|
|
|
|
caption += "\n\nSubmitted by:"
|
|
|
|
if msg.from_user.first_name != None:
|
|
caption += f" {msg.from_user.first_name}"
|
|
if msg.from_user.last_name != None:
|
|
caption += f" {msg.from_user.last_name}"
|
|
if msg.from_user.username != None:
|
|
caption += f" (@{msg.from_user.username})"
|
|
if msg.from_user.phone_number != None:
|
|
caption += f" ({msg.from_user.phone_number})"
|
|
|
|
msg.copy(configGet("admin", "reports"), caption=caption, reply_markup=InlineKeyboardMarkup([
|
|
[
|
|
InlineKeyboardButton(text="✅ Accept", callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}"),
|
|
InlineKeyboardButton(text="❌ Deny", callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
|
|
],
|
|
[
|
|
InlineKeyboardButton(text="☠️ Block sender", callback_data=f"sub_block_{msg.from_user.id}")
|
|
],
|
|
[
|
|
InlineKeyboardButton(text="🏳️ Unblock sender", callback_data=f"sub_unblock_{msg.from_user.id}")
|
|
]
|
|
]
|
|
))
|
|
msg.reply_text(f"Media has been submitted.\nWe'll notify you whether it will be accepted or not soon.", quote=True)
|
|
subLimit(msg.from_user)
|
|
else:
|
|
msg.reply_text(f'You can only submit 1 media per {configGet("timeout", "submission")} seconds')
|
|
|
|
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*_[\s\S]*")) # type: ignore
|
|
def callback_query_yes(app, clb): # type: ignore
|
|
fullclb = clb.data.split("_")
|
|
try:
|
|
submission = app.get_messages(int(fullclb[2]), int(fullclb[3]))
|
|
except:
|
|
clb.answer(text=f"Submission message no longer exist", show_alert=True)
|
|
return
|
|
try:
|
|
app.download_media(submission, file_name=configGet("queue", "locations")+os.sep)
|
|
except:
|
|
clb.answer(text=f"Could not download submission", show_alert=True)
|
|
return
|
|
submission.reply_text(f"✅ Submission approved and accepted", quote=True)
|
|
clb.answer(text=f"✅ Submission approved", show_alert=True)
|
|
|
|
@app.on_callback_query(filters.regex("sub_no_[\s\S]*_[\s\S]*")) # type: ignore
|
|
def callback_query_no(app, clb): # type: ignore
|
|
fullclb = clb.data.split("_")
|
|
try:
|
|
submission = app.get_messages(int(fullclb[2]), int(fullclb[3]))
|
|
except:
|
|
clb.answer(text=f"Submission message no longer exist", show_alert=True)
|
|
return
|
|
submission.reply_text(f"❌ Submission reviewed and declined", quote=True)
|
|
clb.answer(text=f"❌ Submission declined", show_alert=True)
|
|
|
|
@app.on_callback_query(filters.regex("sub_block_[\s\S]*")) # type: ignore
|
|
def callback_query_block(app, clb): # type: ignore
|
|
fullclb = clb.data.split("_")
|
|
app.send_message(int(fullclb[2]), "You were blocked and you can't submit media anymore.")
|
|
subBlock(int(fullclb[2]))
|
|
clb.answer(text=f"User {fullclb[2]} has been blocked", show_alert=True)
|
|
|
|
@app.on_callback_query(filters.regex("sub_unblock_[\s\S]*")) # type: ignore
|
|
def callback_query_unblock(app, clb): # type: ignore
|
|
fullclb = clb.data.split("_")
|
|
app.send_message(int(fullclb[2]), "You were unblocked and you can now submit media.")
|
|
subUnblock(int(fullclb[2]))
|
|
clb.answer(text=f"User {fullclb[2]} has been unblocked", show_alert=True)
|
|
#===========================================================================================================================================
|
|
|
|
|
|
for entry in configGet("time", "posting"):
|
|
schedule.every().day.at(entry).do(send_content)
|
|
|
|
|
|
def background_task():
|
|
try:
|
|
while True:
|
|
try:
|
|
schedule.run_pending()
|
|
time.sleep(1)
|
|
except:
|
|
pass
|
|
except Exception as exp:
|
|
logWrite(f"Exception {exp} happened on task execution")
|
|
except KeyboardInterrupt:
|
|
logWrite('\nShutting down...')
|
|
app.send_message(configGet("admin", "reports"), f"Shutting down with PID `{pid}`") # type: ignore
|
|
os.system('kill -9 '+str(pid))
|
|
|
|
if __name__ == "__main__":
|
|
|
|
logWrite(f'Starting with PID {pid}')
|
|
|
|
app.start() # type: ignore
|
|
app.send_message(configGet("admin", "reports"), f"Starting with pid `{pid}`") # type: ignore
|
|
|
|
t = Thread(target=background_task)
|
|
t.start()
|
|
|
|
app.set_bot_commands([ # type: ignore
|
|
BotCommand("start", "Start using the bot")
|
|
])
|
|
|
|
app.set_bot_commands([ # type: ignore
|
|
BotCommand("reboot", "Reboot the bot"),
|
|
],
|
|
scope=BotCommandScopeChat(chat_id=configGet("admin", "reports")))
|
|
|
|
idle()
|
|
|
|
app.send_message(configGet("admin", "reports"), f"Shutting down with pid `{pid}`") # type: ignore
|
|
logWrite(f'Shutting down with PID {pid}')
|
|
|
|
subprocess.call(f'kill -9 {pid}', shell=True) # type: ignore |