import os import sys from importlib.util import find_spec from configparser import ConfigParser from hashlib import sha256 import json import requests from flask import Flask, g, redirect, url_for, render_template, jsonify, request, send_from_directory from flask_cors import CORS from .content_system import get_content from .item_collections import item_collections_bp theme_bootstrap5_enabled = False if find_spec('theme_bootstrap5'): from theme_bootstrap5 import hogumathi_theme_bootstrap5_bp theme_bootstrap5_enabled = True if find_spec('twitter_v2_facade'): # FIXME get_brand needs a refactor import twitter_v2_facade from twitter_v2_facade import twitter_app as twitter_v2 from twitter_v2_facade import oauth2_login twitter_enabled = True else: print('twitter module not found.') twitter_enabled = False if find_spec('twitter_v2_live_facade'): from twitter_v2_live_facade import twitter_app as twitter_v2_live import brands from brands import brands_bp, get_brand twitter_live_enabled = True else: print('twitter live module not found.') twitter_live_enabled = False if find_spec('twitter_archive_facade'): from twitter_archive_facade import twitter_app as twitter_archive archive_enabled = True else: print('twitter archive module not found.') archive_enabled = False if find_spec('mastodon_facade'): from mastodon_facade import twitter_app as mastodon mastodon_enabled = True else: print('mastodon module not found.') mastodon_enabled = False if find_spec('feeds_facade'): from feeds_facade import twitter_app as feeds feeds_enabled = True else: print('feeds module not found.') feeds_enabled = False if find_spec('youtube_facade'): from youtube_facade import youtube_app as youtube youtube_enabled = True else: print('youtube module not found.') youtube_enabled = False if find_spec('email_facade'): from email_facade import messages_facade as messages messages_enabled = True else: print('messages module not found.') messages_enabled = False if find_spec('videojs'): from videojs import videojs_bp videojs_enabled = True else: print('videojs module not found.') videojs_enabled = False if find_spec('visjs'): from visjs import visjs_bp visjs_enabled = True else: print('messages module not found.') visjs_enabled = False #messages_enabled = False #twitter_live_enabled = True add_account_enabled = True if __name__ == '__main__': glitch_enabled = os.environ.get('PROJECT_DOMAIN') and True t = os.environ.get('BEARER_TOKEN') PORT = int(os.environ.get('PORT', 5000)) HOST = os.environ.get('HOST', '127.0.0.1') archive_enabled = os.environ.get('ARCHIVE_TWEETS_PATH') and True notes_app_url = os.environ.get('NOTES_APP_URL') bedrss_app_url = os.environ.get('NOTES_APP_URL') plots_app_url = os.environ.get('PLOTS_APP_URL') videos_app_url = os.environ.get('VIDEOS_APP_URL') messages_app_url = os.environ.get('MESSAGES_APP_URL') if not os.path.exists('.data'): os.mkdir('.data') if not os.path.exists('.data/cache'): os.mkdir('.data/cache') api = Flask(__name__, static_url_path='') # HACK - environ from .env isn't set yet when the import happens. We should call an init function somewhere. oauth2_login.app_access_token = os.environ.get("BEARER_TOKEN") oauth2_login.app_consumer_key = os.environ.get("TWITTER_CONSUMER_KEY") oauth2_login.app_secret_key = os.environ.get("TWITTER_CONSUMER_SECRET") @api.before_request def add_config (): g.twitter_enabled = twitter_enabled g.archive_enabled = archive_enabled g.mastodon_enabled = mastodon_enabled g.feeds_enabled = feeds_enabled g.youtube_enabled = youtube_enabled g.messages_enabled = messages_enabled g.twitter_live_enabled = twitter_live_enabled g.add_account_enabled = add_account_enabled g.glitch_enabled = glitch_enabled g.videojs_enabled = videojs_enabled g.visjs_enabled = visjs_enabled if glitch_enabled: g.app_url = 'https://{}.glitch.me'.format( os.environ.get('PROJECT_DOMAIN') ) else: g.app_url = 'http://{}:{}'.format('localhost', PORT) if notes_app_url: g.notes_app_url = notes_app_url if bedrss_app_url: g.bedrss_app_url = bedrss_app_url if plots_app_url: g.plots_app_url = plots_app_url if videos_app_url: g.videos_app_url = videos_app_url if messages_app_url: g.messages_app_url = messages_app_url if theme_bootstrap5_enabled: g.theme_bootstrap5_enabled = theme_bootstrap5_enabled @api.context_processor def inject_config (): config = {} config['twitter_enabled'] = twitter_enabled config['archive_enabled'] = archive_enabled config['mastodon_enabled'] = mastodon_enabled config['feeds_enabled'] = feeds_enabled config['youtube_enabled'] = youtube_enabled config['messages_enabled'] = messages_enabled config['twitter_live_enabled'] = twitter_live_enabled config['add_account_enabled'] = add_account_enabled config['glitch_enabled'] = glitch_enabled config['videojs_enabled'] = videojs_enabled config['visjs_enabled'] = visjs_enabled config['theme_bootstrap5_enabled'] = theme_bootstrap5_enabled if notes_app_url: config['notes_app_url'] = notes_app_url if bedrss_app_url: config['bedrss_app_url'] = bedrss_app_url if plots_app_url: config['plots_app_url'] = plots_app_url if videos_app_url: config['videos_app_url'] = videos_app_url if messages_app_url: config['messages_app_url'] = messages_app_url return config @api.context_processor def add_nav_items_to_template_context (): nav_items = [] route_nav = g.get('route_nav') if route_nav: nav_items += route_nav module_nav = g.get('module_nav') if module_nav: nav_items += module_nav #nav_items.sort(key = lambda ni: ni['order']) return dict( nav_items = nav_items ) api.secret_key = os.environ.get('FLASK_SECRET') api.config['TEMPLATES_AUTO_RELOAD'] = True if theme_bootstrap5_enabled: api.register_blueprint(hogumathi_theme_bootstrap5_bp) if videojs_enabled: api.register_blueprint(videojs_bp, url_prefix='/lib/videojs') if visjs_enabled: api.register_blueprint(visjs_bp, url_prefix='/lib/visjs') twitter_v2_facade.register_content_sources() api.register_blueprint(twitter_v2, url_prefix='/twitter') if archive_enabled: api.register_blueprint(twitter_archive, url_prefix='/twitter-archive') if mastodon_enabled: api.register_blueprint(mastodon, url_prefix='/mastodon') if feeds_enabled: if not os.path.exists('.data/cache/feeds'): os.mkdir('.data/cache/feeds') api.register_blueprint(feeds, url_prefix='/feeds') if youtube_enabled: api.register_blueprint(youtube, url_prefix='/youtube') if messages_enabled: api.register_blueprint(messages, url_prefix='/messages') if twitter_live_enabled: brands.register_content_sources() api.register_blueprint(twitter_v2_live, url_prefix='/twitter-live') api.register_blueprint(item_collections_bp, url_prefix='/collections') api.register_blueprint(brands_bp, url_prefix='/') #CORS(api) @api.get('/login.html') def get_login_html (): opengraph_info = dict( type = 'webpage', # threads might be article url = g.app_url, title = 'Hogumathi', description = 'An app for Twitter, Mastodon, YouTube, etc; Open Source.' ) return render_template('login.html', opengraph_info=opengraph_info) @api.get('/') def index (): return redirect(url_for('.get_login_html')) @api.get('/img') def get_image (): url = request.args['url'] url_hash = sha256(url.encode('utf-8')).hexdigest() path = f'.data/cache/media/{url_hash}' if not os.path.exists(path): resp = requests.get(url) if resp.status_code >= 200 and resp.status_code < 300: with open(path, 'wb') as f: f.write(resp.content) with open(f'{path}.meta', 'w') as f: headers = dict(resp.headers) json.dump(headers, f) else: return 'not found.', 404 with open(f'{path}.meta', 'r') as f: headers = json.load(f) #print(url) #print(url_hash) #print(headers) # not sure why some responses use lower case. mimetype = headers.get('Content-Type') or headers.get('content-type') return send_from_directory('.data/cache/media', url_hash, mimetype=mimetype) @api.get('/content/abc123.html') def get_abc123_html (): return 'abc123' @api.get('/content/.html') def get_content_html (content_id, content_kwargs=None): if not content_kwargs: content_kwargs = filter(lambda e: e[0].startswith('content:'), request.args.items()) content_kwargs = dict(map(lambda e: [e[0][len('content:'):], e[1]], content_kwargs)) content = get_content(content_id, **content_kwargs) return jsonify(content) @api.get('/content/def456.html') def get_def456_html (): return get_content_html('brand:ispoogedaily') api.run(port=PORT, host=HOST)