ulduldp commited on
Commit
d2e113d
Β·
verified Β·
1 Parent(s): dfad8b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +195 -192
app.py CHANGED
@@ -1,283 +1,286 @@
1
  import os
2
  import threading
3
  import time
 
 
 
 
 
4
  from flask_srvr import run_flask
 
 
5
 
 
 
 
 
 
6
  def start_flask():
7
- flask_thread = threading.Thread(target=run_flask)
8
- flask_thread.daemon = True # background me chalega
9
- flask_thread.start()
10
 
11
- # Flask start karo
12
  start_flask()
13
 
14
- print("rinning")
 
 
15
  BOT_TOKEN = os.getenv("tgtkn")
16
  GROUP_ID = -1003799294466
17
-
18
- import time
19
- from datetime import datetime
20
- from telegram import *
21
- from telegram.ext import *
22
- import mdb
23
-
24
- waiting_for_file = set()
25
- PAGE_SIZE = 5
26
 
27
  # =========================
28
- # 🧠 DATABASE
29
  # =========================
 
30
 
31
- def get_data(user_id):
32
- key = f"user_{user_id}"
33
- data = mdb.get(key, "json")
 
 
34
  if not data:
35
- return {"files": [], "index": {}}
 
 
 
 
 
 
 
 
 
 
36
  return data
37
 
 
 
38
 
39
- def save_data(user_id, data):
40
- key = f"user_{user_id}"
41
- mdb.set(key, "json", data)
42
 
 
 
43
 
44
  # =========================
45
- # πŸš€ START
46
  # =========================
47
-
48
- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
49
- kb = [
50
- [InlineKeyboardButton("πŸ“€ Upload", callback_data="upload")],
51
- [InlineKeyboardButton("πŸ“‚ My Files", callback_data="files_0")],
52
- [InlineKeyboardButton("πŸ“Š Stats", callback_data="stats")]
53
- ]
54
- await update.message.reply_text(
55
- "☁️ Advanced Cloud Bot",
56
- reply_markup=InlineKeyboardMarkup(kb)
57
- )
58
-
59
 
60
  # =========================
61
- # πŸ“‚ PAGINATION
62
  # =========================
 
 
 
 
 
 
63
 
64
- def build_file_page(data, page):
65
- files = data["files"]
66
- start = page * PAGE_SIZE
67
- end = start + PAGE_SIZE
68
-
69
- chunk = files[start:end]
70
-
71
- text = "πŸ“‚ Your Files:\n\n"
72
- kb = []
73
-
74
- for f in chunk:
75
- fname = f["file_name"]
76
- text += f"β€’ {fname}\n"
77
 
78
- kb.append([
79
- InlineKeyboardButton("ℹ️", callback_data=f"info_{fname}"),
80
- InlineKeyboardButton("πŸ—‘", callback_data=f"del_{fname}")
81
- ])
82
 
83
- nav = []
84
- if page > 0:
85
- nav.append(InlineKeyboardButton("⬅️", callback_data=f"files_{page-1}"))
86
- if end < len(files):
87
- nav.append(InlineKeyboardButton("➑️", callback_data=f"files_{page+1}"))
88
 
89
- if nav:
90
- kb.append(nav)
 
 
91
 
92
- return text, InlineKeyboardMarkup(kb)
 
 
 
 
 
93
 
 
 
 
 
 
 
94
 
95
  # =========================
96
- # πŸ”˜ BUTTONS
97
  # =========================
 
 
98
 
99
- async def buttons(update: Update, context: ContextTypes.DEFAULT_TYPE):
100
- q = update.callback_query
101
- await q.answer()
102
- user_id = q.from_user.id
103
- data = get_data(user_id)
104
 
105
- # πŸ“€ upload
106
- if q.data == "upload":
107
- waiting_for_file.add(user_id)
108
- await q.message.reply_text("πŸ“ Send file")
109
 
110
- # πŸ“‚ files pagination
111
- elif q.data.startswith("files_"):
112
- page = int(q.data.split("_")[1])
113
- text, kb = build_file_page(data, page)
114
- await q.message.reply_text(text, reply_markup=kb)
 
115
 
116
- # πŸ“Š stats
117
- elif q.data == "stats":
118
- await q.message.reply_text(f"πŸ“Š Files: {len(data['files'])}")
 
119
 
120
- # πŸ—‘ delete confirm
121
- elif q.data.startswith("del_"):
122
- fname = q.data.split("_", 1)[1]
123
- kb = [
124
- [InlineKeyboardButton("βœ… Confirm", callback_data=f"confirmdel_{fname}")],
125
- [InlineKeyboardButton("❌ Cancel", callback_data="files_0")]
126
- ]
127
- await q.message.reply_text(f"Delete {fname}?", reply_markup=InlineKeyboardMarkup(kb))
128
 
129
- elif q.data.startswith("confirmdel_"):
130
- fname = q.data.split("_", 1)[1]
 
131
 
132
- if fname in data["index"]:
133
- data["files"] = [f for f in data["files"] if f["file_name"] != fname]
134
- del data["index"][fname]
135
- save_data(user_id, data)
136
 
137
- await q.message.reply_text("πŸ—‘ Deleted")
138
 
139
- # ℹ️ info
140
- elif q.data.startswith("info_"):
141
- fname = q.data.split("_", 1)[1]
 
 
 
142
 
143
- if fname in data["index"]:
144
- f = data["index"][fname]
145
 
146
- kb = [
147
- [InlineKeyboardButton("πŸ”— Share", callback_data=f"share_{fname}")],
148
- [InlineKeyboardButton("❌ Close", callback_data="files_0")]
149
- ]
150
 
151
- text = (
152
- f"πŸ“„ File Info\n\n"
153
- f"Name: {f['original_name']}\n"
154
- f"Saved As: {f['file_name']}\n"
155
- f"Size: {f['file_size']} bytes\n"
156
- f"Uploaded: {f['upload_date']}\n"
157
- f"Shared With: {len(f.get('shared_with', []))} users"
158
- )
159
 
160
- await q.message.reply_text(text, reply_markup=InlineKeyboardMarkup(kb))
 
 
 
 
161
 
162
- # πŸ”— share
163
- elif q.data.startswith("share_"):
164
- fname = q.data.split("_", 1)[1]
 
 
165
 
166
- if fname in data["index"]:
167
- f = data["index"][fname]
168
- link = f"https://t.me/{context.bot.username}?start=share_{fname}_{user_id}"
169
 
170
- await q.message.reply_text(f"πŸ”— Share Link:\n{link}")
 
171
 
 
172
 
173
  # =========================
174
- # πŸ“€ FILE UPLOAD
175
  # =========================
176
-
177
  async def handle_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
178
- user_id = update.effective_user.id
179
 
180
- if user_id not in waiting_for_file:
181
  return
182
 
183
- doc = update.message.document
184
- if not doc:
185
  return
186
 
187
- data = get_data(user_id)
 
 
 
 
188
 
189
- original = doc.file_name
190
- ext = original.split('.')[-1] if '.' in original else "dat"
191
 
192
- ts = int(time.time())
193
- new_name = f"{user_id}_{ts}.{ext}"
194
 
195
- sent = await context.bot.send_document(
196
- chat_id=GROUP_ID,
197
- document=doc.file_id,
198
- filename=new_name
199
- )
200
 
201
  entry = {
202
- "file_name": new_name,
203
- "original_name": original,
204
  "file_id": sent.document.file_id,
205
  "file_size": doc.file_size,
206
- "upload_date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
207
- "shared_with": []
208
  }
209
 
210
  data["files"].append(entry)
211
- data["index"][new_name] = entry
212
-
213
- save_data(user_id, data)
214
 
215
- waiting_for_file.discard(user_id)
216
- await update.message.reply_text("βœ… Uploaded")
217
 
 
 
218
 
219
  # =========================
220
- # πŸ” SEARCH
221
  # =========================
 
 
222
 
223
- async def search(update: Update, context: ContextTypes.DEFAULT_TYPE):
224
- user_id = update.effective_user.id
225
- data = get_data(user_id)
226
-
227
- if not context.args:
228
- return await update.message.reply_text("Usage: /search name")
229
-
230
- query = context.args[0].lower()
231
-
232
- results = [
233
- f for f in data["files"]
234
- if query in f["file_name"].lower() or query in f["original_name"].lower()
235
- ]
236
 
237
- if not results:
238
- return await update.message.reply_text("❌ No results")
239
 
240
- msg = "πŸ” Results:\n\n"
241
- for f in results[:10]:
242
- msg += f"β€’ {f['file_name']}\n"
 
243
 
244
- await update.message.reply_text(msg)
 
245
 
 
 
246
 
247
- # =========================
248
- # πŸ“₯ GET
249
- # =========================
250
 
251
- async def get_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
252
- user_id = update.effective_user.id
253
- data = get_data(user_id)
 
254
 
255
- if not context.args:
256
- return
257
 
258
- fname = context.args[0]
 
259
 
260
- if fname in data["index"]:
261
- await context.bot.send_document(
262
- chat_id=update.effective_chat.id,
263
- document=data["index"][fname]["file_id"]
264
- )
265
- else:
266
- await update.message.reply_text("❌ Not found")
267
 
 
 
 
 
268
 
269
- # =========================
270
- # πŸš€ RUN
271
- # =========================
272
-
273
- app = ApplicationBuilder().token(BOT_TOKEN).build()
274
 
275
- app.add_handler(CommandHandler("start", start))
276
- app.add_handler(CommandHandler("search", search))
277
- app.add_handler(CommandHandler("get", get_file))
278
 
279
- app.add_handler(CallbackQueryHandler(buttons))
280
- app.add_handler(MessageHandler(filters.Document.ALL, handle_file))
281
 
282
- print("πŸ”₯ ADVANCED BOT RUNNING...")
283
- 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
10
+ from telegram import *
11
+ from telegram.ext import *
12
 
13
+ import mdb
14
+
15
+ # =========================
16
+ # πŸš€ FLASK
17
+ # =========================
18
  def start_flask():
19
+ t = threading.Thread(target=run_flask)
20
+ t.daemon = True
21
+ t.start()
22
 
 
23
  start_flask()
24
 
25
+ # =========================
26
+ # βš™οΈ CONFIG
27
+ # =========================
28
  BOT_TOKEN = os.getenv("tgtkn")
29
  GROUP_ID = -1003799294466
30
+ MAX_STORAGE = 15 * 1024 * 1024 * 1024
31
+ HARDCODE_ADMIN = 83939584939485
 
 
 
 
 
 
 
32
 
33
  # =========================
34
+ # 🧠 STATE
35
  # =========================
36
+ user_state = {}
37
 
38
+ # =========================
39
+ # πŸ—„ DB
40
+ # =========================
41
+ def get_data(uid):
42
+ data = mdb.get(f"user_{uid}", "json")
43
  if not data:
44
+ return {
45
+ "files": [],
46
+ "index": {},
47
+ "folders": {
48
+ "root": {
49
+ "name": "root",
50
+ "files": [],
51
+ "folders": []
52
+ }
53
+ }
54
+ }
55
  return data
56
 
57
+ def save_data(uid, data):
58
+ mdb.set(f"user_{uid}", "json", data)
59
 
60
+ def get_admins():
61
+ return mdb.get("admins", "json") or []
 
62
 
63
+ def is_admin(uid):
64
+ return uid == HARDCODE_ADMIN or uid in get_admins()
65
 
66
  # =========================
67
+ # πŸ“Š STORAGE BAR
68
  # =========================
69
+ def storage_bar(used, total, length=10):
70
+ ratio = used / total if total else 0
71
+ filled = int(ratio * length)
72
+ return "β–ˆ" * filled + "β–‘" * (length - filled)
 
 
 
 
 
 
 
 
73
 
74
  # =========================
75
+ # 🧾 ICON
76
  # =========================
77
+ def get_icon(name):
78
+ ext = name.lower().split('.')[-1]
79
+ if ext == "pdf": return "πŸ“„"
80
+ if ext in ["mp4","mkv"]: return "πŸŽ₯"
81
+ if ext in ["jpg","png","jpeg"]: return "πŸ–Ό"
82
+ return "πŸ“¦"
83
 
84
+ # =========================
85
+ # 🏠 MENU
86
+ # =========================
87
+ def main_menu(uid):
88
+ data = get_data(uid)
89
+ used = sum(f["file_size"] for f in data["files"])
 
 
 
 
 
 
 
90
 
91
+ bar = storage_bar(used, MAX_STORAGE)
 
 
 
92
 
93
+ return f"""☁️ Cloud Bot
 
 
 
 
94
 
95
+ πŸ“Š Storage:
96
+ {bar}
97
+ {round(used/1024/1024,2)} MB / 15360 MB
98
+ """
99
 
100
+ def main_kb():
101
+ return InlineKeyboardMarkup([
102
+ [InlineKeyboardButton("πŸ“€ Upload", callback_data="upload_root")],
103
+ [InlineKeyboardButton("πŸ“‚ My Files", callback_data="open_root")],
104
+ [InlineKeyboardButton("πŸ” Search", callback_data="search")]
105
+ ])
106
 
107
+ # =========================
108
+ # πŸš€ START
109
+ # =========================
110
+ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
111
+ uid = update.effective_user.id
112
+ await update.message.reply_text(main_menu(uid), reply_markup=main_kb())
113
 
114
  # =========================
115
+ # πŸ“ FOLDER VIEW
116
  # =========================
117
+ def build_folder(data, folder):
118
+ f = data["folders"][folder]
119
 
120
+ kb = []
 
 
 
 
121
 
122
+ for sub in f["folders"]:
123
+ kb.append([InlineKeyboardButton(f"πŸ“ {sub}", callback_data=f"open_{sub}")])
 
 
124
 
125
+ for fid in f["files"]:
126
+ file = data["index"][fid]
127
+ kb.append([InlineKeyboardButton(
128
+ f"{get_icon(file['original_name'])} {file['original_name']}",
129
+ callback_data=f"file_{fid}"
130
+ )])
131
 
132
+ kb.append([
133
+ InlineKeyboardButton("βž• Folder", callback_data=f"newfolder_{folder}"),
134
+ InlineKeyboardButton("✏️ Rename", callback_data=f"renamefolder_{folder}")
135
+ ])
136
 
137
+ kb.append([
138
+ InlineKeyboardButton("πŸ—‘ Delete", callback_data=f"delfolder_{folder}")
139
+ ])
 
 
 
 
 
140
 
141
+ kb.append([
142
+ InlineKeyboardButton("πŸ“€ Upload", callback_data=f"upload_{folder}")
143
+ ])
144
 
145
+ kb.append([
146
+ InlineKeyboardButton("πŸ”™ Back", callback_data="cancel")
147
+ ])
 
148
 
149
+ return f"πŸ“ {folder}", InlineKeyboardMarkup(kb)
150
 
151
+ # =========================
152
+ # πŸ”˜ BUTTONS
153
+ # =========================
154
+ async def buttons(update: Update, context: ContextTypes.DEFAULT_TYPE):
155
+ q = update.callback_query
156
+ await q.answer()
157
 
158
+ uid = q.from_user.id
159
+ data = get_data(uid)
160
 
161
+ # BACK
162
+ if q.data == "cancel":
163
+ user_state.pop(uid, None)
164
+ return await q.message.edit_text(main_menu(uid), reply_markup=main_kb())
165
 
166
+ # OPEN FOLDER
167
+ if q.data.startswith("open_"):
168
+ folder = q.data.split("_",1)[1]
169
+ text, kb = build_folder(data, folder)
170
+ return await q.message.edit_text(text, reply_markup=kb)
 
 
 
171
 
172
+ # NEW FOLDER
173
+ if q.data.startswith("newfolder_"):
174
+ parent = q.data.split("_",1)[1]
175
+ user_state[uid] = {"mode":"new_folder","parent":parent}
176
+ return await q.message.edit_text("πŸ“ Send folder name")
177
 
178
+ # RENAME FOLDER
179
+ if q.data.startswith("renamefolder_"):
180
+ folder = q.data.split("_",1)[1]
181
+ user_state[uid] = {"mode":"rename_folder","folder":folder}
182
+ return await q.message.edit_text("✏️ Send new folder name")
183
 
184
+ # DELETE FOLDER
185
+ if q.data.startswith("delfolder_"):
186
+ folder = q.data.split("_",1)[1]
187
 
188
+ code = str(random.randint(100000,999999))
189
+ user_state[uid] = {"mode":"delete_folder","folder":folder,"code":code}
190
 
191
+ return await q.message.edit_text(f"Type code to delete:\n{code}")
192
 
193
  # =========================
194
+ # πŸ“€ UPLOAD
195
  # =========================
 
196
  async def handle_file(update: Update, context: ContextTypes.DEFAULT_TYPE):
197
+ uid = update.effective_user.id
198
 
199
+ if uid not in user_state:
200
  return
201
 
202
+ state = user_state[uid]
203
+ if state["mode"] != "upload":
204
  return
205
 
206
+ folder = state.get("folder","root")
207
+ data = get_data(uid)
208
+
209
+ doc = update.message.document
210
+ used = sum(f["file_size"] for f in data["files"])
211
 
212
+ if not is_admin(uid) and used + doc.file_size > MAX_STORAGE:
213
+ return await update.message.reply_text("❌ Storage Full")
214
 
215
+ sent = await context.bot.send_document(GROUP_ID, doc.file_id)
 
216
 
217
+ name = f"{uid}_{int(time.time())}"
 
 
 
 
218
 
219
  entry = {
220
+ "file_name": name,
221
+ "original_name": doc.file_name,
222
  "file_id": sent.document.file_id,
223
  "file_size": doc.file_size,
224
+ "upload_date": str(datetime.now())
 
225
  }
226
 
227
  data["files"].append(entry)
228
+ data["index"][name] = entry
229
+ data["folders"][folder]["files"].append(name)
 
230
 
231
+ save_data(uid, data)
 
232
 
233
+ user_state.pop(uid)
234
+ await update.message.reply_text("βœ… Uploaded", reply_markup=main_kb())
235
 
236
  # =========================
237
+ # πŸ“ TEXT HANDLER
238
  # =========================
239
+ async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
240
+ uid = update.effective_user.id
241
 
242
+ if uid not in user_state:
243
+ return
 
 
 
 
 
 
 
 
 
 
 
244
 
245
+ state = user_state[uid]
246
+ data = get_data(uid)
247
 
248
+ # CREATE FOLDER
249
+ if state["mode"] == "new_folder":
250
+ name = update.message.text
251
+ parent = state["parent"]
252
 
253
+ data["folders"][name] = {"name":name,"files":[],"folders":[]}
254
+ data["folders"][parent]["folders"].append(name)
255
 
256
+ save_data(uid, data)
257
+ user_state.pop(uid)
258
 
259
+ return await update.message.reply_text("βœ… Folder Created", reply_markup=main_kb())
 
 
260
 
261
+ # RENAME FOLDER
262
+ if state["mode"] == "rename_folder":
263
+ new = update.message.text
264
+ old = state["folder"]
265
 
266
+ data["folders"][new] = data["folders"].pop(old)
 
267
 
268
+ save_data(uid, data)
269
+ user_state.pop(uid)
270
 
271
+ return await update.message.reply_text("βœ… Renamed", reply_markup=main_kb())
 
 
 
 
 
 
272
 
273
+ # DELETE FOLDER CONFIRM
274
+ if state["mode"] == "delete_folder":
275
+ if update.message.text == state["code"]:
276
+ folder = state["folder"]
277
 
278
+ if data["folders"][folder]["files"] or data["folders"][folder]["folders"]:
279
+ return await update.message.reply_text("❌ Folder not empty")
 
 
 
280
 
281
+ del data["folders"][folder]
 
 
282
 
283
+ save_data(uid, data)
284
+ user_state.pop(uid)
285
 
286
+ return await update.message.reply_text("πŸ—‘ Deleted", reply_markup=main_kb())