diff --git a/README.md b/README.md
deleted file mode 100644
index 8b13789..0000000
--- a/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/downloader/index.html b/downloader/index.html
new file mode 100644
index 0000000..f365be8
--- /dev/null
+++ b/downloader/index.html
@@ -0,0 +1,242 @@
+
+
+
+
+ Download App
+
+
+
+
+
+
+
+
+
diff --git a/downloader/main.py b/downloader/main.py
new file mode 100644
index 0000000..8ea1cf2
--- /dev/null
+++ b/downloader/main.py
@@ -0,0 +1,136 @@
+from fastapi import FastAPI, WebSocket, HTTPException, Request, Depends, status
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+from fastapi.responses import HTMLResponse
+from fastapi.staticfiles import StaticFiles
+from starlette.websockets import WebSocketDisconnect
+from typing import Optional
+from pydantic import BaseModel
+import aiohttp, asyncio
+import os, tqdm, json
+from collections import defaultdict
+from base64 import b64encode
+
+app = FastAPI()
+
+connected_clients = defaultdict(list)
+downloads = defaultdict(dict)
+completed_downloads = defaultdict(dict)
+canceled_downloads = defaultdict(dict)
+
+
+class DownloadRequest(BaseModel):
+ url: str
+
+
+security = HTTPBasic()
+
+
+def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
+ return credentials.username
+
+
+@app.get("/")
+async def get(request: Request):
+ with open("index.html", "r") as f:
+ content = f.read()
+ return HTMLResponse(content=content)
+
+
+@app.get("/file_exists/")
+async def file_exists(filename: str):
+ if os.path.isfile(filename):
+ os.rename(filename, filename + "+")
+ return {"exists": os.path.isfile(filename)}
+
+
+@app.get("/downloads/")
+async def get_downloads(username: str = Depends(get_current_username)):
+ return {
+ "in_progress": list(downloads[username].keys()),
+ "completed": list(completed_downloads[username].keys()),
+ "canceled": list(canceled_downloads[username].keys()),
+ }
+
+
+@app.post("/download/")
+async def download_file(
+ request: DownloadRequest, username: str = Depends(get_current_username)
+):
+ url = request.url
+ filename = url.split("/")[-1]
+
+ if url in downloads[username]:
+ raise HTTPException(status_code=400, detail="Download already in progress")
+
+ download_task = asyncio.create_task(do_download(url, filename, username))
+ downloads[username][url] = download_task
+
+ return {"message": "Download started"}
+
+
+async def do_download(url, filename, username):
+ try:
+ async with aiohttp.ClientSession() as session:
+ async with session.get(url) as resp:
+ file_size = int(resp.headers["Content-Length"])
+ pbar = tqdm.tqdm(
+ total=(file_size / (1024 * 128)),
+ unit="Mb",
+ ascii=True,
+ unit_scale=True,
+ )
+ with open(filename, "wb") as f:
+ chunk_size = 1024
+ downloaded_size = 0
+ last_progress = 0
+ async for chunk in resp.content.iter_any():
+ pbar.update(len(chunk) / (1024 * 128))
+ if url not in downloads[username]:
+ pbar.close()
+ return
+ f.write(chunk)
+ downloaded_size += len(chunk)
+ # Notify the client about the progress
+ progress = int((downloaded_size / file_size) * 100)
+ # Check if the integer percentage has changed
+ if progress != last_progress:
+ last_progress = progress
+ await notify_clients(progress, url, username)
+ pbar.close()
+ finally:
+ if url in downloads[username]:
+ if url not in canceled_downloads[username]:
+ completed_downloads[username][url] = downloads[username][url]
+ del downloads[username][url]
+
+
+@app.post("/cancel/")
+async def cancel_download(
+ request: DownloadRequest, username: str = Depends(get_current_username)
+):
+ url = request.url
+ if url in downloads[username]:
+ canceled_downloads[username][url] = downloads[username][url]
+ downloads[username][url].cancel()
+ return {"message": "Download canceled"}
+ if url in completed_downloads[username]:
+ del completed_downloads[username][url]
+ return {"message": "Download removed"}
+ else:
+ raise HTTPException(status_code=404, detail="No such download")
+
+
+@app.websocket("/ws/{username}")
+async def websocket_endpoint(websocket: WebSocket, username: str):
+ await websocket.accept()
+ connected_clients[username].append(websocket)
+ try:
+ while True:
+ await websocket.receive_text()
+ except WebSocketDisconnect:
+ connected_clients[username].remove(websocket)
+
+
+async def notify_clients(progress, url, username):
+ for client in connected_clients[username]:
+ await client.send_text(json.dumps({"progress": progress, "url": url}))
\ No newline at end of file
diff --git a/icon_proxy/icons/live-calendar.ico b/icon_proxy/icons/live-calendar.ico
new file mode 100644
index 0000000..5702824
Binary files /dev/null and b/icon_proxy/icons/live-calendar.ico differ
diff --git a/icon_proxy/icons/twitter.ico b/icon_proxy/icons/twitter.ico
new file mode 100644
index 0000000..91dedd2
Binary files /dev/null and b/icon_proxy/icons/twitter.ico differ
diff --git a/icon_proxy/icons/twitter.png b/icon_proxy/icons/twitter.png
new file mode 100644
index 0000000..a3522cd
Binary files /dev/null and b/icon_proxy/icons/twitter.png differ
diff --git a/icon_proxy/main.py b/icon_proxy/main.py
new file mode 100644
index 0000000..d6b4647
--- /dev/null
+++ b/icon_proxy/main.py
@@ -0,0 +1,33 @@
+from fastapi import FastAPI
+from fastapi.responses import FileResponse, HTMLResponse
+from fastapi.staticfiles import StaticFiles
+from pathlib import Path
+
+app = FastAPI()
+
+app.mount("/icons", StaticFiles(directory="icons"), name="icons")
+
+reds = {"live-calendar": "https://outlook.live.com/calendar/0/view/month",
+ "twitter": "https://twitter.com"}
+
+@app.get("/{icon_name}")
+async def redirect_html(icon_name: str):
+ redirect_url = reds.get(icon_name)
+ html_content = f"""
+
+
+
+
+
+ Redirecting...
+
+ """
+ return HTMLResponse(content=html_content)
+
+@app.get("/{icon_name}/favicon.ico")
+async def get_icon(icon_name: str):
+ icon_path = Path(f"icons/{icon_name}.ico")
+ if icon_path.exists():
+ return FileResponse(icon_path)
+ else:
+ return {"error": "Icon not found"}
diff --git a/twt_remove_ad.js b/twt_remove_ad.js
new file mode 100644
index 0000000..21bd4e6
--- /dev/null
+++ b/twt_remove_ad.js
@@ -0,0 +1,28 @@
+// ==UserScript==
+// @name Twitter Remove Ad
+// @namespace http://tampermonkey.net/
+// @version 0.1
+// @description try to take over the world!
+// @author You
+// @match https://twitter.com/home
+// @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com
+// @grant none
+// ==/UserScript==
+
+(function() {
+ let removead = setInterval( function(){
+ console.log("Checking ad..");
+ [...document.querySelectorAll("div[data-testid=cellInnerDiv]")].forEach(e => {
+ var ad = 0;
+ [...e.getElementsByTagName("span")].forEach(f => {
+ if (f.innerText == "Ad") {
+ ad = 1;
+ }
+ });
+ if( ad ) {
+ console.log(e.querySelectorAll("div[data-testid=User-Name]")[0].innerText);
+ e.innerHTML = "";
+ }
+ });
+ }, 1000);
+})();