ulduldp commited on
Commit
39e688c
Β·
verified Β·
1 Parent(s): 8279cb7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -50
app.py CHANGED
@@ -1,7 +1,9 @@
1
  import os
2
  import threading
3
  import time
 
4
  import random
 
5
  from datetime import datetime
6
 
7
  from flask_srvr import run_flask
@@ -25,7 +27,9 @@ start_flask()
25
  # =========================
26
  BOT_TOKEN = os.getenv("tgtkn")
27
  GROUP_ID = -1003799294466
 
28
  MAX_STORAGE = 15 * 1024 * 1024 * 1024
 
29
 
30
  # =========================
31
  # 🧠 STATE
@@ -35,32 +39,53 @@ user_state = {}
35
  # =========================
36
  # πŸ—„ DB
37
  # =========================
38
- def get_data(uid):
39
- data = mdb.get(f"user_{uid}", "json")
40
- if not data:
41
- return {
42
- "files": [],
43
- "index": {},
44
- "folders": {
45
- "root": {
46
- "files": [],
47
- "folders": []
48
- }
49
- }
50
  }
51
- return data
 
 
 
52
 
53
  def save_data(uid, data):
54
  mdb.set(f"user_{uid}", "json", data)
55
 
 
 
 
 
56
  # =========================
57
  # πŸ“Š STORAGE BAR
58
  # =========================
59
- def storage_bar(used, total):
 
60
  ratio = used / total if total else 0
61
  filled = int(ratio * 10)
62
  return "β–ˆ"*filled + "β–‘"*(10-filled)
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  # =========================
65
  # 🏠 MENU
66
  # =========================
@@ -70,25 +95,20 @@ def main_menu(uid):
70
 
71
  return f"""☁️ Cloud Bot
72
 
73
- {storage_bar(used, MAX_STORAGE)}
 
74
  {round(used/1024/1024,2)} MB / 15360 MB
75
  """
76
 
77
  def main_kb():
78
  return InlineKeyboardMarkup([
79
  [InlineKeyboardButton("πŸ“€ Upload", callback_data="upload_root")],
80
- [InlineKeyboardButton("πŸ“‚ Files", callback_data="open_root")]
 
81
  ])
82
 
83
  # =========================
84
- # πŸš€ START
85
- # =========================
86
- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
87
- uid = update.effective_user.id
88
- await update.message.reply_text(main_menu(uid), reply_markup=main_kb())
89
-
90
- # =========================
91
- # πŸ“ FOLDER UI
92
  # =========================
93
  def build_folder(data, folder):
94
  f = data["folders"][folder]
@@ -101,13 +121,27 @@ def build_folder(data, folder):
101
  for fid in f["files"]:
102
  file = data["index"][fid]
103
  kb.append([InlineKeyboardButton(
104
- file["original_name"],
105
  callback_data=f"file_{fid}"
106
  )])
107
 
108
- kb.append([InlineKeyboardButton("βž• Folder", callback_data=f"newfolder_{folder}")])
109
- kb.append([InlineKeyboardButton("πŸ“€ Upload", callback_data=f"upload_{folder}")])
110
- kb.append([InlineKeyboardButton("πŸ”™ Back", callback_data="cancel")])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  return f"πŸ“ {folder}", InlineKeyboardMarkup(kb)
113
 
@@ -122,12 +156,12 @@ async def buttons(update: Update, context: ContextTypes.DEFAULT_TYPE):
122
  uid = q.from_user.id
123
  data = get_data(uid)
124
 
125
- # BACK
126
- if q.data == "cancel":
127
- user_state.pop(uid, None)
128
- return await q.message.edit_text(main_menu(uid), reply_markup=main_kb())
129
 
130
- # OPEN FOLDER
131
  if q.data.startswith("open_"):
132
  folder = q.data.split("_",1)[1]
133
  text, kb = build_folder(data, folder)
@@ -136,40 +170,95 @@ async def buttons(update: Update, context: ContextTypes.DEFAULT_TYPE):
136
  # UPLOAD
137
  if q.data.startswith("upload_"):
138
  folder = q.data.split("_",1)[1]
139
-
140
  user_state[uid] = {"mode":"upload","folder":folder}
141
  return await q.message.edit_text(f"πŸ“€ Upload to {folder}")
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  # NEW FOLDER
144
  if q.data.startswith("newfolder_"):
145
  parent = q.data.split("_",1)[1]
146
-
147
  user_state[uid] = {"mode":"new_folder","parent":parent}
148
  return await q.message.edit_text("πŸ“ Send folder name")
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  except Exception as e:
151
- print("ERROR:", e)
152
 
153
  # =========================
154
- # πŸ“€ FILE UPLOAD
155
  # =========================
156
  async def handle_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
157
  try:
158
  uid = update.effective_user.id
159
 
160
- if uid not in user_state:
161
- return
162
-
163
- state = user_state[uid]
164
- if state["mode"] != "upload":
165
  return
166
 
167
- folder = state["folder"]
168
  data = get_data(uid)
169
 
170
  doc = update.message.document
171
- if not doc:
172
- return
 
 
173
 
174
  sent = await context.bot.send_document(GROUP_ID, doc.file_id)
175
 
@@ -188,7 +277,6 @@ async def handle_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
188
  data["folders"][folder]["files"].append(name)
189
 
190
  save_data(uid, data)
191
-
192
  user_state.pop(uid)
193
 
194
  await update.message.reply_text("βœ… Uploaded", reply_markup=main_kb())
@@ -197,7 +285,7 @@ async def handle_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
197
  print("UPLOAD ERROR:", e)
198
 
199
  # =========================
200
- # πŸ“ TEXT
201
  # =========================
202
  async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
203
  try:
@@ -209,17 +297,65 @@ async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
209
  state = user_state[uid]
210
  data = get_data(uid)
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  if state["mode"] == "new_folder":
213
  name = update.message.text
214
  parent = state["parent"]
215
 
216
- data["folders"][name] = {"files": [], "folders": []}
217
  data["folders"][parent]["folders"].append(name)
218
 
219
  save_data(uid, data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
 
221
  user_state.pop(uid)
222
- await update.message.reply_text("βœ… Folder created", reply_markup=main_kb())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
  except Exception as e:
225
  print("TEXT ERROR:", e)
@@ -234,5 +370,5 @@ app.add_handler(CallbackQueryHandler(buttons))
234
  app.add_handler(MessageHandler(filters.Document.ALL, handle_file))
235
  app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_text))
236
 
237
- print("πŸ”₯ BOT RUNNING")
238
  app.run_polling()
 
1
  import os
2
  import threading
3
  import time
4
+ import hashlib
5
  import random
6
+ import string
7
  from datetime import datetime
8
 
9
  from flask_srvr import run_flask
 
27
  # =========================
28
  BOT_TOKEN = os.getenv("tgtkn")
29
  GROUP_ID = -1003799294466
30
+ PAGE_SIZE = 5
31
  MAX_STORAGE = 15 * 1024 * 1024 * 1024
32
+ HARDCODE_ADMIN = 83939584939485
33
 
34
  # =========================
35
  # 🧠 STATE
 
39
  # =========================
40
  # πŸ—„ DB
41
  # =========================
42
+ def default_data():
43
+ return {
44
+ "files": [],
45
+ "index": {},
46
+ "folders": {
47
+ "root": {"files": [], "folders": [], "parent": None}
 
 
 
 
 
 
48
  }
49
+ }
50
+
51
+ def get_data(uid):
52
+ return mdb.get(f"user_{uid}", "json") or default_data()
53
 
54
  def save_data(uid, data):
55
  mdb.set(f"user_{uid}", "json", data)
56
 
57
+ def is_admin(uid):
58
+ admins = mdb.get("admins", "json") or []
59
+ return uid == HARDCODE_ADMIN or uid in admins
60
+
61
  # =========================
62
  # πŸ“Š STORAGE BAR
63
  # =========================
64
+ def storage_bar(used):
65
+ total = MAX_STORAGE
66
  ratio = used / total if total else 0
67
  filled = int(ratio * 10)
68
  return "β–ˆ"*filled + "β–‘"*(10-filled)
69
 
70
+ # =========================
71
+ # 🧾 ICON
72
+ # =========================
73
+ def get_icon(name):
74
+ ext = name.lower().split('.')[-1]
75
+ if ext == "pdf": return "πŸ“„"
76
+ if ext in ["mp4","mkv"]: return "πŸŽ₯"
77
+ if ext in ["jpg","png","jpeg"]: return "πŸ–Ό"
78
+ return "πŸ“¦"
79
+
80
+ # =========================
81
+ # πŸ” PASSWORD
82
+ # =========================
83
+ def gen_pass():
84
+ return ''.join(random.choices(string.ascii_letters+string.digits,k=16))
85
+
86
+ def hash_pass(p):
87
+ return hashlib.sha256(p.encode()).hexdigest()
88
+
89
  # =========================
90
  # 🏠 MENU
91
  # =========================
 
95
 
96
  return f"""☁️ Cloud Bot
97
 
98
+ πŸ“Š Storage:
99
+ {storage_bar(used)}
100
  {round(used/1024/1024,2)} MB / 15360 MB
101
  """
102
 
103
  def main_kb():
104
  return InlineKeyboardMarkup([
105
  [InlineKeyboardButton("πŸ“€ Upload", callback_data="upload_root")],
106
+ [InlineKeyboardButton("πŸ“‚ My Files", callback_data="open_root")],
107
+ [InlineKeyboardButton("πŸ” Search", callback_data="search")],
108
  ])
109
 
110
  # =========================
111
+ # πŸ“ FOLDER VIEW
 
 
 
 
 
 
 
112
  # =========================
113
  def build_folder(data, folder):
114
  f = data["folders"][folder]
 
121
  for fid in f["files"]:
122
  file = data["index"][fid]
123
  kb.append([InlineKeyboardButton(
124
+ f"{get_icon(file['original_name'])} {file['original_name']}",
125
  callback_data=f"file_{fid}"
126
  )])
127
 
128
+ kb.append([
129
+ InlineKeyboardButton("βž• Folder", callback_data=f"newfolder_{folder}"),
130
+ InlineKeyboardButton("✏️ Rename", callback_data=f"renamefolder_{folder}")
131
+ ])
132
+
133
+ if folder != "root":
134
+ kb.append([
135
+ InlineKeyboardButton("πŸ—‘ Delete", callback_data=f"delfolder_{folder}")
136
+ ])
137
+
138
+ kb.append([
139
+ InlineKeyboardButton("πŸ“€ Upload Here", callback_data=f"upload_{folder}")
140
+ ])
141
+
142
+ kb.append([
143
+ InlineKeyboardButton("πŸ”™ Back", callback_data=f"open_{f['parent'] or 'root'}")
144
+ ])
145
 
146
  return f"πŸ“ {folder}", InlineKeyboardMarkup(kb)
147
 
 
156
  uid = q.from_user.id
157
  data = get_data(uid)
158
 
159
+ # SEARCH MODE
160
+ if q.data == "search":
161
+ user_state[uid] = {"mode":"search"}
162
+ return await q.message.edit_text("πŸ” Send file name")
163
 
164
+ # OPEN
165
  if q.data.startswith("open_"):
166
  folder = q.data.split("_",1)[1]
167
  text, kb = build_folder(data, folder)
 
170
  # UPLOAD
171
  if q.data.startswith("upload_"):
172
  folder = q.data.split("_",1)[1]
 
173
  user_state[uid] = {"mode":"upload","folder":folder}
174
  return await q.message.edit_text(f"πŸ“€ Upload to {folder}")
175
 
176
+ # FILE
177
+ if q.data.startswith("file_"):
178
+ fid = q.data.split("_",1)[1]
179
+ f = data["index"][fid]
180
+
181
+ kb = [
182
+ [InlineKeyboardButton("πŸ‘ Preview", callback_data=f"preview_{fid}")],
183
+ [InlineKeyboardButton("πŸ“₯ Download", callback_data=f"download_{fid}")],
184
+ [InlineKeyboardButton("πŸ” Share", callback_data=f"share_{fid}")],
185
+ [InlineKeyboardButton("πŸ”™ Back", callback_data="open_root")]
186
+ ]
187
+
188
+ return await q.message.edit_text(f"πŸ“„ {f['original_name']}", reply_markup=kb)
189
+
190
+ # PREVIEW
191
+ if q.data.startswith("preview_"):
192
+ fid = q.data.split("_",1)[1]
193
+ f = data["index"][fid]
194
+ ext = f["original_name"].lower().split('.')[-1]
195
+
196
+ if ext in ["jpg","png","jpeg"]:
197
+ await context.bot.send_photo(uid, f["file_id"])
198
+ elif ext in ["mp4","mkv"]:
199
+ await context.bot.send_video(uid, f["file_id"])
200
+ else:
201
+ await context.bot.send_document(uid, f["file_id"])
202
+ return
203
+
204
+ # DOWNLOAD
205
+ if q.data.startswith("download_"):
206
+ fid = q.data.split("_",1)[1]
207
+ await context.bot.send_document(uid, data["index"][fid]["file_id"])
208
+ return
209
+
210
+ # SHARE
211
+ if q.data.startswith("share_"):
212
+ fid = q.data.split("_",1)[1]
213
+
214
+ pwd = gen_pass()
215
+ data["index"][fid]["share"] = hash_pass(pwd)
216
+ save_data(uid, data)
217
+
218
+ link = f"https://t.me/{context.bot.username}?start=share_{fid}_{uid}"
219
+
220
+ return await q.message.edit_text(f"πŸ”— {link}\n\nπŸ” Password:\n{pwd}")
221
+
222
  # NEW FOLDER
223
  if q.data.startswith("newfolder_"):
224
  parent = q.data.split("_",1)[1]
 
225
  user_state[uid] = {"mode":"new_folder","parent":parent}
226
  return await q.message.edit_text("πŸ“ Send folder name")
227
 
228
+ # RENAME FOLDER
229
+ if q.data.startswith("renamefolder_"):
230
+ folder = q.data.split("_",1)[1]
231
+ user_state[uid] = {"mode":"rename_folder","folder":folder}
232
+ return await q.message.edit_text("✏️ Send new name")
233
+
234
+ # DELETE FOLDER
235
+ if q.data.startswith("delfolder_"):
236
+ folder = q.data.split("_",1)[1]
237
+ code = str(random.randint(100000,999999))
238
+ user_state[uid] = {"mode":"delete_folder","folder":folder,"code":code}
239
+ return await q.message.edit_text(f"Type code:\n{code}")
240
+
241
  except Exception as e:
242
+ print("BTN ERROR:", e)
243
 
244
  # =========================
245
+ # πŸ“€ UPLOAD
246
  # =========================
247
  async def handle_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
248
  try:
249
  uid = update.effective_user.id
250
 
251
+ if uid not in user_state or user_state[uid]["mode"] != "upload":
 
 
 
 
252
  return
253
 
254
+ folder = user_state[uid]["folder"]
255
  data = get_data(uid)
256
 
257
  doc = update.message.document
258
+ used = sum(f["file_size"] for f in data["files"])
259
+
260
+ if not is_admin(uid) and used + doc.file_size > MAX_STORAGE:
261
+ return await update.message.reply_text("❌ Storage full")
262
 
263
  sent = await context.bot.send_document(GROUP_ID, doc.file_id)
264
 
 
277
  data["folders"][folder]["files"].append(name)
278
 
279
  save_data(uid, data)
 
280
  user_state.pop(uid)
281
 
282
  await update.message.reply_text("βœ… Uploaded", reply_markup=main_kb())
 
285
  print("UPLOAD ERROR:", e)
286
 
287
  # =========================
288
+ # πŸ“ TEXT HANDLER
289
  # =========================
290
  async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
291
  try:
 
297
  state = user_state[uid]
298
  data = get_data(uid)
299
 
300
+ # SEARCH
301
+ if state["mode"] == "search":
302
+ q = update.message.text.lower()
303
+ res = [f for f in data["files"] if q in f["original_name"].lower()]
304
+
305
+ kb = []
306
+ for f in res[:5]:
307
+ kb.append([InlineKeyboardButton(
308
+ f["original_name"],
309
+ callback_data=f"file_{f['file_name']}"
310
+ )])
311
+
312
+ return await update.message.reply_text("πŸ” Results", reply_markup=InlineKeyboardMarkup(kb))
313
+
314
+ # CREATE FOLDER
315
  if state["mode"] == "new_folder":
316
  name = update.message.text
317
  parent = state["parent"]
318
 
319
+ data["folders"][name] = {"files":[],"folders":[],"parent":parent}
320
  data["folders"][parent]["folders"].append(name)
321
 
322
  save_data(uid, data)
323
+ user_state.pop(uid)
324
+
325
+ return await update.message.reply_text("βœ… Folder Created", reply_markup=main_kb())
326
+
327
+ # RENAME FOLDER
328
+ if state["mode"] == "rename_folder":
329
+ new = update.message.text
330
+ old = state["folder"]
331
+
332
+ data["folders"][new] = data["folders"].pop(old)
333
+
334
+ parent = data["folders"][new]["parent"]
335
+ data["folders"][parent]["folders"].remove(old)
336
+ data["folders"][parent]["folders"].append(new)
337
 
338
+ save_data(uid, data)
339
  user_state.pop(uid)
340
+
341
+ return await update.message.reply_text("βœ… Renamed", reply_markup=main_kb())
342
+
343
+ # DELETE FOLDER
344
+ if state["mode"] == "delete_folder":
345
+ if update.message.text == state["code"]:
346
+ folder = state["folder"]
347
+
348
+ if data["folders"][folder]["files"] or data["folders"][folder]["folders"]:
349
+ return await update.message.reply_text("❌ Not empty")
350
+
351
+ parent = data["folders"][folder]["parent"]
352
+ data["folders"][parent]["folders"].remove(folder)
353
+ del data["folders"][folder]
354
+
355
+ save_data(uid, data)
356
+ user_state.pop(uid)
357
+
358
+ return await update.message.reply_text("πŸ—‘ Deleted", reply_markup=main_kb())
359
 
360
  except Exception as e:
361
  print("TEXT ERROR:", e)
 
370
  app.add_handler(MessageHandler(filters.Document.ALL, handle_file))
371
  app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_text))
372
 
373
+ print("πŸ”₯ FULL BOT RUNNING")
374
  app.run_polling()