| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  | __filename__ = "webapp_media.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2021-01-26 10:07:42 +00:00
										 |  |  | __version__ = "1.2.0" | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-26 11:27:14 +00:00
										 |  |  | __module_group__ = "Timeline" | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 10:18:34 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  | from utils import validUrlPrefix | 
					
						
							| 
									
										
										
										
											2020-12-24 10:18:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def loadPeertubeInstances(baseDir: str, peertubeInstances: []) -> None: | 
					
						
							|  |  |  |     """Loads peertube instances from file into the given list
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     peertubeList = None | 
					
						
							|  |  |  |     peertubeInstancesFilename = baseDir + '/accounts/peertube.txt' | 
					
						
							|  |  |  |     if os.path.isfile(peertubeInstancesFilename): | 
					
						
							|  |  |  |         with open(peertubeInstancesFilename, 'r') as fp: | 
					
						
							|  |  |  |             peertubeStr = fp.read() | 
					
						
							|  |  |  |             if peertubeStr: | 
					
						
							|  |  |  |                 peertubeStr = peertubeStr.replace('\r', '') | 
					
						
							|  |  |  |                 peertubeList = peertubeStr.split('\n') | 
					
						
							| 
									
										
										
										
											2020-12-24 11:42:23 +00:00
										 |  |  |     if not peertubeList: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     for url in peertubeList: | 
					
						
							|  |  |  |         if url in peertubeInstances: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         peertubeInstances.append(url) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _addEmbeddedVideoFromSites(translate: {}, content: str, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                                peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2021-07-13 15:49:29 +00:00
										 |  |  |                                width: int = 400, height: int = 300) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     """Adds embedded videos
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if '>vimeo.com/' in content: | 
					
						
							|  |  |  |         url = content.split('>vimeo.com/')[1] | 
					
						
							|  |  |  |         if '<' in url: | 
					
						
							|  |  |  |             url = url.split('<')[0] | 
					
						
							|  |  |  |             content = \ | 
					
						
							|  |  |  |                 content + "<center>\n<iframe loading=\"lazy\" " + \ | 
					
						
							|  |  |  |                 "src=\"https://player.vimeo.com/video/" + \ | 
					
						
							|  |  |  |                 url + "\" width=\"" + str(width) + \ | 
					
						
							|  |  |  |                 "\" height=\"" + str(height) + \ | 
					
						
							|  |  |  |                 "\" frameborder=\"0\" allow=\"autoplay; " + \ | 
					
						
							|  |  |  |                 "fullscreen\" allowfullscreen></iframe>\n</center>\n" | 
					
						
							|  |  |  |             return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     videoSite = 'https://www.youtube.com' | 
					
						
							|  |  |  |     if '"' + videoSite in content: | 
					
						
							|  |  |  |         url = content.split('"' + videoSite)[1] | 
					
						
							|  |  |  |         if '"' in url: | 
					
						
							|  |  |  |             url = url.split('"')[0].replace('/watch?v=', '/embed/') | 
					
						
							|  |  |  |             if '&' in url: | 
					
						
							|  |  |  |                 url = url.split('&')[0] | 
					
						
							| 
									
										
										
										
											2021-01-14 09:38:51 +00:00
										 |  |  |             if '?utm_' in url: | 
					
						
							|  |  |  |                 url = url.split('?utm_')[0] | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |             content = \ | 
					
						
							|  |  |  |                 content + "<center>\n<iframe loading=\"lazy\" src=\"" + \ | 
					
						
							|  |  |  |                 videoSite + url + "\" width=\"" + str(width) + \ | 
					
						
							|  |  |  |                 "\" height=\"" + str(height) + \ | 
					
						
							|  |  |  |                 "\" frameborder=\"0\" allow=\"autoplay; fullscreen\" " + \ | 
					
						
							|  |  |  |                 "allowfullscreen></iframe>\n</center>\n" | 
					
						
							|  |  |  |             return content | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-23 22:48:19 +00:00
										 |  |  |     invidiousSites = ('https://invidious.snopyta.org', | 
					
						
							| 
									
										
										
										
											2020-12-23 22:50:21 +00:00
										 |  |  |                       'https://yewtu.be', | 
					
						
							|  |  |  |                       'https://tube.connect.cafe', | 
					
						
							|  |  |  |                       'https://invidious.kavin.rocks', | 
					
						
							|  |  |  |                       'https://invidiou.site', | 
					
						
							|  |  |  |                       'https://invidious.tube', | 
					
						
							|  |  |  |                       'https://invidious.xyz', | 
					
						
							|  |  |  |                       'https://invidious.zapashcanon.fr', | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |                       'http://c7hqkpkpemu6e7emz5b4vy' + | 
					
						
							|  |  |  |                       'z7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion', | 
					
						
							|  |  |  |                       'http://axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4' + | 
					
						
							|  |  |  |                       'bzzsg2ii4fv2iid.onion') | 
					
						
							|  |  |  |     for videoSite in invidiousSites: | 
					
						
							|  |  |  |         if '"' + videoSite in content: | 
					
						
							|  |  |  |             url = content.split('"' + videoSite)[1] | 
					
						
							|  |  |  |             if '"' in url: | 
					
						
							|  |  |  |                 url = url.split('"')[0].replace('/watch?v=', '/embed/') | 
					
						
							|  |  |  |                 if '&' in url: | 
					
						
							|  |  |  |                     url = url.split('&')[0] | 
					
						
							| 
									
										
										
										
											2021-01-14 09:38:51 +00:00
										 |  |  |                 if '?utm_' in url: | 
					
						
							|  |  |  |                     url = url.split('?utm_')[0] | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |                 content = \ | 
					
						
							|  |  |  |                     content + "<center>\n<iframe loading=\"lazy\" src=\"" + \ | 
					
						
							|  |  |  |                     videoSite + url + "\" width=\"" + \ | 
					
						
							|  |  |  |                     str(width) + "\" height=\"" + str(height) + \ | 
					
						
							|  |  |  |                     "\" frameborder=\"0\" allow=\"autoplay; fullscreen\" " + \ | 
					
						
							|  |  |  |                     "allowfullscreen></iframe>\n</center>\n" | 
					
						
							|  |  |  |                 return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     videoSite = 'https://media.ccc.de' | 
					
						
							|  |  |  |     if '"' + videoSite in content: | 
					
						
							|  |  |  |         url = content.split('"' + videoSite)[1] | 
					
						
							|  |  |  |         if '"' in url: | 
					
						
							|  |  |  |             url = url.split('"')[0] | 
					
						
							|  |  |  |             if not url.endswith('/oembed'): | 
					
						
							|  |  |  |                 url = url + '/oembed' | 
					
						
							|  |  |  |             content = \ | 
					
						
							|  |  |  |                 content + "<center>\n<iframe loading=\"lazy\" src=\"" + \ | 
					
						
							|  |  |  |                 videoSite + url + "\" width=\"" + \ | 
					
						
							|  |  |  |                 str(width) + "\" height=\"" + str(height) + \ | 
					
						
							|  |  |  |                 "\" frameborder=\"0\" allow=\"fullscreen\" " + \ | 
					
						
							|  |  |  |                 "allowfullscreen></iframe>\n</center>\n" | 
					
						
							|  |  |  |             return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if '"https://' in content: | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |         if peertubeInstances: | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  |             # only create an embedded video for a limited set of | 
					
						
							|  |  |  |             # peertube sites. | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |             peerTubeSites = peertubeInstances | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2020-12-24 10:13:21 +00:00
										 |  |  |             # A default selection of the current larger peertube sites, | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |             # mostly French and German language. | 
					
						
							|  |  |  |             # These have only been semi-vetted, and so should be under | 
					
						
							|  |  |  |             # continuous review. | 
					
						
							| 
									
										
										
										
											2020-12-24 10:13:21 +00:00
										 |  |  |             # Also see https://peertube_isolation.frama.io/list/ for | 
					
						
							|  |  |  |             # adversarial instances. Nothing in that list should be | 
					
						
							|  |  |  |             # in the defaults below. | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |             peerTubeSites = ('share.tube', | 
					
						
							|  |  |  |                              'tube.22decembre.eu', | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                              'libre.video', | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |                              'peertube.linuxrocks.online', | 
					
						
							|  |  |  |                              'spacepub.space', | 
					
						
							|  |  |  |                              'tube.tchncs.de', | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                              'video.irem.univ-paris-diderot.fr', | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |                              'peertube.openstreetmap.fr', | 
					
						
							|  |  |  |                              'video.antopie.org', | 
					
						
							|  |  |  |                              'scitech.video', | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                              'video.ploud.fr', | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |                              'diode.zone', | 
					
						
							|  |  |  |                              'visionon.tv', | 
					
						
							|  |  |  |                              'peertube.fr', | 
					
						
							|  |  |  |                              'peertube.live', | 
					
						
							|  |  |  |                              'kolektiva.media', | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                              'betamax.video', | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |                              'peertube.social', | 
					
						
							|  |  |  |                              'videos.lescommuns.org', | 
					
						
							|  |  |  |                              'video.tedomum.net', | 
					
						
							|  |  |  |                              'tilvids.com', | 
					
						
							|  |  |  |                              'exode.me', | 
					
						
							|  |  |  |                              'peertube.video') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |         for site in peerTubeSites: | 
					
						
							| 
									
										
										
										
											2020-12-24 13:57:02 +00:00
										 |  |  |             site = site.strip() | 
					
						
							|  |  |  |             if not site: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if len(site) < 5: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if '.' not in site: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |             siteStr = site | 
					
						
							| 
									
										
										
										
											2020-12-24 13:13:03 +00:00
										 |  |  |             if site.startswith('http://'): | 
					
						
							|  |  |  |                 site = site.replace('http://', '') | 
					
						
							|  |  |  |             elif site.startswith('https://'): | 
					
						
							|  |  |  |                 site = site.replace('https://', '') | 
					
						
							|  |  |  |             if site.endswith('.onion') or site.endswith('.i2p'): | 
					
						
							|  |  |  |                 siteStr = 'http://' + site | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2020-12-24 12:37:13 +00:00
										 |  |  |                 siteStr = 'https://' + site | 
					
						
							|  |  |  |             siteStr = '"' + siteStr | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  |             if siteStr not in content: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             url = content.split(siteStr)[1] | 
					
						
							|  |  |  |             if '"' not in url: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             url = url.split('"')[0].replace('/watch/', '/embed/') | 
					
						
							|  |  |  |             content = \ | 
					
						
							|  |  |  |                 content + "<center>\n<iframe loading=\"lazy\" " + \ | 
					
						
							|  |  |  |                 "sandbox=\"allow-same-origin " + \ | 
					
						
							|  |  |  |                 "allow-scripts\" src=\"https://" + \ | 
					
						
							|  |  |  |                 site + url + "\" width=\"" + str(width) + \ | 
					
						
							|  |  |  |                 "\" height=\"" + str(height) + \ | 
					
						
							|  |  |  |                 "\" frameborder=\"0\" allow=\"autoplay; " + \ | 
					
						
							|  |  |  |                 "fullscreen\" allowfullscreen></iframe>\n</center>\n" | 
					
						
							|  |  |  |             return content | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _addEmbeddedAudio(translate: {}, content: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     """Adds embedded audio for mp3/ogg
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not ('.mp3' in content or '.ogg' in content): | 
					
						
							|  |  |  |         return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if '<audio ' in content: | 
					
						
							|  |  |  |         return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     extension = '.mp3' | 
					
						
							|  |  |  |     if '.ogg' in content: | 
					
						
							|  |  |  |         extension = '.ogg' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     words = content.strip('\n').split(' ') | 
					
						
							|  |  |  |     for w in words: | 
					
						
							|  |  |  |         if extension not in w: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         w = w.replace('href="', '').replace('">', '') | 
					
						
							|  |  |  |         if w.endswith('.'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if w.endswith('"'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if w.endswith(';'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if w.endswith(':'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if not w.endswith(extension): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  |         if not validUrlPrefix(w): | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |             continue | 
					
						
							|  |  |  |         content += \ | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  |             '<center>\n<audio controls>\n' + \ | 
					
						
							|  |  |  |             '<source src="' + w + '" type="audio/' + \ | 
					
						
							|  |  |  |             extension.replace('.', '') + '">' + \ | 
					
						
							|  |  |  |             translate['Your browser does not support the audio element.'] + \ | 
					
						
							|  |  |  |             '</audio>\n</center>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 12:09:46 +00:00
										 |  |  | def _addEmbeddedVideo(translate: {}, content: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     """Adds embedded video for mp4/webm/ogv
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not ('.mp4' in content or '.webm' in content or '.ogv' in content): | 
					
						
							|  |  |  |         return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if '<video ' in content: | 
					
						
							|  |  |  |         return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     extension = '.mp4' | 
					
						
							|  |  |  |     if '.webm' in content: | 
					
						
							|  |  |  |         extension = '.webm' | 
					
						
							|  |  |  |     elif '.ogv' in content: | 
					
						
							|  |  |  |         extension = '.ogv' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     words = content.strip('\n').split(' ') | 
					
						
							|  |  |  |     for w in words: | 
					
						
							|  |  |  |         if extension not in w: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         w = w.replace('href="', '').replace('">', '') | 
					
						
							|  |  |  |         if w.endswith('.'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if w.endswith('"'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if w.endswith(';'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if w.endswith(':'): | 
					
						
							|  |  |  |             w = w[:-1] | 
					
						
							|  |  |  |         if not w.endswith(extension): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  |         if not validUrlPrefix(w): | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |             continue | 
					
						
							|  |  |  |         content += \ | 
					
						
							| 
									
										
										
										
											2021-03-07 12:06:01 +00:00
										 |  |  |             '<center><figure id="videoContainer" ' + \ | 
					
						
							|  |  |  |             'data-fullscreen="false">\n' + \ | 
					
						
							|  |  |  |             '    <video id="video" controls ' + \ | 
					
						
							| 
									
										
										
										
											2021-07-06 09:44:45 +00:00
										 |  |  |             'preload="metadata">\n' + \ | 
					
						
							|  |  |  |             '<source src="' + w + '" type="video/' + \ | 
					
						
							|  |  |  |             extension.replace('.', '') + '">\n' + \ | 
					
						
							|  |  |  |             translate['Your browser does not support the video element.'] + \ | 
					
						
							|  |  |  |             '</video>\n</figure>\n</center>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     return content | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  | def addEmbeddedElements(translate: {}, content: str, | 
					
						
							|  |  |  |                         peertubeInstances: []) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 19:41:01 +00:00
										 |  |  |     """Adds embedded elements for various media types
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |     content = _addEmbeddedVideoFromSites(translate, content, | 
					
						
							|  |  |  |                                          peertubeInstances) | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     content = _addEmbeddedAudio(translate, content) | 
					
						
							|  |  |  |     return _addEmbeddedVideo(translate, content) |