/home/alex/dev/shorten-url.py (1)

From RaySoft
#!/usr/bin/env python3
# ------------------------------------------------------------------------------
# shorten-url.py
# ==============
#
# Scope     Native
# Copyright (C) 2024 by RaySoft, Zurich, Switzerland
# License   GNU General Public License (GPL) 2.0
#           https://www.gnu.org/licenses/gpl2.txt
#
# ------------------------------------------------------------------------------

BITLY_QUERY_URL = 'https://bit.ly/'
BITLY_POST_URL = 'https://api-ssl.bitly.com/v4/shorten'
BITLY_API_KEY = '******************************'

# ------------------------------------------------------------------------------

PROGRAM_NAME = 'shorten-url'
PROGRAM_VERSION = '0.3'

# ------------------------------------------------------------------------------

from argparse import ArgumentParser, FileType
from itertools import chain
from json import loads
from re import compile
from sys import exit, stderr
import urllib.error
from urllib.parse import quote_plus
from urllib.request import urlopen

# ------------------------------------------------------------------------------

def main():
    parser = ArgumentParser(
        description=f'Shorten URLs with Bitly URL shortener ({BITLY_QUERY_URL})',
        prog=PROGRAM_NAME,
    )
    parser.add_argument(
        '-V', '--version', action='version',
        version=f'%(prog)s {PROGRAM_VERSION}',
    )
    parser.add_argument(
        '-n', '--nobr', action='store_true',
        help='print the output without a line break',
    )
    group1 = parser.add_mutually_exclusive_group(required=True)
    group1.add_argument(
        '-u', '--url', metavar='URL', action='append', nargs='+',
        help='Read URL(s) from command line',
    )
    group1.add_argument(
        '-f', '--file', metavar='FILE', action='append', nargs='+',
        type=FileType(mode='r', encoding='UTF-8'),
        help='Read URL(s) from a file(s). Use a dash (-) to read from stdin',
    )

    args = parser.parse_args()

    urls = []

    if args.url and len(args.url) > 0:
        urls = list(chain.from_iterable(args.url))
    elif args.file and len(args.file) > 0:
        files = list(chain.from_iterable(args.file))

        for file in files:
            for line in file.readlines():
                urls.append(line.strip())

    url_regex = compile(
        r'^https?://'
        r'(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+'
        r'(?:[a-z]{2,6}\.?|[a-z0-9-]{2,}\.?)'
        r'(?::\d+)?'
        r'(?:/?|[/?]\S+)$'
    )

    headers = {
        'Authorization': f'Bearer {BITLY_API_KEY}',
        'Content-Type': 'application/json',
    }

    for url in urls:
        url.lower()

        if not url_regex.match(url):
            print(f'{PROGRAM_NAME}: error', file=stderr)
            return 1

        req = urllib.request.Request(
            BITLY_POST_URL, data=f'{{ "long_url": "{url}" }}'.encode(),
            headers=headers,
        )

        with urlopen(req) as response:
            obj = response.read().decode('utf-8')

        end = '\n'

        if args.nobr:
            end = ''

        print(loads(obj)['link'], end=end)

    return 0

# ------------------------------------------------------------------------------

if __name__ == '__main__':
    return_value = main()

    exit(return_value)

Usage

~/dev/shorten-url --url='https://www.rpl.ch' --url='https://www.raysoft.ch'
~/dev/shorten-url --file=- <<<'https://www.raysoft.ch'
echo 'https://www.raysoft.ch' | ~/dev/shorten-url --file=-
~/dev/shorten-url --file="${HOME}/tmp/urls-1.txt" --file="${HOME}/tmp/urls-2.txt"
cat "${HOME}/tmp/urls-1.txt" "${HOME}/tmp/urls-2.txt" | ~/dev/shorten-url --file=-