def profile(): if request.method == 'GET': user = get_user() mods = list() for mod in user.mods: m = wrap_mod(mod) if m: mods.append(m) mods = sorted(mods, key=lambda m: m['mod'].created, reverse=True) return render_template("profile.html", **{ 'mods': mods, 'following': None }) else: user = get_user() user.description = request.form.get('description') user.twitterUsername = request.form.get('twitter') user.forumUsername = request.form.get('ksp-forum-user') forumId = request.form.get('ksp-forum-id') if forumId: user.forumId = int(forumId) user.ircNick = request.form.get('irc-nick') user.backgroundMedia = request.form.get('backgroundMedia') db.commit() return redirect("/profile")
def make_public(username): user = get_user() if user.username != username: abort(401) user.public = True db.commit() return redirect("/profile")
def login(): if request.method == 'GET': if get_user(): return redirect("/") reset = request.args.get('reset') == '1' return render_template( "login.html", **{ 'return_to': request.args.get('return_to'), 'reset': reset }) else: username = request.form['username'] password = request.form['password'] user = User.query.filter_by(username=username).first() if not user: return render_template( "login.html", **{ "username": username, "errors": 'Your username or password is incorrect.' }) if user.confirmation != '' and user.confirmation != None: return redirect("/account-pending") if not bcrypt.checkpw(password, user.password): return render_template( "login.html", **{ "username": username, "errors": 'Your username or password is incorrect.' }) session['user'] = user.username if 'return_to' in request.form and request.form['return_to']: return redirect(urllib.parse.unquote( request.form.get('return_to'))) return redirect("/")
def download(mod_id, mod_name, version): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not mod.published and (not user or user.id != mod.user_id): abort(401) version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \ ModVersion.friendly_version == version).first() if not version: abort(404) download = DownloadEvent.query\ .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\ .order_by(desc(DownloadEvent.created))\ .first() # Events are aggregated hourly if not download or ( (datetime.now() - download.created).seconds / 60 / 60) >= 1: download = DownloadEvent() download.mod = mod download.version = version download.downloads = 1 mod.downloads.append(download) db.add(download) else: download.downloads += 1 mod.download_count += 1 db.commit() return send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment=True)
def inject(): ads = True if 'ad-opt-out' in request.cookies: ads = False if g.do_not_track: ads = False if not _cfg("project_wonderful_id"): ads = False return { 'mobile': g.mobile, 'ua_platform': request.user_agent.platform, 'analytics_id': _cfg("google_analytics_id"), 'analytics_domain': _cfg("google_analytics_domain"), 'disqus_id': _cfg("disqus_id"), 'dnt': g.do_not_track, 'ads': ads, 'ad_id': _cfg("project_wonderful_id"), 'root': _cfg("protocol") + "://" + _cfg("domain"), 'domain': _cfg("domain"), 'user': get_user(), 'len': len, 'any': any, 'following_mod': following_mod, 'following_user': following_user, 'bgindex': random.choice(range(0, 11)), 'admin': is_admin(), 'wrap_mod': wrap_mod, 'dumb_object': dumb_object }
def following_mod(mod): user = get_user() if not user: return False if any([m.id == mod.id for m in user.following]): return True return False
def unfollow(mod_id): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not any(m.id == mod.id for m in user.following): abort(418) event = FollowEvent.query\ .filter(FollowEvent.mod_id == mod.id)\ .order_by(desc(FollowEvent.created))\ .first() # Events are aggregated hourly if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1: event = FollowEvent() event.mod = mod event.delta = -1 event.events = 1 mod.follow_events.append(event) db.add(event) else: event.delta -= 1 event.events += 1 mod.follower_count -= 1 user.following = [m for m in user.following if m.id == mod_id] db.commit() return { "success": True }
def edit(mod_id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not user or user.id != mod.user_id: abort(401) if request.method == 'GET': return render_template("edit.html", mod=mod) else: name = request.form.get('name') description = request.form.get('description') short_description = request.form.get('short-description') external_link = request.form.get('external-link') license = request.form.get('license') source_link = request.form.get('source-code') donation_link = request.form.get('donation') if not short_description \ or not description \ or not license: # TODO: Better error abort(400) mod.description = description mod.short_description = short_description mod.external_link = external_link mod.license = license mod.source_link = source_link mod.donation_link = donation_link db.commit() return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
def download(mod_id, mod_name, version): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not mod.published and (not user or user.id != mod.user_id): abort(401) version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \ ModVersion.friendly_version == version).first() if not version: abort(404) download = DownloadEvent.query\ .filter(DownloadEvent.mod_id == mod.id and DownloadEvent.version_id == version.id)\ .order_by(desc(DownloadEvent.created))\ .first() # Events are aggregated hourly if not download or ((datetime.now() - download.created).seconds / 60 / 60) >= 1: download = DownloadEvent() download.mod = mod download.version = version download.downloads = 1 mod.downloads.append(download) db.add(download) else: download.downloads += 1 mod.download_count += 1 db.commit() return send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment = True)
def unfollow(mod_id): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not any(m.id == mod.id for m in user.following): abort(418) event = FollowEvent.query\ .filter(FollowEvent.mod_id == mod.id)\ .order_by(desc(FollowEvent.created))\ .first() # Events are aggregated hourly if not event or ((datetime.now() - event.created).seconds / 60 / 60) >= 1: event = FollowEvent() event.mod = mod event.delta = -1 event.events = 1 mod.follow_events.append(event) db.add(event) else: event.delta -= 1 event.events += 1 mod.follower_count -= 1 user.following = [m for m in user.following if m.id == mod_id] db.commit() return {"success": True}
def mod(id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == id).first() if not mod: abort(404) editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not mod.published and not editable: abort(401) videos = list() screens = list() latest = mod.versions[0] screenshot_list = ",".join([s.data for s in mod.media if s.type == 'image']) video_list = ",".join([s.data for s in mod.media if s.type == 'video']) for m in mod.medias: if m.type == 'video': videos.append(m) else: screens.append(m) return render_template("mod.html", **{ 'mod': mod, 'videos': videos, 'screens': screens, 'latest': latest, 'safe_name': secure_filename(mod.name)[:64], 'featured': any(Featured.query.filter(Featured.mod_id == mod.id).all()), 'editable': editable, 'screenshot_list': screenshot_list, 'video_list': video_list })
def profile(): if request.method == 'GET': user = get_user() mods = list() for mod in user.mods: m = wrap_mod(mod) if m: mods.append(m) mods = sorted(mods, key=lambda m: m['mod'].created, reverse=True) return render_template("profile.html", **{ 'mods': mods, 'following': None }) else: user = get_user() user.description = request.form.get('description') user.twitterUsername = request.form.get('twitter') user.forumUsername = request.form.get('ksp-forum-user') user.forumId = int(request.form.get('ksp-forum-id')) user.ircNick = request.form.get('irc-nick') user.backgroundMedia = request.form.get('backgroundMedia') db.commit() return redirect("/profile")
def unfollow(mod_id): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not any(m.id == mod.id for m in user.following): abort(418) user.following = [m for m in user.following if m.id == mod_id] mod.follower_count -= 1 db.commit() return { "success": True }
def publish(mod_id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not user or user.id != mod.user_id: abort(401) mod.published = True mod.updated = datetime.now() db.commit() return redirect('/mod/' + mod_id + '/' + mod_name)
def edit_media(mod_id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not editable: abort(401) screenshots = request.form.get('screenshots') videos = request.form.get('videos') background = request.form.get('backgroundMedia') screenshot_list = screenshots.split(',') video_list = videos.split(',') if len(screenshot_list) > 5 \ or len(video_list) > 2 \ or len(background) > 32: abort(400) [db.delete(m) for m in mod.media] for screenshot in screenshot_list: if screenshot: r = requests.get('https://mediacru.sh/' + screenshot + '.json') if r.status_code != 200: abort(400) j = r.json() data = '' if j['blob_type'] == 'image': for f in j['files']: if f['type'] == 'image/jpeg' or f['type'] == 'image/png': data = f['file'] else: abort(400) m = Media(j['hash'], j['blob_type'], data) mod.medias.append(m) for video in video_list: if video: r = requests.get('https://mediacru.sh/' + video + '.json') if r.status_code != 200: abort(400) j = r.json() data = '' if j['blob_type'] == 'video': data = j['hash'] else: abort(400) m = Media(j['hash'], j['blob_type'], data) mod.medias.append(m) db.add(m) mod.background = background db.commit() return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
def follow(mod_id): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if any(m.id == mod.id for m in user.following): abort(418) user.following.append(mod) mod.follower_count += 1 db.commit() return { "success": True }
def download(mod_id, mod_name, version): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not mod.published and (not user or user.id != mod.user_id): abort(401) version = ModVersion.query.filter(ModVersion.mod_id == mod_id, \ ModVersion.friendly_version == version).first() if not version: abort(404) return send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment = True)
def update(mod_id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not editable: abort(401) if request.method == 'GET': return render_template("update.html", **{'mod': mod}) else: version = request.form.get('version') changelog = request.form.get('changelog') ksp_version = request.form.get('ksp-version') zipball = request.files.get('zipball') if not version \ or not ksp_version \ or not zipball: # Client side validation means that they're just being pricks if they # get here, so we don't need to show them a pretty error message abort(400) filename = secure_filename( mod.name) + '-' + secure_filename(version) + '.zip' base_path = os.path.join( secure_filename(user.username) + '_' + str(user.id), secure_filename(mod.name)) full_path = os.path.join(_cfg('storage'), base_path) if not os.path.exists(full_path): os.makedirs(full_path) path = os.path.join(full_path, filename) if os.path.isfile(path): # We already have this version # TODO: Error message abort(400) zipball.save(path) if not zipfile.is_zipfile(path): os.remove(path) abort(400) # TODO: Error message version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename)) version.changelog = changelog mod.versions.append(version) send_update_notification(mod) db.add(version) db.commit() return redirect('/mod/' + mod_id + '/' + secure_filename(mod.name))
def view_profile(username): user = User.query.filter(User.username == username).first() current = get_user() if not user: abort(404) if not user.public: if not current: abort(401) if current.username != user.username: if not current.admin: abort(401) mods_created = sorted(user.mods, key=lambda mod: mod.created, reverse=True) if not current or current.id != user.id: mods_created = [mod for mod in mods_created if mod.published] mods_followed = sorted(user.following, key=lambda mod: mod.created, reverse=True) return render_template("view_profile.html", **{ 'profile': user, 'mods_created': mods_created, 'mods_followed': mods_followed })
def update(mod_id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not editable: abort(401) if request.method == 'GET': return render_template("update.html", **{ 'mod': mod }) else: version = request.form.get('version') changelog = request.form.get('changelog') ksp_version = request.form.get('ksp-version') zipball = request.files.get('zipball') if not version \ or not ksp_version \ or not zipball: # Client side validation means that they're just being pricks if they # get here, so we don't need to show them a pretty error message abort(400) filename = secure_filename(mod.name) + '-' + secure_filename(version) + '.zip' base_path = os.path.join(secure_filename(user.username) + '_' + str(user.id), secure_filename(mod.name)) full_path = os.path.join(_cfg('storage'), base_path) if not os.path.exists(full_path): os.makedirs(full_path) path = os.path.join(full_path, filename) if os.path.isfile(path): # We already have this version # TODO: Error message abort(400) zipball.save(path) if not zipfile.is_zipfile(path): os.remove(path) abort(400) # TODO: Error message version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename)) version.changelog = changelog mod.versions.append(version) send_update_notification(mod) db.add(version) db.commit() return redirect('/mod/' + mod_id + '/' + secure_filename(mod.name))
def login(): if request.method == 'GET': if get_user(): return redirect("/") return render_template("login.html", **{ 'return_to': request.args.get('return_to') }) else: username = request.form['username'] password = request.form['password'] user = User.query.filter_by(username=username).first() if not user: return render_template("login.html", **{ "username": username, "errors": 'Your username or password is incorrect.' }) if not bcrypt.checkpw(password, user.password): return render_template("login.html", **{ "username": username, "errors": 'Your username or password is incorrect.' }) session['user'] = user.username if 'return_to' in request.form and request.form['return_to']: return redirect(urllib.parse.unquote(request.form.get('return_to'))) return redirect("/")
def view_profile(username): user = User.query.filter(User.username == username).first() current = get_user() if not user: abort(404) if not user.public: if not current or current.username != user.username: if not current.admin: abort(401) mods = list() for mod in user.mods: if len(mod.versions) > 0: m = wrap_mod(mod) if m: mods.append(m) mods = sorted(mods, key=lambda mod: mod['mod'].created, reverse=True) if not current or current.id != mod.user_id: mods = [mod for mod in mods if mod['mod'].published] return render_template("view_profile.html", **{ 'profile': user, 'mods': mods })
def delete(mod_id): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not admin or not user.id == mod.user.id: abort(401) db.delete(mod) for feature in Featured.query.filter(Featured.mod_id == mod.id).all(): db.delete(feature) for media in Media.query.filter(Media.mod_id == mod.id).all(): db.delete(media) for version in ModVersion.query.filter(ModVersion.mod_id == mod.id).all(): db.delete(version) base_path = os.path.join(secure_filename(user.username) + '_' + str(user.id), secure_filename(mod.name)) full_path = os.path.join(_cfg('storage'), base_path) rmtree(full_path) db.commit() return redirect("/profile")
def edit_meta(mod_id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not editable: abort(401) name = request.form.get('name') description = request.form.get('description') short_description = request.form.get('short-description') external_link = request.form.get('external-link') license = request.form.get('license') source_link = request.form.get('source-code') donation_link = request.form.get('donation') if not short_description \ or not description \ or not license: # TODO: Better error abort(400) if len(description) > 100000 \ or len(donation_link) > 512 \ or len(external_link) > 512 \ or len(license) > 128 \ or len(source_link) > 256: abort(400) mod.description = description mod.short_description = short_description mod.external_link = external_link mod.license = license mod.source_link = source_link mod.donation_link = donation_link db.commit() return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
def view_profile(username): user = User.query.filter(User.username == username).first() current = get_user() if not user: abort(404) if not user.public: if not current: abort(401) if current.username != user.username: if not current.admin: abort(401) mods_created = sorted(user.mods, key=lambda mod: mod.created, reverse=True) if not current or current.id != user.id: mods_created = [mod for mod in mods_created if mod.published] mods_followed = sorted(user.following, key=lambda mod: mod.created, reverse=True) return render_template( "view_profile.html", **{ 'profile': user, 'mods_created': mods_created, 'mods_followed': mods_followed })
def mod(id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == id).first() if not mod: abort(404) if not mod.published and (not user or user.id != mod.user_id): abort(401) videos = list() screens = list() latest = mod.versions[0] for m in mod.medias: if m.type == 'video': videos.append(m) else: screens.append(m) return render_template("mod.html", **{ 'mod': mod, 'videos': videos, 'screens': screens, 'latest': latest, 'safe_name': secure_filename(mod.name)[:64] })
def delete(mod_id): user = get_user() mod = Mod.query.filter(Mod.id == mod_id).first() if not mod: abort(404) if not admin or not user.id == mod.user.id: abort(401) db.delete(mod) for feature in Featured.query.filter(Featured.mod_id == mod.id).all(): db.delete(feature) for media in Media.query.filter(Media.mod_id == mod.id).all(): db.delete(media) for version in ModVersion.query.filter(ModVersion.mod_id == mod.id).all(): db.delete(version) base_path = os.path.join( secure_filename(user.username) + '_' + str(user.id), secure_filename(mod.name)) full_path = os.path.join(_cfg('storage'), base_path) rmtree(full_path) db.commit() return redirect("/profile")
def inject(): ads = True if 'ad-opt-out' in request.cookies: ads = False if g.do_not_track: ads = False if not _cfg("project_wonderful_id"): ads = False return { 'mobile': g.mobile, 'ua_platform': request.user_agent.platform, 'analytics_id': _cfg("google_analytics_id"), 'analytics_domain': _cfg("google_analytics_domain"), 'dnt': g.do_not_track, 'ads': ads, 'ad_id': _cfg("project_wonderful_id"), 'root': _cfg("protocol") + "://" + _cfg("domain"), 'domain': _cfg("domain"), 'user': get_user(), 'len': len, 'following_mod': following_mod, 'following_user': following_user }
def mod(id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == id).first() if not mod: abort(404) editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not mod.published and not editable: abort(401) videos = list() screens = list() latest = mod.versions[0] screenshot_list = ",".join([s.data for s in mod.media if s.type == 'image']) video_list = ",".join([s.data for s in mod.media if s.type == 'video']) for m in mod.medias: if m.type == 'video': videos.append(m) else: screens.append(m) referral = request.referrer if referral: host = urllib.parse.urlparse(referral).hostname event = ReferralEvent.query\ .filter(ReferralEvent.mod_id == mod.id)\ .filter(ReferralEvent.host == host)\ .first() if not event: event = ReferralEvent() event.mod = mod event.events = 1 event.host = host mod.referrals.append(event) db.add(event) else: event.events += 1 db.commit() download_stats = None follower_stats = None referrals = None json_versions = None thirty_days_ago = datetime.now() - timedelta(days=30) if editable: referrals = list() for r in ReferralEvent.query\ .filter(ReferralEvent.mod_id == mod.id)\ .order_by(desc(ReferralEvent.events)): referrals.append( { 'host': r.host, 'count': r.events } ) download_stats = list() for d in DownloadEvent.query\ .filter(DownloadEvent.mod_id == mod.id)\ .filter(DownloadEvent.created > thirty_days_ago)\ .order_by(DownloadEvent.created): download_stats.append(dumb_object(d)) follower_stats = list() for f in FollowEvent.query\ .filter(FollowEvent.mod_id == mod.id)\ .filter(FollowEvent.created > thirty_days_ago)\ .order_by(FollowEvent.created): follower_stats.append(dumb_object(f)) json_versions = list() for v in mod.versions: json_versions.append({ 'name': v.friendly_version, 'id': v.id }) return render_template("mod.html", **{ 'mod': mod, 'videos': videos, 'screens': screens, 'latest': latest, 'safe_name': secure_filename(mod.name)[:64], 'featured': any(Featured.query.filter(Featured.mod_id == mod.id).all()), 'editable': editable, 'screenshot_list': screenshot_list, 'video_list': video_list, 'download_stats': download_stats, 'follower_stats': follower_stats, 'referrals': referrals, 'json_versions': json_versions, 'thirty_days_ago': thirty_days_ago })
def create_mod(): if request.method == 'GET': return render_template("create.html") else: user = get_user() if not user.public: # Only public users can create mods # /create tells users about this return redirect("/create/mod") name = request.form.get('name') description = request.form.get('description') short_description = request.form.get('short-description') version = request.form.get('version') ksp_version = request.form.get('ksp-version') external_link = request.form.get('external-link') license = request.form.get('license') source_link = request.form.get('source-code') donation_link = request.form.get('donation') screenshots = request.form.get('screenshots') videos = request.form.get('videos') background = request.form.get('backgroundMedia') zipball = request.files.get('zipball') # Validate if not name \ or not short_description \ or not description \ or not version \ or not ksp_version \ or not license \ or not zipball: # Client side validation means that they're just being pricks if they # get here, so we don't need to show them a pretty error message abort(400) screenshot_list = screenshots.split(',') video_list = videos.split(',') # Validation, continued if len(name) > 100 \ or len(description) > 100000 \ or len(donation_link) > 512 \ or len(external_link) > 512 \ or len(license) > 128 \ or len(source_link) > 256 \ or len(background) > 32 \ or len(screenshot_list) > 5 \ or len(video_list) > 2: abort(400) mod = Mod() mod.user = user mod.name = name mod.description = description mod.short_description = short_description mod.external_link = external_link mod.license = license mod.source_link = source_link mod.donation_link = donation_link mod.background = background # Do media for screenshot in screenshot_list: if screenshot: r = requests.get('https://mediacru.sh/' + screenshot + '.json') if r.status_code != 200: abort(400) j = r.json() data = '' if j['blob_type'] == 'image': for f in j['files']: if f['type'] == 'image/jpeg' or f['type'] == 'image/png': data = f['file'] else: abort(400) m = Media(j['hash'], j['blob_type'], data) mod.medias.append(m) for video in video_list: if video: r = requests.get('https://mediacru.sh/' + video + '.json') if r.status_code != 200: abort(400) j = r.json() data = '' if j['blob_type'] == 'video': data = j['hash'] else: abort(400) m = Media(j['hash'], j['blob_type'], data) mod.medias.append(m) db.add(m) # Save zipball filename = secure_filename(name) + '-' + secure_filename(version) + '.zip' base_path = os.path.join(secure_filename(user.username) + '_' + str(user.id), secure_filename(name)) full_path = os.path.join(_cfg('storage'), base_path) if not os.path.exists(full_path): os.makedirs(full_path) path = os.path.join(full_path, filename) if os.path.isfile(path): # We already have this version # TODO: Error message abort(400) zipball.save(path) if not zipfile.is_zipfile(path): os.remove(path) abort(400) # TODO: Error message version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename)) mod.versions.append(version) db.add(version) # Save database entry db.add(mod) db.commit() return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
def is_admin(): user = get_user() if not user: return False return user.admin
def create_mod(): if request.method == 'GET': return render_template("create.html") else: user = get_user() if not user.public: # Only public users can create mods # /create tells users about this return redirect("/create/mod") name = request.form.get('name') description = request.form.get('description') short_description = request.form.get('short-description') version = request.form.get('version') ksp_version = request.form.get('ksp-version') external_link = request.form.get('external-link') license = request.form.get('license') source_link = request.form.get('source-code') donation_link = request.form.get('donation') screenshots = request.form.get('screenshots') videos = request.form.get('videos') background = request.form.get('backgroundMedia') zipball = request.files.get('zipball') # Validate if not name \ or not short_description \ or not description \ or not version \ or not ksp_version \ or not license \ or not zipball: # Client side validation means that they're just being pricks if they # get here, so we don't need to show them a pretty error message abort(400) screenshot_list = screenshots.split(',') video_list = videos.split(',') # Validation, continued if len(name) > 100 \ or len(description) > 100000 \ or len(donation_link) > 512 \ or len(external_link) > 512 \ or len(license) > 128 \ or len(source_link) > 256 \ or len(background) > 32 \ or len(screenshot_list) > 5 \ or len(video_list) > 2: abort(400) mod = Mod() mod.user = user mod.name = name mod.description = description mod.short_description = short_description mod.external_link = external_link mod.license = license mod.source_link = source_link mod.donation_link = donation_link mod.background = background # Do media for screenshot in screenshot_list: if screenshot: r = requests.get('https://mediacru.sh/' + screenshot + '.json') if r.status_code != 200: abort(400) j = r.json() data = '' if j['blob_type'] == 'image': for f in j['files']: if f['type'] == 'image/jpeg' or f[ 'type'] == 'image/png': data = f['file'] else: abort(400) m = Media(j['hash'], j['blob_type'], data) mod.medias.append(m) for video in video_list: if video: r = requests.get('https://mediacru.sh/' + video + '.json') if r.status_code != 200: abort(400) j = r.json() data = '' if j['blob_type'] == 'video': data = j['hash'] else: abort(400) m = Media(j['hash'], j['blob_type'], data) mod.medias.append(m) db.add(m) # Save zipball filename = secure_filename(name) + '-' + secure_filename( version) + '.zip' base_path = os.path.join( secure_filename(user.username) + '_' + str(user.id), secure_filename(name)) full_path = os.path.join(_cfg('storage'), base_path) if not os.path.exists(full_path): os.makedirs(full_path) path = os.path.join(full_path, filename) if os.path.isfile(path): # We already have this version # TODO: Error message abort(400) zipball.save(path) if not zipfile.is_zipfile(path): os.remove(path) abort(400) # TODO: Error message version = ModVersion(secure_filename(version), ksp_version, os.path.join(base_path, filename)) mod.versions.append(version) db.add(version) # Save database entry db.add(mod) db.commit() return redirect('/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64])
def mod(id, mod_name): user = get_user() mod = Mod.query.filter(Mod.id == id).first() if not mod: abort(404) editable = False if user: if user.admin: editable = True if user.id == mod.user_id: editable = True if not mod.published and not editable: abort(401) videos = list() screens = list() latest = mod.versions[0] screenshot_list = ",".join( [s.data for s in mod.media if s.type == 'image']) video_list = ",".join([s.data for s in mod.media if s.type == 'video']) for m in mod.medias: if m.type == 'video': videos.append(m) else: screens.append(m) referral = request.referrer if referral: host = urllib.parse.urlparse(referral).hostname event = ReferralEvent.query\ .filter(ReferralEvent.mod_id == mod.id)\ .filter(ReferralEvent.host == host)\ .first() if not event: event = ReferralEvent() event.mod = mod event.events = 1 event.host = host mod.referrals.append(event) db.add(event) else: event.events += 1 db.commit() download_stats = None follower_stats = None referrals = None json_versions = None thirty_days_ago = datetime.now() - timedelta(days=30) if editable: referrals = list() for r in ReferralEvent.query\ .filter(ReferralEvent.mod_id == mod.id)\ .order_by(desc(ReferralEvent.events)): referrals.append({'host': r.host, 'count': r.events}) download_stats = list() for d in DownloadEvent.query\ .filter(DownloadEvent.mod_id == mod.id)\ .filter(DownloadEvent.created > thirty_days_ago)\ .order_by(DownloadEvent.created): download_stats.append(dumb_object(d)) follower_stats = list() for f in FollowEvent.query\ .filter(FollowEvent.mod_id == mod.id)\ .filter(FollowEvent.created > thirty_days_ago)\ .order_by(FollowEvent.created): follower_stats.append(dumb_object(f)) json_versions = list() for v in mod.versions: json_versions.append({'name': v.friendly_version, 'id': v.id}) return render_template( "mod.html", **{ 'mod': mod, 'videos': videos, 'screens': screens, 'latest': latest, 'safe_name': secure_filename(mod.name)[:64], 'featured': any(Featured.query.filter(Featured.mod_id == mod.id).all()), 'editable': editable, 'screenshot_list': screenshot_list, 'video_list': video_list, 'download_stats': download_stats, 'follower_stats': follower_stats, 'referrals': referrals, 'json_versions': json_versions, 'thirty_days_ago': thirty_days_ago })