예제 #1
0
def send_update_notification(mod, version, user):
    followers = [u.email for u in mod.followers]
    changelog = version.changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    with open("emails/mod-updated") as f:
        message = html.parser.HTMLParser().unescape(
            pystache.render(
                f.read(), {
                    'mod':
                    mod,
                    'user':
                    user,
                    'site-name':
                    _cfg('site-name'),
                    'domain':
                    _cfg("domain"),
                    'latest':
                    version,
                    'url':
                    '/mod/' + str(mod.id) + '/' +
                    secure_filename(mod.name)[:64],
                    'changelog':
                    changelog
                }))
    subject = user.username + " has just updated " + mod.name + "!"
    send_mail.delay(_cfg('support-mail'), targets, subject, message)
예제 #2
0
def send_update_notification(mod):
    followers = [u.email for u in mod.followers]
    changelog = mod.versions[-1].changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    for follower in followers:
        smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
        smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
        with open("emails/mod-updated") as f:
            message = MIMEText(
                pystache.render(
                    f.read(), {
                        'mod':
                        mod,
                        'domain':
                        _cfg("domain"),
                        'latest':
                        mod.versions[-1],
                        'url':
                        '/mod/' + str(mod.id) + '/' +
                        secure_filename(mod.name)[:64],
                        'changelog':
                        changelog
                    }))
        message[
            'Subject'] = mod.user.username + " has just updated " + mod.name + "!"
        message['From'] = "*****@*****.**"
        message['To'] = follower
        smtp.sendmail("*****@*****.**", [follower],
                      message.as_string())
        smtp.quit()
예제 #3
0
def is_oauth_provider_configured(provider):
    if provider == 'github':
        return bool(_cfg('gh-oauth-id')) and bool(_cfg('gh-oauth-secret'))
    if provider == 'google':
        return (bool(_cfg('google-oauth-id')) and
                bool(_cfg('google-oauth-secret')))
    return False
예제 #4
0
def send_autoupdate_notification(mod):
    if _cfg("smtp-host") == "":
        return
    followers = [u.email for u in mod.followers]
    changelog = mod.default_version().changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    with open("emails/mod-autoupdated") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(pystache.render(f.read(),
            {
                'mod': mod,
                'domain': _cfg("domain"),
                'latest': mod.default_version(),
                'url': '/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64],
                'changelog': changelog
            })))
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = mod.name + " is compatible with RimWorld " + mod.versions[0].ksp_version + "!"
    message['From'] = "*****@*****.**"
    message['To'] = ";".join(targets)
    sendEmail(message,targets)
예제 #5
0
def is_oauth_provider_configured(provider):
    if provider == 'github':
        return bool(_cfg('gh-oauth-id')) and bool(_cfg('gh-oauth-secret'))
    if provider == 'google':
        return (bool(_cfg('google-oauth-id'))
                and bool(_cfg('google-oauth-secret')))
    return False
예제 #6
0
def update_mod_background(mod_id):
    if current_user == None:
        return { 'error': True, 'reason': 'You are not logged in.' }, 401
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        return { 'error': True, 'reason': 'Mod not found.' }, 404
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod.user_id:
            editable = True
        if any([u.accepted and u.user == current_user for u in mod.shared_authors]):
            editable = True
    if not editable:
        return { 'error': True, 'reason': 'Not enought rights.' }, 401
    f = request.files['image']
    filetype = os.path.splitext(os.path.basename(f.filename))[1]
    if not filetype in ['.png', '.jpg']:
        return { 'error': True, 'reason': 'This file type is not acceptable.' }, 400
    filename = secure_filename(mod.name) + '-' + str(time.time()) + filetype
    base_path = os.path.join(secure_filename(mod.user.username) + '_' + str(mod.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)
    try:
        os.remove(os.path.join(_cfg('storage'), mod.background))
    except:
        pass # who cares
    f.save(path)
    mod.background = os.path.join(base_path, filename)
    return { 'path': '/content/' + mod.background }
예제 #7
0
def browse_updated():
    mods = Mod.query.filter(Mod.published, ModVersion.query.filter(ModVersion.mod_id == Mod.id).count() > 1).order_by(
        desc(Mod.updated)
    )
    total_pages = math.ceil(mods.count() / 30)
    page = request.args.get("page")
    if page:
        page = int(page)
        if page < 1:
            page = 1
        if page > total_pages:
            page = total_pages
    else:
        page = 1
    mods = mods.offset(30 * (page - 1)).limit(30)
    return render_template(
        "browse-list.html",
        mods=mods,
        page=page,
        total_pages=total_pages,
        url="/browse/updated",
        name="Recently Updated Mods",
        rss="/browse/updated.rss",
        site_name=_cfg("site-name"),
        support_mail=_cfg("support-mail"),
    )
예제 #8
0
파일: api.py 프로젝트: williambl/SpaceDock
def update_mod_background(mod_id):
    if current_user == None:
        return { 'error': True, 'reason': 'You are not logged in.' }, 401
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        return { 'error': True, 'reason': 'Mod not found.' }, 404
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod.user_id:
            editable = True
        if any([u.accepted and u.user == current_user for u in mod.shared_authors]):
            editable = True
    if not editable:
        return { 'error': True, 'reason': 'Not enought rights.' }, 401
    f = request.files['image']
    filetype = os.path.splitext(os.path.basename(f.filename))[1]
    if not filetype in ['.png', '.jpg']:
        return { 'error': True, 'reason': 'This file type is not acceptable.' }, 400
    filename = secure_filename(mod.name) + '-' + str(time.time()) + filetype
    base_path = os.path.join(secure_filename(mod.user.username) + '_' + str(mod.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)
    try:
        os.remove(os.path.join(_cfg('storage'), mod.background))
    except:
        pass # who cares
    f.save(path)
    mod.background = os.path.join(base_path, filename)
    return { 'path': '/content/' + mod.background }
예제 #9
0
def send_autoupdate_notification(mod):
    followers = [u.email for u in mod.followers]
    changelog = mod.default_version().changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    with open("emails/mod-autoupdated") as f:
        message = html.parser.HTMLParser().unescape(pystache.render(f.read(),
            {
                'mod': mod,
                'domain': _cfg("domain"),
                'latest': mod.default_version(),
                'url': '/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64],
                'changelog': changelog
            }))
	# We (or rather just me) probably want that this is not dependent on KSP, since I know some people
	# who run forks of KerbalStuff for non-KSP purposes. 
	# TODO(Thomas): Consider in putting the game name into a config.
    subject = mod.name + " is compatible with KSP " + mod.versions[0].ksp_version + "!"
    send_mail.delay(_cfg('support-mail'), targets, subject, message)
예제 #10
0
def browse_new_rss():
    mods = Mod.query.filter(Mod.published).order_by(desc(Mod.created))
    mods = mods.limit(30)
    return Response(render_template("rss.xml", mods=mods, title="New mods on Kerbal Stuff",\
            description="The newest mods on Kerbal Stuff", \
            url="/browse/new", site_name=_cfg('site-name'), support_mail=_cfg('support-mail')),
    mimetype="text/xml")
예제 #11
0
def send_mail(sender, recipients, subject, message, important=False):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(host=_cfg("smtp-host"), port=_cfgi("smtp-port"))
    if _cfgb("smtp-tls"):
        smtp.starttls()
    if _cfg("smtp-user") != "":
        smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    message = MIMEText(message)
    if important:
        message['X-MC-Important'] = "true"
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = subject
    message['From'] = sender
    if len(recipients) > 1:
        message['Precedence'] = 'bulk'
    for group in chunks(recipients, 100):
        if len(group) > 1:
            message['To'] = "undisclosed-recipients:;"
        else:
            message['To'] = ";".join(group)
        print("Sending email from {} to {} recipients".format(
            sender, len(group)))
        smtp.sendmail(sender, group, message.as_string())
    smtp.quit()
예제 #12
0
def index():
    featured = Featured.query.order_by(desc(Featured.created)).limit(6)[:6]
    top = search_mods("", 1, 3)[0]
    new = Mod.query.filter(Mod.published).order_by(desc(
        Mod.created)).limit(3)[:3]
    recent = Mod.query.filter(Mod.published).order_by(desc(
        Mod.updated)).limit(3)[:3]
    user_count = User.query.count()
    mod_count = Mod.query.count()
    yours = list()
    if current_user:
        yours = sorted(current_user.following,
                       key=lambda m: m.updated,
                       reverse=True)[:3]
    return render_template("index.html",\
        featured=featured,\
        new=new,\
        top=top,\
        recent=recent,\
        user_count=user_count,\
        mod_count=mod_count,
        yours=yours,
                           site_name=_cfg('site-name'),
                           support_mail=_cfg('support-mail'),
                           source_code=_cfg('source-code'))
예제 #13
0
def send_autoupdate_notification(mod):
    followers = [u.email for u in mod.followers]
    changelog = mod.default_version().changelog
    if changelog:
        changelog = "\n".join(["    " + l for l in changelog.split("\n")])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    with open("emails/mod-autoupdated") as f:
        message = html.parser.HTMLParser().unescape(
            pystache.render(
                f.read(),
                {
                    "mod": mod,
                    "domain": _cfg("domain"),
                    "site-name": _cfg("site-name"),
                    "latest": mod.default_version(),
                    "url": "/mod/" + str(mod.id) + "/" + secure_filename(mod.name)[:64],
                    "changelog": changelog,
                },
            )
        )
    # We (or rather just me) probably want that this is not dependent on KSP, since I know some people
    # who run forks of KerbalStuff for non-KSP purposes.
    # TODO(Thomas): Consider in putting the game name into a config.
    subject = mod.name + " is compatible with Game " + mod.versions[0].gameversion.friendly_version + "!"
    send_mail.delay(_cfg("support-mail"), targets, subject, message)
예제 #14
0
def browse_updated_rss():
    mods = Mod.query.filter(Mod.published).order_by(desc(Mod.updated))
    mods = mods.limit(30)
    return Response(render_template("rss.xml", mods=mods, title="Recently updated on Kerbal Stuff",\
            description="Mods on Kerbal Stuff updated recently", \
            url="/browse/updated", site_name=_cfg('site-name'), support_mail=_cfg('support-mail')),
    mimetype="text/xml")
예제 #15
0
def send_update_notification(mod, version, user):
    followers = [u.email for u in mod.followers]
    changelog = version.changelog
    if changelog:
        changelog = "\n".join(["    " + l for l in changelog.split("\n")])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    with open("emails/mod-updated") as f:
        message = html.parser.HTMLParser().unescape(
            pystache.render(
                f.read(),
                {
                    "mod": mod,
                    "user": user,
                    "site-name": _cfg("site-name"),
                    "domain": _cfg("domain"),
                    "latest": version,
                    "url": "/mod/" + str(mod.id) + "/" + secure_filename(mod.name)[:64],
                    "changelog": changelog,
                },
            )
        )
    subject = user.username + " has just updated " + mod.name + "!"
    send_mail.delay(_cfg("support-mail"), targets, subject, message)
예제 #16
0
def update_mod_background(mod_id):
    if current_user == None:
        return {"error": True, "reason": "You are not logged in."}, 401
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        return {"error": True, "reason": "Mod not found."}, 404
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod.user_id:
            editable = True
        if any([u.accepted and u.user == current_user for u in mod.shared_authors]):
            editable = True
    if not editable:
        return {"error": True, "reason": "Not enought rights."}, 401
    f = request.files["image"]
    filetype = os.path.splitext(os.path.basename(f.filename))[1]
    if not filetype in [".png", ".jpg"]:
        return {"error": True, "reason": "This file type is not acceptable."}, 400
    filename = secure_filename(mod.name) + "-" + str(time.time()) + filetype
    base_path = os.path.join(secure_filename(mod.user.username) + "_" + str(mod.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)
    try:
        os.remove(os.path.join(_cfg("storage"), mod.background))
    except:
        pass  # who cares
    f.save(path)
    mod.background = os.path.join(base_path, filename)
    return {"path": "/content/" + mod.background}
예제 #17
0
def send_update_notification_sync(mod, version, user):
    followers = [u.email for u in mod.followers]
    changelog = version.changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/mod-updated") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(pystache.render(f.read(),
            {
                'mod': mod,
                'user': user,
                'domain': _cfg("domain"),
                'latest': version,
                'url': '/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64],
                'changelog': changelog
            })))
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = user + " has just updated " + mod.name + "!"
    message['From'] = "*****@*****.**"
    message['To'] = ";".join(targets)
    smtp.sendmail("*****@*****.**", targets, message.as_string())
    smtp.quit()
예제 #18
0
def sendEmail(message,emailto):
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.starttls()
    smtp.ehlo()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    smtp.sendmail("*****@*****.**", [ emailto ], message.as_string())
    smtp.quit()
예제 #19
0
def download(mod_id, mod_name, version):
    mod = Mod.query.filter(Mod.id == mod_id).first()
    if not mod:
        abort(404)
    if not mod.published and (not current_user or current_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()
    if not os.path.isfile(os.path.join(_cfg('storage'), version.download_path)):
        abort(404)
    # 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
    return send_file(os.path.join(_cfg('storage'), version.download_path), as_attachment = True)
예제 #20
0
파일: app.py 프로젝트: jemmy655/KerbalStuff
def hook_publish():
    print("Hook recieved")
    allow = False
    for ip in _cfg("hook_ips").split(","):
        parts = ip.split("/")
        range = 32
        if len(parts) != 1:
            range = int(parts[1])
        addr = networkMask(parts[0], range)
        if addressInNetwork(dottedQuadToNum(request.remote_addr), addr):
            allow = True
    if not allow:
        print("Hook ignored - not whitelisted IP")
        abort(403)
    print("Hook permitted")
    # Pull and restart site
    event = json.loads(request.data.decode("utf-8"))
    if not _cfg("hook_repository") == "%s/%s" % (event["repository"]["owner"]["name"], event["repository"]["name"]):
        return "ignored"
    if any("[noupdate]" in c["message"] for c in event["commits"]):
        return "ignored"
    if "refs/heads/" + _cfg("hook_branch") == event["ref"]:
        print("Updating on hook")
        subprocess.call(["git", "pull", "origin", "master"])
        subprocess.call(_cfg("restart_command").split())
        return "thanks"
    return "ignored"
예제 #21
0
def send_autoupdate_notification(mod):
    followers = [u.email for u in mod.followers]
    changelog = mod.default_version().changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    with open("emails/mod-autoupdated") as f:
        message = html.parser.HTMLParser().unescape(
            pystache.render(
                f.read(), {
                    'mod':
                    mod,
                    'domain':
                    _cfg("domain"),
                    'latest':
                    mod.default_version(),
                    'url':
                    '/mod/' + str(mod.id) + '/' +
                    secure_filename(mod.name)[:64],
                    'changelog':
                    changelog
                }))

# We (or rather just me) probably want that this is not dependent on KSP, since I know some people
# who run forks of KerbalStuff for non-KSP purposes.
# TODO(Thomas): Consider in putting the game name into a config.
    subject = mod.name + " is compatible with KSP " + mod.versions[
        0].ksp_version + "!"
    send_mail.delay(_cfg('support-mail'), targets, subject, message)
예제 #22
0
def singlegame_browse_updated(gameshort):
    if not gameshort:
        gameshort = "kerbal-space-program"
    ga = Game.query.filter(Game.short == gameshort).first()
    session["game"] = ga.id
    session["gamename"] = ga.name
    session["gameshort"] = ga.short
    session["gameid"] = ga.id
    mods = Mod.query.filter(
        Mod.published, Mod.game_id == ga.id, ModVersion.query.filter(ModVersion.mod_id == Mod.id).count() > 1
    ).order_by(desc(Mod.updated))
    total_pages = math.ceil(mods.count() / 30)
    page = request.args.get("page")
    if page:
        page = int(page)
        if page < 1:
            page = 1
        if page > total_pages:
            page = total_pages
    else:
        page = 1
    mods = mods.offset(30 * (page - 1)).limit(30)
    return render_template(
        "browse-list.html",
        mods=mods,
        page=page,
        total_pages=total_pages,
        ga=ga,
        url="/browse/updated",
        name="Recently Updated Mods",
        rss="/browse/updated.rss",
        site_name=_cfg("site-name"),
        support_mail=_cfg("support-mail"),
    )
예제 #23
0
def hook_publish():
    print("Hook recieved")
    allow = False
    for ip in _cfg("hook_ips").split(","):
        parts = ip.split("/")
        range = 32
        if len(parts) != 1:
            range = int(parts[1])
        addr = networkMask(parts[0], range)
        if addressInNetwork(dottedQuadToNum(request.remote_addr), addr):
            allow = True
    if not allow:
        print("Hook ignored - not whitelisted IP")
        abort(403)
    print("Hook permitted")
    # Pull and restart site
    event = json.loads(request.data.decode("utf-8"))
    if not _cfg("hook_repository") == "%s/%s" % (
            event["repository"]["owner"]["name"], event["repository"]["name"]):
        return "ignored"
    if any("[noupdate]" in c["message"] for c in event["commits"]):
        return "ignored"
    if "refs/heads/" + _cfg("hook_branch") == event["ref"]:
        print("Updating on hook")
        subprocess.call(["git", "pull", "origin", "master"])
        subprocess.call(_cfg("restart_command").split())
        return "thanks"
    return "ignored"
예제 #24
0
def send_autoupdate_notification(mod):
    if _cfg("smtp-host") == "":
        return
    followers = [u.email for u in mod.followers]
    changelog = mod.versions[-1].changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    for follower in followers:
        smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
        smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
        with open("emails/mod-autoupdated") as f:
            message = MIMEText(pystache.render(f.read(),
                {
                    'mod': mod,
                    'domain': _cfg("domain"),
                    'latest': mod.versions[-1],
                    'url': '/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64],
                    'changelog': changelog
                }))
        message['Subject'] = mod.name + " is compatible with KSP " + mod.versions[0].ksp_version + "!"
        message['From'] = "*****@*****.**"
        message['To'] = follower
        smtp.sendmail("*****@*****.**", [ follower ], message.as_string())
        smtp.quit()
예제 #25
0
def singlegame_browse_featured_rss(gameshort):
    if not gameshort:
        gameshort = "kerbal-space-program"
    ga = Game.query.filter(Game.short == gameshort).first()
    session["game"] = ga.id
    session["gamename"] = ga.name
    session["gameshort"] = ga.short
    session["gameid"] = ga.id
    mods = Featured.query.outerjoin(Mod).filter(Mod.game_id == ga.id).order_by(desc(Featured.created))
    mods = mods.limit(30)
    # Fix dates
    for f in mods:
        f.mod.created = f.created
    mods = [dumb_object(f.mod) for f in mods]
    db.rollback()
    return Response(
        render_template(
            "rss.xml",
            mods=mods,
            title="Featured mods on " + _cfg("site-name"),
            ga=ga,
            description="Featured mods on " + _cfg("site-name"),
            url="/browse/featured",
        ),
        mimetype="text/xml",
    )
예제 #26
0
def browse_updated_rss():
    mods = Mod.query.filter(Mod.published).order_by(desc(Mod.updated))
    mods = mods.limit(30)
    return Response(render_template("rss.xml", mods=mods, title="Recently updated on " + _cfg('site-name'),\
            description="Mods on " + _cfg('site-name') + " updated recently", \
            url="/browse/updated", site_name=_cfg('site-name'), support_mail=_cfg('support-mail')),
			mimetype="text/xml")
예제 #27
0
def singlegame_browse_all(gameshort):
    if not gameshort:
        gameshort = "kerbal-space-program"
    ga = Game.query.filter(Game.short == gameshort).first()
    session["game"] = ga.id
    session["gamename"] = ga.name
    session["gameshort"] = ga.short
    session["gameid"] = ga.id
    page = request.args.get("page")
    if page:
        page = int(page)
    else:
        page = 1
    mods, total_pages = search_mods(ga, "", page, 30)
    return render_template(
        "browse-list.html",
        mods=mods,
        page=page,
        total_pages=total_pages,
        ga=ga,
        url="/browse/all",
        name="All Mods",
        site_name=_cfg("site-name"),
        support_mail=_cfg("support-mail"),
    )
예제 #28
0
def send_autoupdate_notification(mod):
    if _cfg("smtp-host") == "":
        return
    followers = [u.email for u in mod.followers]
    changelog = mod.default_version().changelog
    if changelog:
        changelog = '\n'.join(['    ' + l for l in changelog.split('\n')])

    targets = list()
    for follower in followers:
        targets.append(follower)
    if len(targets) == 0:
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/mod-autoupdated") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(pystache.render(f.read(),
            {
                'mod': mod,
                'domain': _cfg("domain"),
                'latest': mod.default_version(),
                'url': '/mod/' + str(mod.id) + '/' + secure_filename(mod.name)[:64],
                'changelog': changelog
            })))
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = mod.name + " is compatible with KSP " + mod.versions[0].ksp_version + "!"
    message['From'] = "*****@*****.**"
    message['To'] = ";".join(targets)
    smtp.sendmail("*****@*****.**", targets, message.as_string())
    smtp.quit()
예제 #29
0
def browse_new_rss():
    mods = Mod.query.filter(Mod.published).order_by(desc(Mod.created))
    mods = mods.limit(30)
    return Response(render_template("rss.xml", mods=mods, title="New mods on " + _cfg('site-name'),\
            description="The newest mods on " + _cfg('site-name'), \
            url="/browse/new", site_name=_cfg('site-name'), support_mail=_cfg('support-mail')), 
			mimetype="text/xml")
예제 #30
0
def update_user_background(username):
    if current_user == None:
        return {'error': True, 'reason': 'You are not logged in.'}, 401
    user = User.query.filter(User.username == username).first()
    if not current_user.admin and current_user.username != user.username:
        return {
            'error': True,
            'reason': 'You are not authorized to edit this user\'s background'
        }, 403
    f = request.files['image']
    filetype = os.path.splitext(os.path.basename(f.filename))[1]
    if not filetype in ['.png', '.jpg']:
        return {
            'error': True,
            'reason': 'This file type is not acceptable.'
        }, 400
    filename = secure_filename(user.username) + filetype
    base_path = os.path.join(
        secure_filename(user.username) + '-' + str(time.time()) + '_' +
        str(user.id))
    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)
    try:
        os.remove(os.path.join(_cfg('storage'), user.backgroundMedia))
    except:
        pass  # who cares
    f.save(path)
    user.backgroundMedia = os.path.join(base_path, filename)
    return {'path': '/content/' + user.backgroundMedia}
예제 #31
0
def send_reset(user):
    with open("emails/password-reset") as f:
        message = html.parser.HTMLParser().unescape(\
                pystache.render(f.read(), { 'user': user, 'site-name': _cfg('site-name'), "domain": _cfg("domain"), 'confirmation': user.passwordReset }))
    send_mail.delay(_cfg('support-mail'), [user.email],
                    "Reset your password on " + _cfg('site-name'),
                    message,
                    important=True)
예제 #32
0
def send_confirmation(user, followMod=None):
    with open("emails/confirm-account") as f:
        if followMod != None:
            message = pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"),\
                    'confirmation': user.confirmation + "?f=" + followMod })
        else:
            message = html.parser.HTMLParser().unescape(\
                    pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"), 'confirmation': user.confirmation }))
    send_mail.delay("*****@*****.**", [ user.email ], "Welcome to Kerbal Stuff!", message, important=True)
예제 #33
0
def send_confirmation(user, followMod=None):
    with open("emails/confirm-account") as f:
        if followMod != None:
            message = pystache.render(f.read(), { 'user': user, 'site-name': _cfg('site-name'), "domain": _cfg("domain"),\
                    'confirmation': user.confirmation + "?f=" + followMod })
        else:
            message = html.parser.HTMLParser().unescape(\
                    pystache.render(f.read(), { 'user': user, 'site-name': _cfg('site-name'), "domain": _cfg("domain"), 'confirmation': user.confirmation }))
    send_mail.delay(_cfg('support-mail'), [ user.email ], "Welcome to " + _cfg('site-name') + "!", message, important=True)
예제 #34
0
def send_confirmation(user, followMod=None):
    with open("emails/confirm-account") as f:
        if followMod != None:
            message = pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"),\
                    'confirmation': user.confirmation + "?f=" + followMod })
        else:
            message = html.parser.HTMLParser().unescape(\
                    pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"), 'confirmation': user.confirmation }))
    send_mail.delay(_cfg('support-mail'), [ user.email ], "Welcome to " + _cfg('site-name') + "!", message, important=True)
예제 #35
0
파일: email.py 프로젝트: Majiir/KerbalStuff
def send_confirmation(user):
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/confirm-account") as f:
        message = MIMEText(pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"), 'confirmation': user.confirmation }))
    message['Subject'] = "Welcome to Kerbal Stuff!"
    message['From'] = "*****@*****.**"
    message['To'] = user.email
    smtp.sendmail("*****@*****.**", [ user.email ], message.as_string())
    smtp.quit()
예제 #36
0
def send_grant_notice(mod, user):
    with open("emails/grant-notice") as f:
        message = html.parser.HTMLParser().unescape(\
                pystache.render(f.read(), { 'user': user, 'site-name': _cfg('site-name'), "domain": _cfg("domain"),\
                'mod': mod, 'url': url_for('mods.mod', id=mod.id, mod_name=mod.name) }))
    send_mail.delay(_cfg('support-mail'), [user.email],
                    "You've been asked to co-author a mod on " +
                    _cfg('site-name'),
                    message,
                    important=True)
예제 #37
0
def connect_with_oauth():
    provider = request.form.get('provider')

    if not is_oauth_provider_configured(provider):
        return 'This install is not configured for login with %s' % provider

    oauth = get_oauth_provider(provider)
    callback = "{}://{}{}".format(_cfg("protocol"), _cfg("domain"),
            url_for('.connect_with_oauth_authorized_' + provider))
    return oauth.authorize(callback=callback)
예제 #38
0
def edit_list(list_id, list_name):
    mod_list = ModList.query.filter(ModList.id == list_id).first()
    if not mod_list:
        abort(404)
    editable = False
    if current_user:
        if current_user.admin:
            editable = True
        if current_user.id == mod_list.user_id:
            editable = True
    if not editable:
        abort(401)
    if request.method == 'GET':
        return render_template(
            "edit_list.html", **{
                'mod_list': mod_list,
                'mod_ids': [m.mod.id for m in mod_list.mods],
                "site_name": _cfg('site-name'),
                "support_mail": _cfg('support-mail')
            })
    else:
        description = request.form.get('description')
        background = request.form.get('background')
        bgOffsetY = request.form.get('bg-offset-y')
        mods = json.loads(request.form.get('mods'))
        mod_list.description = description
        if background and background != '':
            mod_list.background = background
        try:
            mod_list.bgOffsetY = int(bgOffsetY)
        except:
            pass
        # Remove mods
        removed_mods = [m for m in mod_list.mods if not m.mod_id in mods]
        for mod in removed_mods:
            mod_list.mods.remove(mod)

        # Add mods
        added_mods = [
            m for m in mods if not m in [mod.mod.id for mod in mod_list.mods]
        ]
        for m in added_mods:
            mod = Mod.query.filter(Mod.id == m).first()
            mli = ModListItem()
            mli.mod_id = mod.id
            mli.mod_list = mod_list
            mod_list.mods.append(mli)
            db.add(mli)
            db.commit()
        for mod in mod_list.mods:
            mod.sort_index = mods.index(mod.mod.id)
        return redirect(
            url_for("lists.view_list",
                    list_id=mod_list.id,
                    list_name=mod_list.name))
예제 #39
0
def browse():
    featured = Featured.query.order_by(desc(Featured.created)).limit(6)[:6]
    top = search_mods("", 1, 6)[:6][0]
    new = Mod.query.filter(Mod.published).order_by(desc(
        Mod.created)).limit(6)[:6]
    return render_template("browse.html",
                           featured=featured,
                           top=top,
                           new=new,
                           site_name=_cfg('site-name'),
                           support_mail=_cfg('support-mail'))
예제 #40
0
def register():
    if not _cfgb('registration'):
        return redirect("/")
    if request.method == 'POST':
        # Validate
        kwargs = dict()
        followMod = request.form.get('follow-mod')
        email = request.form.get('email')
        username = request.form.get('username')
        password = request.form.get('password')
        confirmPassword = request.form.get('repeatPassword')



        error = check_email_for_registration(email)
        if error:
            kwargs['emailError'] = error

        error = check_username_for_registration(username)
        if error:
            kwargs['usernameError'] = error

        if not password:
            kwargs['passwordError'] = 'Password is required.'
        else:
            if password != confirmPassword:
                kwargs['repeatPasswordError'] = 'Passwords do not match.'
            if len(password) < 5:
                kwargs['passwordError'] = 'Your password must be greater than 5 characters.'
            if len(password) > 256:
                kwargs['passwordError'] = 'We admire your dedication to security, but please use a shorter password.'
        if not kwargs == dict():
            # Fill in config values
            kwargs['site_name'] = _cfg('site-name')
            kwargs['support_mail'] = _cfg('support-mail')
            if email is not None:
                kwargs['email'] = email
            if username is not None:
                kwargs['username'] = username
            kwargs['registration'] = registration = _cfgb('registration')
            print("test")
            return render_template("register.html", **kwargs)
        # All valid, let's make them an account
        user = User(username, email, password)
        user.confirmation = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        db.add(user)
        db.commit() # We do this manually so that we're sure everything's hunky dory before the email leaves
        if followMod:
            send_confirmation(user, followMod)
        else:
            send_confirmation(user)
        return redirect("/account-pending")
    else:
        return render_template("register.html", **{ "site_name": _cfg('site-name'), "support_mail": _cfg('support-mail'), "registration": _cfgb('registration') })
예제 #41
0
def send_to_ckan(mod):
    if not _cfg("netkan_repo_path"):
        return
    if not mod.ckan:
        return
    json_blob = {
        'spec_version': 'v1.4',
        'identifier': re.sub(r'\W+', '', mod.name),
        '$kref': '#/ckan/spacedock/' + str(mod.id),
        'license': mod.license,
        'x_via': 'Automated ' + _cfg('site-name') + ' CKAN submission'
    }
    wd = _cfg("netkan_repo_path")
    path = os.path.join(wd, 'NetKAN', json_blob['identifier'] + '.netkan')

    if os.path.exists(path):
        # If the file is already there, then chances are this mod has already been indexed
        return

    with open(path, 'w') as f:
        f.write(json.dumps(json_blob, indent=4))
    subprocess.call(['git', 'fetch', 'upstream'], cwd=wd)
    subprocess.call([
        'git', 'checkout', '-b', 'add-' + json_blob['identifier'],
        'upstream/master'
    ],
                    cwd=wd)
    subprocess.call(['git', 'add', '-A'], cwd=wd)
    subprocess.call(['git', 'commit', '-m', 'Add {0} from '.format(mod.name) + _cfg('site-name') + '\n\nThis is an automated commit on behalf of {1}'\
            .format(mod.name, mod.user.username), '--author={0} <{1}>'.format(mod.user.username, mod.user.email)], cwd=wd)
    subprocess.call(
        ['git', 'push', '-u', 'origin', 'add-' + json_blob['identifier']],
        cwd=wd)
    g = Github(_cfg('github_user'), _cfg('github_pass'))
    r = g.get_repo("KSP-CKAN/NetKAN")
    r.create_pull(title="Add {0} from ".format(mod.name) + _cfg('site-name'), base=r.default_branch, head=_cfg('github_user') + ":add-" + json_blob['identifier'], body=\
"""\
This pull request was automatically generated by """ + _cfg('site-name') + """ on behalf of {0}, to add [{1}]({4}{2}) to CKAN.

Mod details:
    name = {2}
    author = {0}
    abstract = {6}
    license = {7}
    Homepage = {8}
    description = {5}

Please direct questions about this pull request to [{0}]({4}{3}).
""".format(mod.user.username, mod.name,\
    url_for('mods.mod', mod_name=mod.name, id=mod.id),\
    url_for("profile.view_profile", username=mod.user.username),\
    _cfg("protocol") + "://" + _cfg("domain"),\
    mod.description, mod.short_description,\
    mod.license, mod.external_link))
예제 #42
0
def send_reset(user):
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/password-reset") as f:
        message = MIMEText(pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"), 'confirmation': user.passwordReset }))
    message['X-MC-Important'] = "true"
    message['Subject'] = "Reset your password on Kerbal Stuff"
    message['From'] = "*****@*****.**"
    message['To'] = user.email
    smtp.sendmail("*****@*****.**", [ user.email ], message.as_string())
    smtp.quit()
예제 #43
0
def connect_with_oauth():
    provider = request.form.get('provider')

    if not is_oauth_provider_configured(provider):
        return 'This install is not configured for login with %s' % provider

    oauth = get_oauth_provider(provider)
    callback = "{}://{}{}".format(
        _cfg("protocol"), _cfg("domain"),
        url_for('.connect_with_oauth_authorized_' + provider))
    return oauth.authorize(callback=callback)
예제 #44
0
def browse_featured_rss():
    mods = Featured.query.order_by(desc(Featured.created))
    mods = mods.limit(30)
    # Fix dates
    for f in mods:
        f.mod.created = f.created
    mods = [dumb_object(f.mod) for f in mods]
    db.rollback()
    return Response(render_template("rss.xml", mods=mods, title="Featured mods on Kerbal Stuff",\
            description="Featured mods on Kerbal Stuff", \
            url="/browse/featured", site_name=_cfg('site-name'), support_mail=_cfg('support-mail')),
    mimetype="text/xml")
예제 #45
0
 def background_thumb(self):
     if (_cfg('thumbnail_size') == ''):
         return self.background
     thumbnailSizesStr = _cfg('thumbnail_size').split('x')
     thumbnailSize = (int(thumbnailSizesStr[0]), int(thumbnailSizesStr[1]))
     split = os.path.split(self.background)
     thumbPath = os.path.join(split[0], 'thumb_' + split[1])
     fullThumbPath = os.path.join(os.path.join(_cfg('storage'), thumbPath.replace('/content/', '')))
     fullImagePath = os.path.join(_cfg('storage'), self.background.replace('/content/', ''))
     if not os.path.exists(fullThumbPath):
         thumbnail.create(fullImagePath, fullThumbPath, thumbnailSize)
     return thumbPath
예제 #46
0
def browse_featured_rss():
    mods = Featured.query.order_by(desc(Featured.created))
    mods = mods.limit(30)
    # Fix dates
    for f in mods:
        f.mod.created = f.created
    mods = [dumb_object(f.mod) for f in mods]
    db.rollback()
    return Response(render_template("rss.xml", mods=mods, title="Featured mods on " + _cfg('site-name'),\
            description="Featured mods on " + _cfg('site-name'), \
            url="/browse/featured", site_name=_cfg('site-name'), support_mail=_cfg('support-mail')), 
			mimetype="text/xml")
예제 #47
0
def send_reset(user):
    if _cfg("smtp-host") == "":
        return
    with open("emails/password-reset") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(\
                pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"), 'confirmation': user.passwordReset })))
    message['X-MC-Important'] = "true"
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = "Reset your password on Planet RimWorld Mods"
    message['From'] = "*****@*****.**"
    message['To'] = user.email
    sendEmail(message,user.email)
예제 #48
0
def backend():
    users = User.query.count()
    new_users = User.query.order_by(desc(User.created)).limit(24)
    mods = Mod.query.count()
    versions = GameVersion.query.order_by(desc(GameVersion.id)).all()
    return render_template("admin.html",
                           users=users,
                           mods=mods,
                           new_users=new_users,
                           versions=versions,
                           site_name=_cfg('site-name'),
                           support_mail=_cfg('support-mail'))
예제 #49
0
def send_bulk_email(users, subject, body):
    if _cfg("smtp-host") == "":
        return
    for u in users:
        smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
        smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
        message = MIMEText(body)
        message['Subject'] = subject
        message['From'] = "*****@*****.**"
        message['To'] = u
        smtp.sendmail("*****@*****.**", [ u ], message.as_string())
        smtp.quit()
예제 #50
0
def browse_new_rss():
    mods = Mod.query.filter(Mod.published).order_by(desc(Mod.created))
    mods = mods.limit(30)
    return Response(
        render_template(
            "rss.xml",
            mods=mods,
            title="New mods on " + _cfg("site-name"),
            description="The newest mods on " + _cfg("site-name"),
            url="/browse/new",
        ),
        mimetype="text/xml",
    )
예제 #51
0
def send_grant_notice(mod, user):
    if _cfg("smtp-host") == "":
        return
    with open("emails/grant-notice") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(\
                pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"),\
                'mod': mod, 'url': url_for('mods.mod', id=mod.id, mod_name=mod.name) })))
    message['X-MC-Important'] = "true"
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = "You've been asked to co-author a mod on Planet RimWorld Mods"
    message['From'] = "*****@*****.**"
    message['To'] = user.email
    sendEmail(message,user.email)
예제 #52
0
def singlegame_browse_new_rss(gameshort):
    if not gameshort:
        gameshort = 'kerbal-space-program'
    ga = Game.query.filter(Game.short == gameshort).first()
    session['game'] = ga.id
    session['gamename'] = ga.name
    session['gameshort'] = ga.short
    session['gameid'] = ga.id
    mods = Mod.query.filter(Mod.published,
                            Mod.game_id == ga.id).order_by(desc(Mod.created))
    mods = mods.limit(30)
    return Response(render_template("rss.xml", mods=mods, title="New mods on " + _cfg('site-name'),ga = ga,\
            description="The newest mods on " + _cfg('site-name'), \
            url="/browse/new"), mimetype="text/xml")
예제 #53
0
def inject():
    ads = True
    first_visit = 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
    if request.cookies.get('first_visit') != None:
        first_visit = 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': current_user,
        'len': len,
        'any': any,
        'following_mod': following_mod,
        'following_user': following_user,
        'admin': is_admin(),
        'wrap_mod': wrap_mod,
        'dumb_object': dumb_object,
        'first_visit': first_visit,
        'request': request,
        'locale': locale,
        'url_for': url_for
    }
예제 #54
0
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
    }
예제 #55
0
def send_bulk_email(users, subject, body):
    if _cfg("smtp-host") == "":
        return
    targets = list()
    for u in users:
        targets.append(u)
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    message = MIMEText(body)
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = subject
    message['From'] = "*****@*****.**"
    message['To'] = ";".join(targets)
    smtp.sendmail("*****@*****.**", targets, message.as_string())
    smtp.quit()
예제 #56
0
def forgot_password():
    if request.method == 'GET':
        return render_template("forgot.html", **{ "site_name": _cfg('site-name'), "support_mail": _cfg('support-mail') })
    else:
        email = request.form.get('email')
        if not email:
            return render_template("forgot.html", **{ "bad_email": True, "site_name": _cfg('site-name'), "support_mail": _cfg('support-mail') })
        user = User.query.filter(User.email == email).first()
        if not user:
            return render_template("forgot.html", **{ "bad_email": True, "email": email, "site_name": _cfg('site-name'), "support_mail": _cfg('support-mail') })
        user.passwordReset = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        user.passwordResetExpiry = datetime.now() + timedelta(days=1)
        db.commit()
        send_reset(user)
        return render_template("forgot.html", **{ "success": True, "site_name": _cfg('site-name'), "support_mail": _cfg('support-mail') })
예제 #57
0
def send_reset(user):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/password-reset") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(\
                pystache.render(f.read(), { 'user': user, "domain": _cfg("domain"), 'confirmation': user.passwordReset })))
    message['X-MC-Important'] = "true"
    message['X-MC-PreserveRecipients'] = "false"
    message['Subject'] = "Reset your password on Kerbal Stuff"
    message['From'] = "*****@*****.**"
    message['To'] = user.email
    smtp.sendmail("*****@*****.**", [ user.email ], message.as_string())
    smtp.quit()