Compare commits

...

17 Commits
0.1 ... master

Author SHA1 Message Date
f167669bc4 readme updates 2024-04-13 23:35:11 -04:00
0187f66627 update readme files 2024-04-13 23:33:58 -04:00
7b8a6a34fe update README.md 2024-04-13 23:24:16 -04:00
b9e3591299 update README.md 2024-04-13 23:22:36 -04:00
73a80f6d3d add support for TinyURL 2024-04-13 23:03:50 -04:00
e5b701aa55 update console messages 2024-04-13 22:29:15 -04:00
9afc7b1298 update version number 2024-04-13 21:49:50 -04:00
a655b3b02e unshortener copies to clipboard 2024-04-13 21:46:51 -04:00
ca2c990002 implement in memory cache 2024-04-13 21:44:41 -04:00
8563addf49 rename extension to Unshortener 2024-04-13 21:09:46 -04:00
c8539af605 add port to Makefile 2024-04-13 21:09:13 -04:00
4962cc0920 remove unneeded activeTab permission 2024-04-13 21:08:51 -04:00
f69f32c438 remove build directory 2024-04-13 21:05:27 -04:00
e8ccfbb80a add typing to unshorten_twitter 2024-04-13 21:04:09 -04:00
4296afee69 rename UNSHORTENERS 2024-04-13 21:03:20 -04:00
4d01e8812d chore: makefile spacing 2024-04-13 20:55:12 -04:00
cf852fa14f add API Makefile 2024-04-13 20:51:37 -04:00
11 changed files with 124 additions and 28 deletions

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
.idea .idea
venv venv
extension/build
__pycache__ __pycache__
*.py[cod] *.py[cod]

View File

@ -1,2 +1,24 @@
# Unshorten # Unshortener
Firefox Extension and API server for revealing links behind shortened URLs. Firefox Extension and API server for revealing links behind shortened URLs.
**Supported sites**:
- t.co
- tinyurl.com
## Usage
In order to deal with CORS, Unshorten must send links to a resolver API.
```shell
cd server
make build
docker -d --name unshortener -p 8000:8000 unshortener-api
```
Build the extension and import into Firefox. Right click on a link and choose
"Unshorten Link". The result will be copied to the clipboard.
```shell
cd extension
make zip
```

View File

@ -6,9 +6,11 @@ VERSION := $(shell jq -r '.version' $(SRC_DIR)/manifest.json)
ZIP_FILE := $(EXTENSION_NAME)-$(VERSION).zip ZIP_FILE := $(EXTENSION_NAME)-$(VERSION).zip
all: zip all: zip
zip: zip:
@mkdir -p $(BUILD_DIR) @mkdir -p $(BUILD_DIR)
zip -r $(BUILD_DIR)/$(ZIP_FILE) $(SRC_DIR) -x "*.DS_Store" zip -r $(BUILD_DIR)/$(ZIP_FILE) $(SRC_DIR) -x "*.DS_Store"
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)

View File

@ -1,2 +1,14 @@
# Unshorten # Unshortener Extension
A Firefox extension to unshorten links from sites like Twitter. A Firefox extension to reveal links behind URL shorteners like Twitter and TinyURL.
**Supported sites:**
- t.co
- tinyurl.com
## Usage
Build the extension and install it in Firefox. Right-clicking links will reveal a new
"Unshorten link" option which will resolve the link and copy it to the clipboard.
```shell
make zip
```

Binary file not shown.

View File

@ -1,5 +1,6 @@
const shortenerDomains = [ const shortenerDomains = [
"t.co" "t.co",
"tinyurl.com"
]; ];
browser.contextMenus.create({ browser.contextMenus.create({
@ -28,16 +29,17 @@ function getDomainFromUrl(linkUrl) {
} }
function unshortenUrl(linkUrl) { function unshortenUrl(linkUrl) {
console.log(linkUrl);
fetch("http://localhost:8000/?url=" + linkUrl) fetch("http://localhost:8000/?url=" + linkUrl)
.then(res => { .then(res => {
if (!res.ok) { if (!res.ok) {
console.log("error fetching result"); console.log("Couldn't unshorten URL: " + res.statusText);
} }
return res.json(); return res.json();
}) })
.then(data => { .then(unshortenedUrl => {
console.log(data); console.log("unshortened: " + unshortenedUrl)
}); navigator.clipboard.writeText(unshortenedUrl)
.catch(err => console.error("Couldn't copy to clipboard: ", err));
})
.catch(err => {console.error("Couldn't contact server:", err)});
} }

View File

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "Unshorten", "name": "Unshortener",
"version": "0.1", "version": "0.3",
"description": "Unshorten links from Twitter.", "description": "Unshorten links from Twitter.",
@ -18,6 +18,7 @@
"permissions": [ "permissions": [
"activeTab", "activeTab",
"clipboardWrite",
"contextMenus" "contextMenus"
] ]
} }

15
server/Makefile Normal file
View File

@ -0,0 +1,15 @@
IMAGE_NAME=unshortener-api
CONTAINER_NAME=unshortener
CONTAINER_PORT=8000
build:
docker build -t $(IMAGE_NAME) .
run:
docker run --name $(CONTAINER_NAME) -d -p $(CONTAINER_PORT):8000 $(IMAGE_NAME)
stop:
docker stop $(CONTAINER_NAME)
clean:
docker rm $(CONTAINER_NAME)
clean-image:
docker rmi $(IMAGE_NAME)

View File

@ -1,2 +1,14 @@
# Unshorten Server # Unshortener Resolver API
Simple FastAPI app to unshorten URLs. Simple FastAPI app to resolve links behind shortened URLs.
**Supported sites**:
- t.co
- tinyurl.com
## Usage
Build and run the Docker container:
```shell
make build
docker -d --name unshortener -p 8000:8000 unshortener-api
```

View File

@ -3,12 +3,15 @@ from typing import Optional
from urllib.parse import urlparse from urllib.parse import urlparse
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from unshorteners import unshorten_twitter from unshorteners import unshorten_twitter, unshorten_tinyurl
UNSHORTENERS = { UNSHORTEN = {
't.co': unshorten_twitter 't.co': unshorten_twitter,
'tinyurl.com': unshorten_tinyurl
} }
CACHE = {}
app = FastAPI(docs_url=None, redoc_url=None) app = FastAPI(docs_url=None, redoc_url=None)
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
@ -26,7 +29,15 @@ async def receive_url(url: Optional[str] = None):
return {"error": "no url provided"} return {"error": "no url provided"}
domain = urlparse(url).netloc domain = urlparse(url).netloc
if domain not in UNSHORTENERS: if domain not in UNSHORTEN:
return {"error": f"cannot unshorten {domain}"} return {"error": f"cannot unshorten {domain}"}
return UNSHORTENERS[domain](url) if url in CACHE:
return CACHE[url]
result = UNSHORTEN[domain](url)
if result:
CACHE[url] = result
return result
return {"error": "server error"}

View File

@ -1,12 +1,27 @@
"""Unshortening functions""" """Unshortening functions"""
import re import re
from typing import Optional
import requests import requests
def unshorten_twitter(url): def unshorten_tinyurl(url: str) -> Optional[str]:
"""Retrieve the actual URL behind a TinyURL."""
try:
response = requests.get(url, timeout=4, allow_redirects=False)
except requests.RequestException:
return None
if response.status_code == 301:
return response.headers.get("location", None)
return None
def unshorten_twitter(url: str) -> Optional[str]:
"""Retrieve the actual URL behind a Twitter URL.""" """Retrieve the actual URL behind a Twitter URL."""
pattern = re.compile(r"<title>(.*?)<\/title>") pattern = re.compile(r"<title>(.*?)<\/title>")
try:
response = requests.get( response = requests.get(
url=url, url=url,
headers={ headers={
@ -14,6 +29,8 @@ def unshorten_twitter(url):
}, },
timeout=4 timeout=4
) )
except requests.RequestException:
return None
match = pattern.search(response.text) match = pattern.search(response.text)
if match: if match: