66This script reads lines from stdin or files named as arguments, then:
77
881. retrieves or creates new short URLs, taking into account existing RedirectTemp
9- directives in custom.htacess or short.htacess ;
10- 2. appends RedirectTemp directives for newly created short URLs to short.htacess ;
9+ directives in custom.htaccess or short.htaccess ;
10+ 2. appends RedirectTemp directives for newly created short URLs to short.htaccess ;
11113. outputs the list of (short, long) URLs retrieved or created.
1212
1313"""
1717from collections .abc import Iterator
1818from time import strftime
1919
20+ HTACCESS_CUSTOM = 'custom.htaccess'
21+ HTACCESS_SHORT = 'short.htaccess'
22+ HTACCESS_FILES = (HTACCESS_CUSTOM , HTACCESS_SHORT )
2023BASE_DOMAIN = 'fpy.li'
2124
22- def load_redirects ():
25+ 26+ def load_redirects () -> tuple [dict , dict ]:
2327 redirects = {}
2428 targets = {}
25- for filename in ( 'custom.htaccess' , 'short.htaccess' ) :
29+ for filename in HTACCESS_FILES :
2630 with open (filename ) as fp :
2731 for line in fp :
2832 if line .startswith ('RedirectTemp' ):
2933 _ , short , long = line .split ()
3034 short = short [1 :] # Remove leading slash
31- assert short not in redirects , f" { filename } : duplicate redirect from { short } "
32- # custom is live since 2022, we cannot change it remove duplicate targets
33- if not filename . startswith ( 'custom' ) :
34- assert long not in targets , f" { filename } : Duplicate redirect to { long } "
35+ assert short not in redirects , f' { filename } : duplicate redirect from { short } '
36+ # htaccess. custom is live since 2022, we can't change it remove duplicate targets
37+ if filename != HTACCESS_CUSTOM :
38+ assert long not in targets , f' { filename } : duplicate redirect to { long } '
3539 redirects [short ] = long
3640 targets [long ] = short
3741 return redirects , targets
@@ -41,9 +45,7 @@ def load_redirects():
4145
4246
4347def gen_short (start_len = 1 ) -> Iterator [str ]:
44- """
45- Generate every possible sequence of SDIGITS, starting with start_len
46- """
48+ """Generate every possible sequence of SDIGITS, starting with start_len"""
4749 length = start_len
4850 while True :
4951 for short in itertools .product (SDIGITS , repeat = length ):
@@ -52,22 +54,20 @@ def gen_short(start_len=1) -> Iterator[str]:
5254
5355
5456def gen_unused_short (redirects : dict ) -> Iterator [str ]:
55- """
56- Generate next available short URL of len >= 2.
57- """
57+ """Generate next available short URL of len >= 2."""
5858 for short in gen_short (2 ):
5959 if short not in redirects :
6060 yield short
6161
6262
63- def shorten (urls : list [str ], redirects : dict , targets : dict ) -> list [tuple [str ,str ]]:
64- """return (short, long) pairs, appending directives to short.htaccess as needed"""
63+ def shorten (urls : list [str ], redirects : dict , targets : dict ) -> list [tuple [str ,str ]]:
64+ """Return (short, long) pairs, appending directives to HTACCESS_SHORT as needed. """
6565 iter_short = gen_unused_short (redirects )
6666 pairs = []
6767 timestamp = strftime ('%Y-%m-%d %H:%M:%S' )
68- with open ('short.htaccess' , 'a' ) as fp :
68+ with open (HTACCESS_SHORT , 'a' ) as fp :
6969 for long in urls :
70- assert BASE_DOMAIN not in long , f" { long } is a { BASE_DOMAIN } URL"
70+ assert BASE_DOMAIN not in long , f' { long } is a { BASE_DOMAIN } URL'
7171 if long in targets :
7272 short = targets [long ]
7373 else :
@@ -79,16 +79,16 @@ def shorten(urls: list[str], redirects: dict, targets: dict) -> list[tuple[str,s
7979 timestamp = None
8080 fp .write (f'RedirectTemp /{ short } { long } \n ' )
8181 pairs .append ((short , long ))
82-
82+ 8383 return pairs
8484
8585
86- def main ():
86+ def main ()-> None :
8787 """read URLS from filename arguments or stdin"""
88- urls = [line .strip () for line in fileinput .input (encoding = " utf-8" )]
88+ urls = [line .strip () for line in fileinput .input (encoding = ' utf-8' )]
8989 redirects , targets = load_redirects ()
9090 for short , long in shorten (urls , redirects , targets ):
91- print (f'{ BASE_DOMAIN } /{ short } \t { long } ' )
91+ print (f'{ BASE_DOMAIN } /{ short } \t { long } ' )
9292
9393
9494if __name__ == '__main__' :
0 commit comments