diff --git a/db.py b/db.py index 081c4649..71c1be2e 100644 --- a/db.py +++ b/db.py @@ -45,7 +45,7 @@ class Telegram(Base): __tablename__ = "telegram" royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="telegram", lazy="joined") telegram_id = Column(BigInteger, primary_key=True) first_name = Column(String, nullable=False) @@ -91,7 +91,7 @@ class Steam(Base): __tablename__ = "steam" royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="steam", lazy="joined") steam_id = Column(String, primary_key=True) persona_name = Column(String) @@ -172,7 +172,7 @@ class RocketLeague(Base): __tablename__ = "rocketleague" steam_id = Column(String, ForeignKey("steam.steam_id"), primary_key=True) - steam = relationship("Steam", lazy="joined") + steam = relationship("Steam", backref="rl", lazy="joined") season = Column(Integer) @@ -299,7 +299,7 @@ class Dota(Base): __tablename__ = "dota" steam_id = Column(String, ForeignKey("steam.steam_id"), primary_key=True) - steam = relationship("Steam", lazy="joined") + steam = relationship("Steam", backref="dota", lazy="joined") rank_tier = Column(Integer) @@ -398,7 +398,7 @@ class LeagueOfLegends(Base): __tablename__ = "leagueoflegends" royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="lol", lazy="joined") summoner_id = Column(BigInteger, primary_key=True) summoner_name = Column(String, nullable=False) @@ -482,7 +482,7 @@ class Osu(Base): __tablename__ = "osu" royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="osu", lazy="joined") osu_id = Column(Integer, primary_key=True) osu_name = Column(String, nullable=False) @@ -540,7 +540,7 @@ class Discord(Base): __table_args__ = tuple(UniqueConstraint("name", "discriminator")) royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="discord", lazy="joined") discord_id = Column(BigInteger, primary_key=True) name = Column(String, nullable=False) @@ -584,7 +584,7 @@ class Overwatch(Base): __tablename__ = "overwatch" royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="overwatch", lazy="joined") battletag = Column(String, primary_key=True) discriminator = Column(Integer, primary_key=True) @@ -669,9 +669,9 @@ class Diario(Base): id = Column(Integer, primary_key=True) timestamp = Column(DateTime, nullable=False) saver_id = Column(Integer, ForeignKey("telegram.telegram_id")) - saver = relationship("Telegram", foreign_keys=saver_id, lazy="joined") + saver = relationship("Telegram", foreign_keys=saver_id, backref="diario_saves", lazy="joined") author_id = Column(Integer, ForeignKey("telegram.telegram_id")) - author = relationship("Telegram", foreign_keys=author_id, lazy="joined") + author = relationship("Telegram", foreign_keys=author_id, backref="diario_authored", lazy="joined") text = Column(String) def __repr__(self): @@ -725,7 +725,7 @@ class BaluRage(Base): id = Column(Integer, primary_key=True) royal_id = Column(Integer, ForeignKey("royals.id")) - royal = relationship("Royal", lazy="joined") + royal = relationship("Royal", backref="times_raged", lazy="joined") reason = Column(String) def __repr__(self): @@ -737,7 +737,7 @@ class PlayedMusic(Base): id = Column(Integer, primary_key=True) enqueuer_id = Column(BigInteger, ForeignKey("discord.discord_id")) - enqueuer = relationship("Discord", lazy="joined") + enqueuer = relationship("Discord", backref="music_played", lazy="joined") filename = Column(String) def __repr__(self): @@ -798,9 +798,9 @@ class VoteAnswer(Base): __tablename__ = "voteanswer" question_id = Column(Integer, ForeignKey("votequestion.id")) - question = relationship("VoteQuestion") + question = relationship("VoteQuestion", backref="answers", lazy="joined") user_id = Column(BigInteger, ForeignKey("telegram.telegram_id")) - user = relationship("Telegram") + user = relationship("Telegram", backref="votes_cast", lazy="joined") choice = Column(Enum(VoteChoices), nullable=False) __table_args__ = (PrimaryKeyConstraint("question_id", "user_id"),) @@ -827,8 +827,27 @@ class CustomCSS(Base): css = Column(Text, nullable=False) +class WikiEntry(Base): + __tablename__ = "wikientries" + + key = Column(String, primary_key=True) + content = Column(Text, nullable=False) + + +class WikiLog(Base): + __tablename__ = "wikilog" + + edit_id = Column(Integer, primary_key=True) + editor_id = Column(Integer, ForeignKey("royals.id"), nullable=False) + editor = relationship("Royal", backref="wiki_edits", lazy="joined") + edited_key = Column(String, ForeignKey("wikientries.key"), nullable=False) + edited = relationship("WikiEntry", backref="edit_logs", lazy="joined") + timestamp = Column(DateTime, nullable=False) + reason = Column(Text) + + # If run as script, create all the tables in the db if __name__ == "__main__": print("Creating new tables...") Base.metadata.create_all(bind=engine) - print("Done!") \ No newline at end of file + print("Done!") diff --git a/discordbot.py b/discordbot.py index 5233aa2d..ae928cd0 100644 --- a/discordbot.py +++ b/discordbot.py @@ -260,7 +260,7 @@ def command(func): return new_func -def requires_cv(func): +def requires_voice_client(func): "Decorator. Ensures the voice client is connected before running the command." async def new_func(channel: discord.Channel, author: discord.Member, params: typing.List[str], *args, **kwargs): global voice_client @@ -331,7 +331,7 @@ async def add_video_from_file(file): @command -@requires_cv +@requires_voice_client async def cmd_play(channel: discord.Channel, author: discord.Member, params: typing.List[str]): if len(params) < 2: await client.send_message(channel, "⚠ Non hai specificato una canzone da riprodurre!\n" @@ -365,7 +365,7 @@ async def cmd_play(channel: discord.Channel, author: discord.Member, params: typ @command -@requires_cv +@requires_voice_client async def cmd_skip(channel: discord.Channel, author: discord.Member, params: typing.List[str]): global voice_player if voice_player is None: @@ -376,7 +376,7 @@ async def cmd_skip(channel: discord.Channel, author: discord.Member, params: typ @command -@requires_cv +@requires_voice_client async def cmd_remove(channel: discord.Channel, author: discord.Member, params: typing.List[str]): if len(voice_queue) == 0: await client.send_message(channel, "⚠ Non c'è nessun video in coda.") @@ -443,7 +443,7 @@ async def cmd_queue(channel: discord.Channel, author: discord.Member, params: ty @command -@requires_cv +@requires_voice_client async def cmd_shuffle(channel: discord.Channel, author: discord.Member, params: typing.List[str]): if len(voice_queue) == 0: await client.send_message(channel, "⚠ Non ci sono video in coda!") @@ -453,7 +453,7 @@ async def cmd_shuffle(channel: discord.Channel, author: discord.Member, params: @command -@requires_cv +@requires_voice_client async def cmd_clear(channel: discord.Channel, author: discord.Member, params: typing.List[str]): global voice_queue if len(voice_queue) == 0: @@ -463,6 +463,15 @@ async def cmd_clear(channel: discord.Channel, author: discord.Member, params: ty await client.send_message(channel, ":regional_indicator_x: Tutti i video in coda rimossi.") +@command +@requires_voice_client +async def cmd_dump_voice_player_error(channel: discord.Channel, author: discord.Member, params: typing.List[str]): + global voice_player + if voice_player is None: + return + await client.send_message(channel, f"```\n{str(voice_player.error)}\n```") + + async def queue_predownload_videos(): while True: for index, video in enumerate(voice_queue[:int(config["YouTube"]["predownload_videos"])].copy()): @@ -522,7 +531,8 @@ async def queue_play_next_video(): voice_player = await now_playing.create_player() voice_player.start() await client.change_presence(game=discord.Game(name=now_playing.plain_text(), type=2)) - await client.send_message(client.get_channel(config["Discord"]["main_channel"]), f":arrow_forward: Ora in riproduzione: {str(now_playing)}") + await client.send_message(client.get_channel(config["Discord"]["main_channel"]), + f":arrow_forward: Ora in riproduzione: {str(now_playing)}") del voice_queue[0] @@ -540,7 +550,8 @@ commands = { "!queue": cmd_queue, "!q": cmd_queue, "!shuffle": cmd_shuffle, - "!clear": cmd_clear + "!clear": cmd_clear, + "!dump_vp": cmd_dump_voice_player_error } diff --git a/requirements.txt b/requirements.txt index 5c40c6eb..674fc723 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ psycopg2-binary PyNaCl async_timeout raven -bcrypt \ No newline at end of file +bcrypt +markdown \ No newline at end of file diff --git a/static/nryg.less b/static/nryg.less index aea5408e..e94aa47e 100644 --- a/static/nryg.less +++ b/static/nryg.less @@ -23,6 +23,36 @@ input[type="text"], input[type="password"] { font-family: sans-serif; } +textarea { + background-color: rgba(red(@text-color), green(@text-color), blue(@text-color), 0.1); + color: @text-color; + font-size: small; + font-family: "Consolas", "Source Code Pro", monospace; + padding: 2px; + margin: 1px; + border: 1px dotted @text-color; + width: 100%; +} + +button, input[type="submit"] { + background-color: rgba(red(@text-color), green(@text-color), blue(@text-color), 0.1); + border-radius: 0; + border: 1px solid @text-color; + color: @text-color; + padding: 2px; + padding-left: 8px; + padding-right: 8px; + margin: 1px; + font-size: medium; + font-family: sans-serif; +} + +button:hover, input[type="submit"]:hover { + background-color: rgba(red(@text-color), green(@text-color), blue(@text-color), 0.3); + color: @accent-color; + border: 1px solid @accent-color; +} + .input-grid { display: grid; @@ -442,6 +472,16 @@ input[type="text"], input[type="password"] { } } +.wiki { + .wiki-log { + font-family: "Consolas", "Source Code Pro", monospace; + + .last-reason { + font-style: italic; + } + } +} + #edit-css { font-size: medium; } \ No newline at end of file diff --git a/telegrambot.py b/telegrambot.py index b43cf553..7bd383ed 100644 --- a/telegrambot.py +++ b/telegrambot.py @@ -451,7 +451,6 @@ def cmd_wheel(bot: Bot, update: Update): session.close() - def process(arg_discord_connection): print("Telegrambot starting...") if arg_discord_connection is not None: diff --git a/templates/main.html b/templates/main.html index 65a1ca01..a09493b3 100644 --- a/templates/main.html +++ b/templates/main.html @@ -9,14 +9,28 @@ Royal Games

- Benvenuto al sito web della Royal Games! E' ancora un po' triste e spoglio, ma spero che collaboriate a migliorarlo! -

-

- Attualmente, sto sviluppando i profili RYG! + Benvenuto al sito web della Royal Games! Sta lentamente migliorando, ma spero che comunque collaboriate a migliorarlo!

+

Profili

+

Giochi

+ +

Wiki

+ {% endblock %} \ No newline at end of file diff --git a/templates/wiki.html b/templates/wiki.html new file mode 100644 index 00000000..44428e6b --- /dev/null +++ b/templates/wiki.html @@ -0,0 +1,31 @@ +{% extends 'base.html' %} + +{% block pagetitle %} + {{ key }} +{% endblock %} + +{% block body %} +
+

+ {{ key }} +

+ {% if wiki_page %} +
+ {{ converted_md }} +
+
+ Ultima modifica di {{ wiki_log.editor.username }} alle {{ wiki_log.timestamp.isoformat() }}{% if wiki_log.reason %}, motivo: {{ wiki_log.reason }}{% endif %} +
+ {% endif %} + {% if session.get('user_id', '') %} +

Modifica

+
+
+
+
+ +
+
+ {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/webserver.py b/webserver.py index 337fa855..a19734d7 100644 --- a/webserver.py +++ b/webserver.py @@ -1,8 +1,11 @@ -from flask import Flask, render_template, request, abort, redirect, url_for +from flask import Flask, render_template, request, abort, redirect, url_for, Markup, escape from flask import session as fl_session import db import bcrypt import configparser +import markdown +import datetime +import telegram app = Flask(__name__) @@ -14,6 +17,7 @@ config.read("config.ini") app.secret_key = config["Flask"]["secret_key"] +telegram_bot = telegram.Bot(config["Telegram"]["bot_token"]) @app.route("/") def page_main(): @@ -57,7 +61,7 @@ def page_loggedin(): user = db_session.query(db.Royal).filter_by(username=username).one_or_none() db_session.close() if user is None: - abort(403) + abort(401) return if user.password is None: fl_session["user_id"] = user.id @@ -66,7 +70,7 @@ def page_loggedin(): fl_session["user_id"] = user.id return redirect(url_for("page_main")) else: - abort(403) + abort(401) return @@ -75,7 +79,7 @@ def page_password(): user_id = fl_session.get("user_id") if request.method == "GET": if user_id is None: - abort(403) + abort(401) return return render_template("password.html") elif request.method == "POST": @@ -89,7 +93,7 @@ def page_password(): return redirect(url_for("page_main")) else: db_session.close() - abort(403) + abort(401) return @@ -101,12 +105,12 @@ def page_setcss(): if request.method == "GET": db_session.close() if user_id is None: - abort(403) + abort(401) return return render_template("setcss.html", css=ccss.css) elif request.method == "POST": if user_id is None: - abort(403) + abort(401) return css = request.form.get("css", "") if "", methods=["GET", "POST"]) +def page_wiki(key: str): + db_session = db.Session() + wiki_page = db_session.query(db.WikiEntry).filter_by(key=key).one_or_none() + if request.method == "GET": + wiki_latest_edit = db_session.query(db.WikiLog).filter_by(edited_key=key) \ + .order_by(db.WikiLog.timestamp.desc()).first() + db_session.close() + if wiki_page is None: + return render_template("wiki.html", key=key) + converted_md = Markup(markdown.markdown(escape(wiki_page.content))) + return render_template("wiki.html", key=key, wiki_page=wiki_page, converted_md=converted_md, + wiki_log=wiki_latest_edit) + elif request.method == "POST": + user_id = fl_session.get('user_id') + user = db_session.query(db.Royal).filter_by(id=user_id).one() + if user_id is None: + db_session.close() + abort(401) + return + if wiki_page is None: + wiki_page = db.WikiEntry(key=key, content=request.form.get("content")) + db_session.add(wiki_page) + db_session.flush() + else: + wiki_page.content = request.form.get("content") + edit_reason = request.form.get("reason") + new_log = db.WikiLog(editor=user, edited_key=key, timestamp=datetime.datetime.now(), reason=edit_reason) + db_session.add(new_log) + db_session.commit() + telegram_bot.send_message(config["Telegram"]["main_group"], + f'ℹ️ La pagina wiki {key} è stata' + f' modificata da' + f' {user.username}:' + f' {"Nessun motivo specificato." if not edit_reason else edit_reason}', + parse_mode="HTML") + return redirect(url_for("page_wiki", key=key)) + + if __name__ == "__main__": try: - app.run(host="0.0.0.0", port=1234, debug=__debug__) + app.run(host="0.0.0.0", port=1235, debug=__debug__) except KeyboardInterrupt: pass