Spaces:
Running
Running
Upload 4 files
Browse files- Dockerfile +25 -6
- app.py +27 -9
- main.py +251 -44
- requirements.txt +6 -1
Dockerfile
CHANGED
@@ -1,12 +1,31 @@
|
|
1 |
-
FROM
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
WORKDIR /app
|
4 |
|
5 |
-
COPY
|
6 |
-
RUN pip install --no-cache-dir -r requirements.txt
|
7 |
|
8 |
-
|
9 |
|
10 |
-
|
|
|
11 |
|
12 |
-
CMD ["gunicorn", "--worker-class", "eventlet", "-w", "1", "-b", "0.0.0.0:7860", "app:app"]
|
|
|
1 |
+
FROM ubuntu
|
2 |
+
|
3 |
+
RUN apt-get update && \
|
4 |
+
apt-get install -y sudo && \
|
5 |
+
apt-get clean
|
6 |
+
RUN apt-get update && apt-get install -y python3 python3-pip python3.12-venv
|
7 |
+
RUN apt-get update && apt-get install -y \
|
8 |
+
curl \
|
9 |
+
ca-certificates \
|
10 |
+
megatools \
|
11 |
+
gnupg && \
|
12 |
+
curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
|
13 |
+
RUN rm -rf /var/lib/apt/lists/*
|
14 |
+
|
15 |
+
# Añadir un usuario llamado 'appuser'
|
16 |
+
RUN useradd -ms /bin/bash appuser
|
17 |
+
RUN usermod -aG sudo appuser
|
18 |
+
RUN echo "appuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
19 |
+
|
20 |
+
USER appuser
|
21 |
|
22 |
WORKDIR /app
|
23 |
|
24 |
+
COPY . /app
|
|
|
25 |
|
26 |
+
RUN sudo chmod -R 777 /app
|
27 |
|
28 |
+
RUN python3 -m venv venv
|
29 |
+
RUN /bin/bash -c "source venv/bin/activate && pip3 install -r requirements.txt"
|
30 |
|
31 |
+
CMD ["venv/bin/gunicorn", "--worker-class", "eventlet", "-w", "1", "-b", "0.0.0.0:7860", "app:app"]
|
app.py
CHANGED
@@ -1,9 +1,29 @@
|
|
1 |
from flask import Flask, render_template
|
2 |
from flask_socketio import SocketIO, send, emit
|
|
|
3 |
|
4 |
app = Flask(__name__)
|
5 |
app.config['SECRET_KEY'] = 'secret!'
|
6 |
socketio = SocketIO(app, cors_allowed_origins="*")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
@socketio.on('connect')
|
9 |
def handle_connect():
|
@@ -16,17 +36,15 @@ def handle_disconnect():
|
|
16 |
|
17 |
@socketio.on('message')
|
18 |
def handle_message(message):
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
emit('response', {'data': 'Custom event received'})
|
26 |
-
|
27 |
@app.route('/')
|
28 |
def index():
|
29 |
-
return
|
30 |
|
31 |
if __name__ == '__main__':
|
32 |
socketio.run(app, host='0.0.0.0', port=7860)
|
|
|
1 |
from flask import Flask, render_template
|
2 |
from flask_socketio import SocketIO, send, emit
|
3 |
+
import json, subprocess
|
4 |
|
5 |
app = Flask(__name__)
|
6 |
app.config['SECRET_KEY'] = 'secret!'
|
7 |
socketio = SocketIO(app, cors_allowed_origins="*")
|
8 |
+
subprocess.Popen(["venv/bin/python","main.py"])
|
9 |
+
|
10 |
+
def list_directory(path):
|
11 |
+
result = []
|
12 |
+
for root, dirs, files in os.walk(path):
|
13 |
+
rel_path = os.path.relpath(root, path)
|
14 |
+
if rel_path == ".":
|
15 |
+
rel_path = ""
|
16 |
+
for file in files:
|
17 |
+
file_path = os.path.join(rel_path, file)
|
18 |
+
file_full_path = os.path.join(root, file)
|
19 |
+
file_size = os.path.getsize(file_full_path)
|
20 |
+
result.append({"type": "file", "path": file_path, "size": file_size})
|
21 |
+
for dir in dirs:
|
22 |
+
dir_path = os.path.join(rel_path, dir)
|
23 |
+
dir_full_path = os.path.join(root, dir)
|
24 |
+
dir_content = list_directory(dir_full_path)
|
25 |
+
result.append({"type": "directory", "path": dir_path, "files": dir_content})
|
26 |
+
return result
|
27 |
|
28 |
@socketio.on('connect')
|
29 |
def handle_connect():
|
|
|
36 |
|
37 |
@socketio.on('message')
|
38 |
def handle_message(message):
|
39 |
+
if message == "files":
|
40 |
+
dir = './files'
|
41 |
+
if not os.path.exists(dir):
|
42 |
+
os.mkdir(dir)
|
43 |
+
files_list = list_directory(directory)
|
44 |
+
emit("files",files_list)
|
|
|
|
|
45 |
@app.route('/')
|
46 |
def index():
|
47 |
+
return json.dumps({"connect":True})
|
48 |
|
49 |
if __name__ == '__main__':
|
50 |
socketio.run(app, host='0.0.0.0', port=7860)
|
main.py
CHANGED
@@ -1,48 +1,255 @@
|
|
1 |
-
from
|
2 |
-
import os, json,
|
|
|
|
|
|
|
3 |
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
users = []
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
global
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
else:
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from telethon import events, utils, Button, TelegramClient
|
2 |
+
import asyncio, os, time, re, sys, threading, random, subprocess, json, base64, requests, shutil, zipfile
|
3 |
+
from bs4 import BeautifulSoup
|
4 |
+
from FastTelethon import download_file, upload_file
|
5 |
+
import subprocess
|
6 |
|
7 |
+
api_id = 9024532
|
8 |
+
api_hash = "131b576240be107210aace99a5f5c5b0"
|
9 |
+
token = "7829277186:AAGZKtL06JxT5yp0FVNMjFy9yBKJiRpM-Y0"
|
10 |
+
|
11 |
+
client = TelegramClient("AutoD", api_id, api_hash)
|
12 |
+
|
13 |
+
class Timer:
|
14 |
+
def __init__(self, time_between=2):
|
15 |
+
self.start_time = time.time()
|
16 |
+
self.time_between = time_between
|
17 |
+
|
18 |
+
def can_send(self):
|
19 |
+
if time.time() > (self.start_time + self.time_between):
|
20 |
+
self.start_time = time.time()
|
21 |
+
return True
|
22 |
+
return False
|
23 |
+
|
24 |
+
def execute_command(command):
|
25 |
+
try:
|
26 |
+
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
27 |
+
if result.stdout:
|
28 |
+
return str(result.stdout)
|
29 |
+
if result.stderr:
|
30 |
+
return str(result.stderr)
|
31 |
+
except Exception as e:
|
32 |
+
return str(f"Error: {e}")
|
33 |
+
|
34 |
+
def folder_size(folder_path):
|
35 |
+
total_size = 0
|
36 |
+
for dirpath, dirnames, filenames in os.walk(folder_path):
|
37 |
+
for f in filenames:
|
38 |
+
fp = os.path.join(dirpath, f)
|
39 |
+
total_size += os.path.getsize(fp)
|
40 |
+
return total_size
|
41 |
+
|
42 |
+
def split_ext(file=None, dir="./",size=3):
|
43 |
+
size = size * 1024 * 1024
|
44 |
+
files = []
|
45 |
+
tamano_archivo = os.path.getsize(file)
|
46 |
+
if tamano_archivo < size:
|
47 |
+
files.append(file)
|
48 |
+
else:
|
49 |
+
with open(file, 'rb') as archivo_original:
|
50 |
+
parte = 1
|
51 |
+
totalparte = (tamano_archivo//size)+1
|
52 |
+
while True:
|
53 |
+
contenido_parte = archivo_original.read(size)
|
54 |
+
if not contenido_parte:
|
55 |
+
break
|
56 |
+
nombre_parte = f"{file.split('/')[-1].split('.')[0]}.7z.{str(parte).zfill(3)}"
|
57 |
+
with open(dir+"/"+nombre_parte, 'wb') as archivo_parte:
|
58 |
+
archivo_parte.write(contenido_parte)
|
59 |
+
files.append(nombre_parte)
|
60 |
+
parte += 1
|
61 |
+
os.unlink(file)
|
62 |
+
return files
|
63 |
+
|
64 |
+
def sizeof_fmt(num, suffix='B'):
|
65 |
+
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
|
66 |
+
if abs(num) < 1024.0:
|
67 |
+
return "%3.2f%s%s" % (num, unit, suffix)
|
68 |
+
num /= 1024.0
|
69 |
+
return "%.2f%s%s" % (num, 'Yi', suffix)
|
70 |
+
|
71 |
+
if not os.path.exists("./files"):
|
72 |
+
os.mkdir("./files")
|
73 |
+
|
74 |
+
client.start(bot_token=token)
|
75 |
|
76 |
users = []
|
77 |
+
process = []
|
78 |
+
basedata = {}
|
79 |
+
cdpaths = []
|
80 |
+
|
81 |
+
@client.on(events.NewMessage())
|
82 |
+
async def mybot(event):
|
83 |
+
global basedata
|
84 |
+
global process
|
85 |
+
global cdpaths
|
86 |
+
if len(cdpaths) > 0:
|
87 |
+
cd = "/"+"/".join(cdpaths)
|
88 |
+
else:
|
89 |
+
cd = "/"
|
90 |
+
text = event.raw_text
|
91 |
+
user_id = event.message.chat.id
|
92 |
+
msg_id = event.message.id
|
93 |
+
user_name = event.message.chat.username
|
94 |
+
mode = "auto"
|
95 |
+
try:
|
96 |
+
mode = basedata[f"{user_id}_mode"]
|
97 |
+
except:
|
98 |
+
None
|
99 |
+
if len(users) == 0:
|
100 |
+
users.append(user_id)
|
101 |
+
if not user_id in users:
|
102 |
+
await event.reply("<b>¡Acceso no autorizado!</b>", parse_mode="HTML")
|
103 |
+
raise ValueError(f"({user_id}) No es un usuario autorizado")
|
104 |
+
if not os.path.exists(f"./files"):
|
105 |
+
os.mkdir(f"./files")
|
106 |
+
if not os.path.exists(f"./files_temp"):
|
107 |
+
os.mkdir(f"./files_temp")
|
108 |
+
directorio = f'./files'+cd
|
109 |
+
files = [(archivo, os.path.getmtime(os.path.join(directorio, archivo))) for archivo in os.listdir(directorio)]
|
110 |
+
file = sorted(files, key=lambda x: x, reverse=True)
|
111 |
+
files = []
|
112 |
+
for f in file:
|
113 |
+
x,y = f
|
114 |
+
files.append(x)
|
115 |
+
if "/start" == text:
|
116 |
+
basedata[f"{user_id}_username"] = user_name
|
117 |
+
await event.reply(f"<code>AUTOD • TechDev</code>", parse_mode="HTML", buttons=[[Button.inline('?', b'')]])
|
118 |
+
elif "/add " in text:
|
119 |
+
user = int(text.replace("/add", ""))
|
120 |
+
users.append(user)
|
121 |
+
await event.reply("Usuario añadido")
|
122 |
+
elif "/ban " in text:
|
123 |
+
user = int(text.replace("/ban", ""))
|
124 |
+
users.append(user)
|
125 |
+
await event.reply("Usuario borrado")
|
126 |
+
elif "/ls" in text:
|
127 |
+
msg = f"#LISTDIR #GOOD\n<code>{'/'.join(cdpaths)}</code>\n<b>LÍMITE - {sizeof_fmt(folder_size('./files'))}/100.0GiB</b>\n\n"
|
128 |
+
for f in files:
|
129 |
+
if os.path.isfile("./files"+cd+"/"+f):
|
130 |
+
msg += f" 📃 <code>{f}</code>\n"
|
131 |
+
else:
|
132 |
+
msg += f" 📁 <code>{f}</code>\n"
|
133 |
+
if len(files) == 0:
|
134 |
+
msg += "<i>No hay archivos</i>"
|
135 |
+
await event.reply(msg, parse_mode="HTML")
|
136 |
+
elif "/rm " in text:
|
137 |
+
path = text.replace("/rm ", "")
|
138 |
+
try:
|
139 |
+
if os.path.isfile("./files"+cd+"/"+path):
|
140 |
+
os.unlink("./files"+cd+"/"+path)
|
141 |
+
else:
|
142 |
+
shutil.rmtree("./files"+cd+"/"+path)
|
143 |
+
msg = "#REMOVE #GOOD\n\n<b>✓ ¡Directorio Eliminado!</b>"
|
144 |
+
except:
|
145 |
+
msg = "#REMOVE #ERROR\n\n<b>No existe el directorio</b>"
|
146 |
+
await event.reply(msg, parse_mode="HTML")
|
147 |
+
elif "/cd " in text:
|
148 |
+
path = text.replace("/cd ", "")
|
149 |
+
if not os.path.isdir("./files/"+cd+"/"+path):
|
150 |
+
cdpaths = []
|
151 |
+
msg = "#CHANGEDIR #ERROR\n\n<b>No existe el directorio</b>"
|
152 |
+
else:
|
153 |
+
cdpaths = path.split("/")
|
154 |
+
msg = "#CHANGEDIR #GOOD\n\n<b>✓ ¡Directorio abierto!</b>"
|
155 |
+
directorio = f'./files/'+"/".join(cdpaths)
|
156 |
+
files = [(archivo, os.path.getmtime(os.path.join(directorio, archivo))) for archivo in os.listdir(directorio)]
|
157 |
+
file = sorted(files, key=lambda x: x, reverse=True)
|
158 |
+
files = []
|
159 |
+
for f in file:
|
160 |
+
x,y = f
|
161 |
+
files.append(x)
|
162 |
+
msg = f"\n\n<code>{'/'.join(cdpaths)}</code>\n<b>LÍMITE - {sizeof_fmt(folder_size('./files'))}/100.0GiB</b>\n\n"
|
163 |
+
for f in files:
|
164 |
+
if os.path.isfile("./files"+cd+"/"+f):
|
165 |
+
msg += f" 📃 <code>{f}</code>\n"
|
166 |
+
else:
|
167 |
+
msg += f" 📁 <code>{f}</code>\n"
|
168 |
+
if len(files) == 0:
|
169 |
+
msg += "<i>No hay archivos</i>"
|
170 |
+
await event.reply(msg, parse_mode="HTML")
|
171 |
+
elif "/mkdir " in text:
|
172 |
+
dir = text.replace("/mkdir ", "")
|
173 |
+
os.mkdir("./files"+cd+"/"+dir)
|
174 |
+
msg = "#MAKEDIR #GOOD\n\n<b>✓ ¡DIRECTORIO CREADO!</b>"
|
175 |
+
cdpaths.append(dir)
|
176 |
+
directorio = f'./files/'+"/".join(cdpaths)
|
177 |
+
files = [(archivo, os.path.getmtime(os.path.join(directorio, archivo))) for archivo in os.listdir(directorio)]
|
178 |
+
file = sorted(files, key=lambda x: x, reverse=True)
|
179 |
+
files = []
|
180 |
+
for f in file:
|
181 |
+
x,y = f
|
182 |
+
files.append(x)
|
183 |
+
msg = f"\n\n<code>{'/'.join(cdpaths)}</code>\n<b>LÍMITE - {sizeof_fmt(folder_size('./files'))}/100.0GiB</b>\n\n"
|
184 |
+
for f in files:
|
185 |
+
if os.path.isfile("./files"+cd+"/"+f):
|
186 |
+
msg += f" 📃 <code>{f}</code>\n"
|
187 |
+
else:
|
188 |
+
msg += f" 📁 <code>{f}</code>\n"
|
189 |
+
if len(files) == 0:
|
190 |
+
msg += "<i>No hay archivos</i>"
|
191 |
+
await event.reply(msg, parse_mode="HTML")
|
192 |
+
elif event.document and user_id in users:
|
193 |
+
code = str(random.randint(100000,999999))
|
194 |
+
process.append(code)
|
195 |
+
while not code == process[0]:
|
196 |
+
await asyncio.sleep(3)
|
197 |
+
msging = "<b>PREPARANDO</b>"
|
198 |
+
msg = await event.reply(msging, parse_mode="HTML",buttons=[Button.inline("CANCELAR",b'del|'+code.encode('utf-8'))])
|
199 |
+
await msg.edit("<b>DESCARGANDO</b>", parse_mode="HTML",buttons=[Button.inline("CANCELAR",b'del|'+code.encode('utf-8'))])
|
200 |
+
basedata[code] = "down:0/0"+"|CARGANDO..."
|
201 |
+
basedata[code+"auto-act"] = True
|
202 |
+
caption = event.message.message
|
203 |
+
mime_type = str(event.media.document.mime_type)
|
204 |
+
extension = mime_type.split("/")[1]
|
205 |
+
if event.file.name:
|
206 |
+
name = event.file.name
|
207 |
else:
|
208 |
+
if caption:
|
209 |
+
name = str(caption).split("\n")[0]+"."+extension
|
210 |
+
else:
|
211 |
+
name = "document_"+str(time.strftime("%d_%H_%M_%S"))+"."+extension
|
212 |
+
if os.path.exists("./files/"+name):
|
213 |
+
name = name.replace(".", f"_{str(time.strftime('%d%H%M%S'))}.")
|
214 |
+
timer = Timer()
|
215 |
+
async def progress_bar(current, total):
|
216 |
+
if not code in process:
|
217 |
+
raise ValueError(f"Se detuvo el proceso {code}")
|
218 |
+
basedata[code] = "down:"+str(current)+"/"+str(total)
|
219 |
+
if basedata[code+"auto-act"]:
|
220 |
+
text1 = "<b>DESCARGANDO</b>"
|
221 |
+
bar = f"<i>{round((current/total)*100,1)}%</i> <b>[</b>"
|
222 |
+
prog = round(int(15*(current/total)),0)
|
223 |
+
deprog = 15-prog
|
224 |
+
bar += ("-"*prog)+"|"
|
225 |
+
bar += ("-"*deprog)+"<b>]</b>"
|
226 |
+
if len(process) > 1:
|
227 |
+
infopro = f"\n+{len(process)-1} procesos..."
|
228 |
+
else:
|
229 |
+
infopro = ""
|
230 |
+
if timer.can_send():
|
231 |
+
await msg.edit(f"{text1}\n\n<b>Nombre:</b> <code>{name}</code>\n<b>Progreso:</b> {bar}\n<b>Tamaño:</b> <code>{sizeof_fmt(total)}</code>\n\n{infopro}", parse_mode="HTML", buttons=[Button.inline("CANCELAR", b'del|'+code.encode("utf8"))])
|
232 |
+
with open("./files_temp/"+name, "wb") as out:
|
233 |
+
await download_file(event.client, event.document, out, progress_callback=progress_bar)
|
234 |
+
os.rename("./files_temp/"+name, "./files"+cd+"/"+name)
|
235 |
+
upmsg = await event.reply(f"#DOWNLOAD #GOOD\n\n<b>✓ ¡Proceso completado!</b>", parse_mode="HTML")
|
236 |
+
await client.delete_messages(user_id, msg.id)
|
237 |
+
basedata[code] = None
|
238 |
+
process.remove(code)
|
239 |
+
@client.on(events.CallbackQuery)
|
240 |
+
async def callback_query(event):
|
241 |
+
global basedata
|
242 |
+
global process
|
243 |
+
user_id = event.query.user_id
|
244 |
+
msg_id = event.query.msg_id
|
245 |
+
data = event.query.data.decode("utf-8")
|
246 |
+
orden = str(data).split("|")[0]
|
247 |
+
if orden == "del":
|
248 |
+
code = str(data).split("|")[1]
|
249 |
+
try:
|
250 |
+
process.remove(code)
|
251 |
+
except:
|
252 |
+
None
|
253 |
+
await client.delete_messages(user_id, msg_id)
|
254 |
+
print("CONECTADO")
|
255 |
+
client.run_until_disconnected()
|
requirements.txt
CHANGED
@@ -1,3 +1,8 @@
|
|
1 |
flask-socketio>=5.3.4
|
2 |
eventlet>=0.33.3
|
3 |
-
gunicorn>=20.1.0
|
|
|
|
|
|
|
|
|
|
|
|
1 |
flask-socketio>=5.3.4
|
2 |
eventlet>=0.33.3
|
3 |
+
gunicorn>=20.1.0
|
4 |
+
requests
|
5 |
+
bs4
|
6 |
+
flask
|
7 |
+
psutil
|
8 |
+
telethon
|