Compare commits
3 Commits
ffcdeedbc9
...
dce0da91b2
Author | SHA1 | Date |
---|---|---|
Ceda EI | dce0da91b2 | |
Ceda EI | 9137953537 | |
Ceda EI | 79ef6da558 |
|
@ -2,16 +2,21 @@
|
|||
"Creates a firefox web app"
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import shlex
|
||||
import stat
|
||||
import sys
|
||||
import os
|
||||
import os.path as pt
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
from collections import Counter
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from PIL import Image
|
||||
|
||||
|
||||
REPO_DIR = pt.dirname(sys.argv[0])
|
||||
REPO_DIR = pt.abspath(pt.dirname(sys.argv[0]))
|
||||
BIN_DIR = f"{REPO_DIR}/bin"
|
||||
ICON_DIR = f"{REPO_DIR}/icons"
|
||||
|
||||
|
@ -37,6 +42,40 @@ def absolute_url(base_url, relative_url):
|
|||
return relative_url
|
||||
|
||||
|
||||
# pylint: disable=W0613
|
||||
def create_webapp(name, url, exec_name, logo, profile):
|
||||
"Creates the necessary files for the webapp."
|
||||
local_vars = locals()
|
||||
# Create a dictionary with shell-quoted version of arguments
|
||||
quoted = {i: shlex.quote(local_vars[i]) for i in ("name", "url", "exec_name",
|
||||
"logo", "profile")}
|
||||
# Download and convert the logo
|
||||
logo_pt = f"{ICON_DIR}/{exec_name}.png"
|
||||
res = requests.get(logo, allow_redirects=True)
|
||||
with Image.open(io.BytesIO(res.content)) as img:
|
||||
img.save(logo_pt, "PNG")
|
||||
|
||||
# Create the binary
|
||||
script_pt = f"{BIN_DIR}/{exec_name}"
|
||||
with open(script_pt, "w") as script:
|
||||
script.write("#!/usr/bin/env sh\n")
|
||||
script.write(f"firefox --profile {quoted['profile']} {quoted['url']}\n")
|
||||
os.chmod(script_pt, os.stat(script_pt).st_mode | stat.S_IXUSR | stat.S_IXGRP)
|
||||
|
||||
# Create the desktop file
|
||||
desk_pt = pt.expanduser(f"~/.local/share/applications/{exec_name}.desktop")
|
||||
with open(desk_pt, "w") as desktop:
|
||||
desktop.write(f"""
|
||||
[Desktop Entry]
|
||||
Name={name} (Web App)
|
||||
Exec={script_pt}
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon={logo_pt}
|
||||
Categories=Network;X-WebApps
|
||||
""".strip() + "\n")
|
||||
|
||||
|
||||
def extract_metadata(url):
|
||||
"Extract metadata using bs4"
|
||||
# Get and parse the page
|
||||
|
@ -45,7 +84,9 @@ def extract_metadata(url):
|
|||
metadata = {}
|
||||
|
||||
# Find the title
|
||||
titles = [soup.title.string]
|
||||
titles = []
|
||||
if soup.title:
|
||||
titles = [soup.title.string]
|
||||
for tag in soup.find_all("meta"):
|
||||
title_props = ["title", "og:title", "twitter:title"]
|
||||
if tag.get("property", None) in title_props \
|
||||
|
@ -53,11 +94,16 @@ def extract_metadata(url):
|
|||
titles.append(tag["content"])
|
||||
# Set title to the most common if it occurs more than once, else prefer
|
||||
# title tag
|
||||
most_common = Counter(titles).most_common(1)[0]
|
||||
if most_common[1] > 1:
|
||||
metadata["title"] = most_common[0].strip()
|
||||
most_common = Counter(titles).most_common(1)
|
||||
if not most_common:
|
||||
metadata["title"] = None
|
||||
elif most_common[0][1] > 1:
|
||||
metadata["title"] = most_common[0][0].strip()
|
||||
else:
|
||||
metadata["title"] = soup.title.string.strip()
|
||||
if soup.title:
|
||||
metadata["title"] = soup.title.string.strip()
|
||||
else:
|
||||
metadata["title"] = most_common[0][0].strip()
|
||||
|
||||
# Find the image.
|
||||
# Try link first, followed by /favicon.{png,ico}, followed by og:, twitter:
|
||||
|
@ -121,6 +167,7 @@ def main():
|
|||
eprint(f"Maybe you meant https://{args.url} ?")
|
||||
sys.exit(1)
|
||||
|
||||
print("Fetching details ...")
|
||||
metadata = extract_metadata(args.url)
|
||||
if not args.name:
|
||||
args.name = metadata["title"]
|
||||
|
@ -146,6 +193,13 @@ def main():
|
|||
print(f"Logo URL:\t\t{args.logo}")
|
||||
print(f"Executable Name:\t{args.exec_name}")
|
||||
print(f"Firefox Profile:\t{args.firefox_profile}")
|
||||
print()
|
||||
print("Do you want to create the app with the above details (Y/n): ",
|
||||
end=' ')
|
||||
inp = input()
|
||||
if not inp or inp[0].upper() != "N":
|
||||
create_webapp(args.name, args.url, args.exec_name, args.logo,
|
||||
args.firefox_profile)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
8
setup.sh
8
setup.sh
|
@ -75,7 +75,7 @@ if [[ $FIREFOX_PROFILE == "" ]] || (( NEW == 1 )); then
|
|||
echo -n "Use an existing profile for apps? (y/N): "
|
||||
read -r input
|
||||
if [[ ${input^^} == "Y" ]]; then
|
||||
echo "Enter path to existing profile (or run the script with --firefox_profile): "
|
||||
echo -n "Enter path to existing profile (or run the script with --firefox_profile): "
|
||||
read -r FIREFOX_PROFILE
|
||||
else
|
||||
NEW=1
|
||||
|
@ -113,13 +113,13 @@ read -r
|
|||
|
||||
mkdir "$FIREFOX_PROFILE/chrome" &> /dev/null || true
|
||||
HIDDEN_SELECTORS=()
|
||||
echo -e "Do you want to hide tabs? (y/N)"
|
||||
echo -n "Do you want to hide tabs? (y/N) "
|
||||
read -r input
|
||||
if [[ ${input^^} == "Y" ]]; then
|
||||
HIDDEN_SELECTORS=("${HIDDEN_SELECTORS[@]}" "#tabbrowser-tabs")
|
||||
fi
|
||||
|
||||
echo -e "Do you want to hide main toolbar (address bar, back, forward, etc)? (y/N)"
|
||||
echo -n "Do you want to hide main toolbar (address bar, back, forward, etc)? (y/N) "
|
||||
read -r input
|
||||
if [[ ${input^^} == "Y" ]]; then
|
||||
HIDDEN_SELECTORS=("${HIDDEN_SELECTORS[@]}" "#nav-bar")
|
||||
|
@ -137,3 +137,5 @@ if (( ${#HIDDEN_SELECTORS[@]} > 0 )); then
|
|||
visibility: collapse !important;
|
||||
}" >> "$FIREFOX_PROFILE/chrome/userChrome.css"
|
||||
fi
|
||||
|
||||
echo "Optional: Add $(cd "$ICON_DIR"; pwd) to your PATH to allowing launching the app from command line"
|
||||
|
|
Loading…
Reference in New Issue