create_gallery_index.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #!/usr/bin/python3
  2. import logging
  3. import os
  4. from os import listdir
  5. from os.path import isdir, isfile, join
  6. import re
  7. from string import Template
  8. import sys
  9. import traceback
  10. #import Image
  11. from configparser import ConfigParser
  12. from optparse import OptionParser
  13. __all__ = []
  14. __version__ = 0.1
  15. __date__ = '2021-12-27'
  16. __updated__ = '2021-12-27'
  17. DEBUG = 1
  18. TESTRUN = 0
  19. PROFILE = 0
  20. html = Template("""<html>
  21. <head>
  22. <script src="/res/js/jquery.min.js"></script>
  23. <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  24. <link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lightgallery@2.0.0-beta.3/css/lightgallery-bundle.css" />
  25. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  26. <link type="text/css" rel="stylesheet" href="/res/user.css" />
  27. <link type="text/css" rel="stylesheet" href="/res/galleryindex.css" />
  28. </head>
  29. <body class="index">
  30. <div id="header" class="index">
  31. <h1>$title</h1>
  32. <div class="searchcontainer">
  33. <form role="form">
  34. <div class="form-group">
  35. <input type="input" class="form-control input-lg" id="txt-search" placeholder="Suchbegriff eingeben">
  36. </div>
  37. </form>
  38. </div>
  39. </div><!-- end header -->
  40. <div id="outer_lightgallery">
  41. <ul class="nav nav-tabs" id="myTab" role="tablist">
  42. <li class="nav-item">
  43. <a class="nav-link active" id="lightgallery-tab" data-toggle="tab" href="#lightgallery" role="tab" aria-controls="lightgallery" aria-selected="true">Alle Galerien</a>
  44. </li>
  45. <li class="nav-item">
  46. <a class="nav-link" id="filters-tab" data-toggle="tab" href="#filters" role="tab" aria-controls="filters" aria-selected="false">Filter</a>
  47. </li>
  48. <li class="nav-item">
  49. <a class="nav-link" id="results-tab" data-toggle="tab" href="#results" role="tab" aria-controls="results" aria-selected="false">Filter-Ergebnisse</a>
  50. </li>
  51. </ul>
  52. <div class="tab-content" id="myTabContent">
  53. <div class="tab-pane fade active index" id="lightgallery" role="tabpanel" aria-labelledby="lightgallery-tab">
  54. $dirlist
  55. </div>
  56. <div class="tab-pane fade" id="filters" role="tabpanel" aria-labelledby="filters-tab"><div style="padding:5em;">Zum Filtern bitte einen Suchbegriff in das Suchfeld eingeben.</div></div>
  57. <div class="tab-pane fade" id="results" role="tabpanel" aria-labelledby="results-tab"><div style="padding:5em;">Es gibt noch keine Filter-Ergebnisse</div></div>
  58. </div>
  59. </div>
  60. <script src="headerimages.js"></script>
  61. <script>
  62. function choosePic() {
  63. var randomNum = Math.floor(Math.random() * myPix.length);
  64. document.getElementById("header").style.backgroundImage = "url('" + myPix[randomNum] + "')";
  65. }
  66. function gallery_startup() {
  67. choosePic();
  68. $$('#myTab li:first-child a').tab('show')
  69. }
  70. window.onload = gallery_startup();
  71. </script>
  72. <script src="/res/js/lightgallery.min.js"></script>
  73. <script src="/res/plugins/relativeCaption/lg-relative-caption.min.js"></script>
  74. <script src="/res/plugins/fullscreen/lg-fullscreen.min.js"></script>
  75. <script src="/res/plugins/autoplay/lg-autoplay.min.js"></script>
  76. <script src="/res/plugins/thumbnail/lg-thumbnail.min.js"></script>
  77. <script src="/res/plugins/zoom/lg-zoom.min.js"></script>
  78. <script src="searchdata.js"></script>
  79. <script src="/res/lightgallery_search.js"></script>
  80. </body>
  81. </html>""")
  82. def maketitle(x):
  83. x = str(x)
  84. x = re.sub('^\d\d\d_', '', x)
  85. x = re.sub('_', ' ', x)
  86. return x
  87. def remove_prefix(text, prefix):
  88. return text[text.startswith(prefix) and len(prefix):]
  89. def getthumb(gallerydir, webrootdir):
  90. thumb = ''
  91. try:
  92. for f in listdir(join(gallerydir, '_thumbnails')):
  93. # print(f)
  94. thumbfile = join(gallerydir, '_thumbnails', f)
  95. if isfile(thumbfile):
  96. if str(f).lower().endswith('jpg'):
  97. thumb = remove_prefix(join(gallerydir, '_thumbnails', f), webrootdir)
  98. break
  99. except:
  100. pass
  101. return(thumb)
  102. def get_headerimage(gallerydir, webrootdir):
  103. print(gallerydir)
  104. return(remove_prefix(join(gallerydir, 'header/header.jpg'), webrootdir))
  105. def get_directories_in_gallerydir(gallerydir):
  106. onlydirs = []
  107. for f in listdir(gallerydir):
  108. if isdir(join(gallerydir, f)):
  109. if str(f) != '_thumbnails':
  110. onlydirs.append(f)
  111. onlydirs.sort()
  112. return(onlydirs)
  113. def read_config(opts):
  114. try:
  115. config_object = ConfigParser()
  116. config_object.read( "." + os.path.splitext(os.path.basename(__file__))[0] )
  117. ini = dict(config_object.items('default'))
  118. for key in ini:
  119. if not opts.__dict__[key]:
  120. opts.__dict__[key] = ini[key]
  121. except:
  122. pass
  123. def write_config(opts):
  124. ini = {}
  125. for key in opts.__dict__:
  126. value = opts.__dict__[key]
  127. if value is None:
  128. pass
  129. elif key == 'verbose':
  130. pass
  131. else:
  132. ini[key] = str(value)
  133. config_object = ConfigParser()
  134. config_object.read_dict({'default' : ini})
  135. with open("." + os.path.splitext(os.path.basename(__file__))[0], 'w') as conf:
  136. config_object.write(conf)
  137. def create_index_html(gallerydir, opts):
  138. read_config(opts)
  139. logging.info(f"Creating index in {gallerydir}")
  140. dirs = get_directories_in_gallerydir(gallerydir)
  141. logging.info(dirs)
  142. dirlist = ''
  143. headerimages = ''
  144. for d in dirs:
  145. headerimages = headerimages + '","' + get_headerimage(join(gallerydir,d), opts.webrootdir)
  146. thumb = getthumb(join(gallerydir,d), opts.webrootdir)
  147. print(thumb)
  148. # dirlist = dirlist + f"<div class='direntry'><a href='{d}'><img src='{thumb}'>&nbsp;" + maketitle(d) + "</a></div>\n"
  149. dirlist = dirlist + f"<div class='img-wrapper'><img src='{thumb}'><div class='p'><a href='{d}'>" + maketitle(d) + "</a></div></div>\n"
  150. #print(dirlist)
  151. headerimages = re.sub('^",', '', headerimages)
  152. with open(join(gallerydir, 'headerimages.js'), 'w') as e:
  153. e.write('var myPix = new Array(' + headerimages + '");')
  154. title = opts.title or os.path.basename(os.path.normpath(os.getcwd()))
  155. with open(join(gallerydir, 'index.html'), 'w') as f:
  156. dirlist2 = dirlist
  157. f.write(html.substitute( dirlist=dirlist2, title=title ))
  158. write_config(opts)
  159. def main(argv=None):
  160. '''Command line options.'''
  161. program_name = os.path.basename(sys.argv[0])
  162. program_version = "v0.1"
  163. program_build_date = "%s" % __updated__
  164. program_version_string = '%%prog %s (%s)' % (program_version, program_build_date)
  165. #program_usage = '''usage: spam two eggs''' # optional - will be autogenerated by optparse
  166. program_longdesc = '''create index for directory of lightgallery galleries''' # optional - give further explanation about what the program does
  167. program_license = "Copyright 2021 Markus Spring (markus-spring.info). \
  168. Licensed under the Apache License 2.0\nhttp://www.apache.org/licenses/LICENSE-2.0"
  169. if argv is None:
  170. argv = sys.argv[1:]
  171. try:
  172. # setup option parser
  173. parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
  174. # parser.add_option("-i", "--in", dest="infile", help="set input path [default: %default]", metavar="FILE")
  175. # parser.add_option("-o", "--out", dest="outfile", help="set output path [default: %default]", metavar="FILE")
  176. parser.add_option("-v", "--verbose", dest="verbose", action="count", help="set verbosity level [default: %default]")
  177. parser.add_option("-t", "--title", action="store", dest="title", help="set index title [default: %default]")
  178. parser.add_option("-w", "--webrootdir", action="store", dest="webrootdir", help="webserver root dir [default: %default]")
  179. parser.set_defaults( verbose=0)
  180. (opts, args) = parser.parse_args(argv)
  181. if opts.verbose > 0:
  182. print(("verbosity level = %d" % opts.verbose))
  183. if opts.title:
  184. print(("title = %s" % opts.title))
  185. if len(args) < 1:
  186. parser.error("directory argument missing")
  187. # MAIN BODY #
  188. logging.basicConfig(filename=os.path.basename(sys.argv[0]) + '.log', level=logging.INFO)
  189. create_index_html(args[0], opts)
  190. except BaseException as ex:
  191. ex_type, ex_value, ex_traceback = sys.exc_info() # Get current system exception
  192. trace_back = traceback.extract_tb(ex_traceback) # Extract unformatter stack traces as tuples
  193. stack_trace = list() # Format stacktrace
  194. for trace in trace_back:
  195. stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))
  196. print("Exception type : %s " % ex_type.__name__)
  197. print("Exception message : %s" %ex_value)
  198. print("Stack trace : %s" %stack_trace)
  199. if __name__ == "__main__":
  200. if DEBUG:
  201. sys.argv.append("-v")
  202. if TESTRUN:
  203. import doctest
  204. doctest.testmod()
  205. if PROFILE:
  206. import cProfile
  207. import pstats
  208. profile_filename = 'config_reader.config_reader_profile.txt'
  209. cProfile.run('main()', profile_filename)
  210. statsfile = open("profile_stats.txt", "wb")
  211. p = pstats.Stats(profile_filename, stream=statsfile)
  212. stats = p.strip_dirs().sort_stats('cumulative')
  213. stats.print_stats()
  214. statsfile.close()
  215. sys.exit(0)
  216. sys.exit(main())
  217. #Local Variables:
  218. #compile-command: "./create_gallery_index.py -t 'Dias Ed Spring 1958-1998' /media/thinc_webserver_data/vaters_dias/"
  219. #End: