Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
f167669bc4 | |||
0187f66627 | |||
7b8a6a34fe | |||
b9e3591299 | |||
73a80f6d3d | |||
e5b701aa55 | |||
9afc7b1298 | |||
a655b3b02e | |||
ca2c990002 | |||
8563addf49 | |||
c8539af605 | |||
4962cc0920 | |||
f69f32c438 | |||
e8ccfbb80a | |||
4296afee69 | |||
4d01e8812d | |||
cf852fa14f |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
.idea
|
.idea
|
||||||
venv
|
venv
|
||||||
|
|
||||||
|
extension/build
|
||||||
|
|
||||||
__pycache__
|
__pycache__
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
|
||||||
|
26
README.md
26
README.md
@ -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
|
||||||
|
```
|
@ -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)
|
||||||
|
|
||||||
|
@ -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.
@ -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)});
|
||||||
}
|
}
|
@ -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
15
server/Makefile
Normal 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)
|
@ -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
|
||||||
|
```
|
@ -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"}
|
||||||
|
@ -1,19 +1,36 @@
|
|||||||
"""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>")
|
||||||
|
|
||||||
response = requests.get(
|
try:
|
||||||
url=url,
|
response = requests.get(
|
||||||
headers={
|
url=url,
|
||||||
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0"
|
headers={
|
||||||
},
|
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0"
|
||||||
timeout=4
|
},
|
||||||
)
|
timeout=4
|
||||||
|
)
|
||||||
|
except requests.RequestException:
|
||||||
|
return None
|
||||||
|
|
||||||
match = pattern.search(response.text)
|
match = pattern.search(response.text)
|
||||||
if match:
|
if match:
|
||||||
|
Loading…
Reference in New Issue
Block a user