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); +})();