Compare commits

..

No commits in common. "master" and "0.2" have entirely different histories.
master ... 0.2

7 changed files with 26 additions and 94 deletions

View File

@ -1,24 +1,2 @@
# Unshortener # Unshorten
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

@ -1,14 +1,2 @@
# Unshortener Extension # Unshorten
A Firefox extension to reveal links behind URL shorteners like Twitter and TinyURL. A Firefox extension to unshorten links from sites like Twitter.
**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
```

View File

@ -1,6 +1,5 @@
const shortenerDomains = [ const shortenerDomains = [
"t.co", "t.co"
"tinyurl.com"
]; ];
browser.contextMenus.create({ browser.contextMenus.create({
@ -32,14 +31,13 @@ function unshortenUrl(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("Couldn't unshorten URL: " + res.statusText); console.log("error fetching result");
} }
return res.json(); return res.json();
}) })
.then(unshortenedUrl => { .then(unshortenedUrl => {
console.log("unshortened: " + unshortenedUrl) console.log("unshortened: " + unshortenedUrl)
navigator.clipboard.writeText(unshortenedUrl) navigator.clipboard.writeText(unshortenedUrl)
.catch(err => console.error("Couldn't copy to clipboard: ", err)); .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": "Unshortener", "name": "Unshortener",
"version": "0.3", "version": "0.2",
"description": "Unshorten links from Twitter.", "description": "Unshorten links from Twitter.",

View File

@ -1,14 +1,2 @@
# Unshortener Resolver API # Unshorten Server
Simple FastAPI app to resolve links behind shortened URLs. Simple FastAPI app to unshorten 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,11 +3,10 @@ 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, unshorten_tinyurl from unshorteners import unshorten_twitter
UNSHORTEN = { UNSHORTEN = {
't.co': unshorten_twitter, 't.co': unshorten_twitter
'tinyurl.com': unshorten_tinyurl
} }
CACHE = {} CACHE = {}
@ -33,11 +32,9 @@ async def receive_url(url: Optional[str] = None):
return {"error": f"cannot unshorten {domain}"} return {"error": f"cannot unshorten {domain}"}
if url in CACHE: if url in CACHE:
return CACHE[url] unshortened = CACHE[url]
else:
unshortened = UNSHORTEN[domain](url)
CACHE[url] = unshortened
result = UNSHORTEN[domain](url) return unshortened
if result:
CACHE[url] = result
return result
return {"error": "server error"}

View File

@ -1,27 +1,12 @@
"""Unshortening functions""" """Unshortening functions"""
import re import re
from typing import Optional
import requests import requests
def unshorten_tinyurl(url: str) -> Optional[str]: def unshorten_twitter(url: 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={
@ -29,8 +14,6 @@ def unshorten_twitter(url: str) -> Optional[str]:
}, },
timeout=4 timeout=4
) )
except requests.RequestException:
return None
match = pattern.search(response.text) match = pattern.search(response.text)
if match: if match: