Merge remote-tracking branch 'origin/master' into queue_v3
# Conflicts: # discordbot.py # template_config.ini
5
.gitattributes
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.woff filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
6
.gitignore
vendored
|
@ -1,9 +1,11 @@
|
|||
config.ini
|
||||
.idea/
|
||||
.vscode/
|
||||
__pycache__
|
||||
diario.json
|
||||
libopus-0.dll
|
||||
music.opus
|
||||
opusfiles/
|
||||
ignored/*
|
||||
markovmodel.json
|
||||
ignored/
|
||||
markovmodels/
|
||||
logs/
|
||||
|
|
2
application.wsgi
Normal file
|
@ -0,0 +1,2 @@
|
|||
import webserver
|
||||
application = webserver.app
|
31
awardfiorygi.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
import telegram
|
||||
import configparser
|
||||
import db
|
||||
import strings
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read("config.ini")
|
||||
|
||||
|
||||
telegram_bot = telegram.Bot(config["Telegram"]["bot_token"])
|
||||
session = db.Session()
|
||||
|
||||
|
||||
name = input("Utente Royalnet: ")
|
||||
user = session.query(db.Royal).filter(db.Royal.username == name).one()
|
||||
number = int(input("Fiorygi da aggiungere: "))
|
||||
user.fiorygi += number
|
||||
reason = input("Motivazione: ")
|
||||
fiorygi = f"fioryg{'i' if number != 1 else ''}"
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
strings.safely_format_string(strings.TELEGRAM.FIORYGI_AWARDED,
|
||||
words={
|
||||
"mention": user.telegram[0].mention(),
|
||||
"number": str(number),
|
||||
"fiorygi": fiorygi,
|
||||
"reason": reason
|
||||
}),
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True)
|
||||
session.commit()
|
||||
session.close()
|
79
cast.py
|
@ -1,79 +0,0 @@
|
|||
import random
|
||||
import math
|
||||
import db
|
||||
|
||||
|
||||
def cast(spell_name: str, target_name: str, platform: str) -> str:
|
||||
spell = spell_name.capitalize()
|
||||
# Seed the rng with the spell name
|
||||
# so that spells always deal the same damage
|
||||
random.seed(spell)
|
||||
dmg_dice = random.randrange(1, 11)
|
||||
dmg_max = random.sample([4, 6, 8, 10, 12, 20, 100], 1)[0]
|
||||
dmg_mod = random.randrange(math.floor(-dmg_max / 5), math.ceil(dmg_max / 5) + 1)
|
||||
dmg_type = random.sample(["da fuoco", "da freddo", "elettrici", "sonici", "necrotici", "magici",
|
||||
"da acido", "divini", "nucleari", "psichici", "fisici", "puri", "da taglio",
|
||||
"da perforazione", "da impatto", "da caduta", "gelato", "onnipotenti", "oscuri",
|
||||
"di luce", "da velocità", "da cactus", "meta", "dannosi", "da radiazione",
|
||||
"tuamammici", "da maledizione", "pesanti", "leggeri", "immaginari", "da laser",
|
||||
"da neutrini", "galattici", "cerebrali", "ritardati", "ritardanti"], 1)[0]
|
||||
# Reseed the rng with a random value
|
||||
# so that the dice roll always deals a different damage
|
||||
random.seed()
|
||||
total = dmg_mod
|
||||
# Check for a critical hit
|
||||
crit = 1
|
||||
while True:
|
||||
crit_die = random.randrange(1, 21)
|
||||
if crit_die == 20:
|
||||
crit *= 2
|
||||
else:
|
||||
break
|
||||
for dice in range(0, dmg_dice):
|
||||
total += random.randrange(1, dmg_max + 1)
|
||||
if crit > 1:
|
||||
if platform == "telegram":
|
||||
crit_msg = f"<b>CRITICO ×{crit}{'!' * crit}</b>\n"
|
||||
elif platform == "discord":
|
||||
crit_msg = f"**CRITICO ×{crit}{'!' * crit}**\n"
|
||||
total *= crit
|
||||
else:
|
||||
crit_msg = ""
|
||||
if platform == "telegram":
|
||||
if dmg_dice == 10 and dmg_max == 100 and dmg_mod == 20:
|
||||
return f"❇️‼️ Ho lanciato <b>{spell}</b> su " \
|
||||
f"<i>{target_name}</i>.\n" \
|
||||
f"Una grande luce illumina il cielo, seguita poco dopo da un fungo di fumo nel luogo" \
|
||||
f" in cui si trovava <i>{target_name}</i>.\n" \
|
||||
f"Il fungo si espande a velocità smodata, finchè il fumo non ricopre la Terra intera e le tenebre" \
|
||||
f" cadono su di essa.\n" \
|
||||
f"Dopo qualche minuto, la temperatura ambiente raggiunge gli 0 °C, e continua a diminuire.\n" \
|
||||
f"L'Apocalisse Nucleare è giunta, e tutto per polverizzare <i>{target_name}</i>" \
|
||||
f" con <b>{spell}</b>.\n" \
|
||||
f"<i>{target_name}</i> subisce 10d100+20=<b>9999</b> danni apocalittici!"
|
||||
return f"❇️ Ho lanciato <b>{spell}</b> su " \
|
||||
f"<i>{target_name}</i>.\n" \
|
||||
f"{crit_msg}" \
|
||||
f"<i>{target_name}</i> subisce {dmg_dice}d{dmg_max}" \
|
||||
f"{'+' if dmg_mod > 0 else ''}{str(dmg_mod) if dmg_mod != 0 else ''}" \
|
||||
f"{'×' + str(crit) if crit > 1 else ''}" \
|
||||
f"=<b>{total if total > 0 else 0}</b> danni {dmg_type}!"
|
||||
elif platform == "discord":
|
||||
if dmg_dice == 10 and dmg_max == 100 and dmg_mod == 20:
|
||||
return f"❇️‼️ Ho lanciato **{spell}** su " \
|
||||
f"_{target_name}_.\n" \
|
||||
f"Una grande luce illumina il cielo, seguita poco dopo da un fungo di fumo nel luogo" \
|
||||
f" in cui si trovava _{target_name}_.\n" \
|
||||
f"Il fungo si espande a velocità smodata, finchè il fumo non ricopre la Terra intera e le tenebre" \
|
||||
f" cadono su di essa.\n" \
|
||||
f"Dopo qualche minuto, la temperatura ambiente raggiunge gli 0 °C, e continua a diminuire.\n" \
|
||||
f"L'Apocalisse Nucleare è giunta, e tutto per polverizzare _{target_name}_" \
|
||||
f" con **{spell}**.\n" \
|
||||
f"_{target_name}_ subisce 10d100+20=**9999** danni apocalittici!"
|
||||
return f"❇️ Ho lanciato **{spell}** su " \
|
||||
f"_{target_name}_.\n" \
|
||||
f"{crit_msg}" \
|
||||
f"_{target_name}_ subisce {dmg_dice}d{dmg_max}" \
|
||||
f"{'+' if dmg_mod > 0 else ''}{str(dmg_mod) if dmg_mod != 0 else ''}" \
|
||||
f"{'×' + str(crit) if crit > 1 else ''}" \
|
||||
f"=**{total if total > 0 else 0}** danni {dmg_type}!"
|
14
chatasthebot.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import telegram
|
||||
import configparser
|
||||
config = configparser.ConfigParser()
|
||||
config.read("config.ini")
|
||||
|
||||
|
||||
telegram_bot = telegram.Bot(config["Telegram"]["bot_token"])
|
||||
|
||||
|
||||
while True:
|
||||
message = input()
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"], message,
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True)
|
601
db.py
|
@ -1,29 +1,35 @@
|
|||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import typing
|
||||
import time
|
||||
|
||||
import coloredlogs
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker, relationship
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
# noinspection PyUnresolvedReferences
|
||||
from sqlalchemy import Column, BigInteger, Integer, String, DateTime, ForeignKey, Float, Enum, create_engine, \
|
||||
UniqueConstraint, PrimaryKeyConstraint, Boolean, LargeBinary, Text, Date, func
|
||||
from sqlalchemy.inspection import inspect
|
||||
import requests
|
||||
from errors import NotFoundError, AlreadyExistingError, PrivateError
|
||||
from utils.errors import NotFoundError, AlreadyExistingError, PrivateError
|
||||
import re
|
||||
import enum
|
||||
# Both packages have different pip names
|
||||
# noinspection PyPackageRequirements
|
||||
from discord import User as DiscordUser
|
||||
# noinspection PyPackageRequirements
|
||||
from telegram import User as TelegramUser
|
||||
import loldata
|
||||
from dirty import Dirty
|
||||
import query_discord_music
|
||||
from utils.dirty import Dirty, DirtyDelta
|
||||
import sql_queries
|
||||
from flask import escape
|
||||
import configparser
|
||||
import typing
|
||||
from utils import MatchmakingStatus, errors
|
||||
import strings
|
||||
if typing.TYPE_CHECKING:
|
||||
# noinspection PyPackageRequirements
|
||||
from discord import User as DiscordUser
|
||||
# noinspection PyPackageRequirements
|
||||
from telegram import User as TelegramUser
|
||||
|
||||
# Init the config reader
|
||||
import configparser
|
||||
config = configparser.ConfigParser()
|
||||
config.read("config.ini")
|
||||
|
||||
|
@ -38,7 +44,76 @@ os.environ["COLOREDLOGS_LOG_FORMAT"] = "%(asctime)s %(levelname)s %(name)s %(mes
|
|||
coloredlogs.install(level="DEBUG", logger=logger)
|
||||
|
||||
|
||||
class Royal(Base):
|
||||
def relationship_name_search(_class, keyword) -> typing.Optional[tuple]:
|
||||
"""Recursively find a relationship with a given name."""
|
||||
inspected = set()
|
||||
|
||||
def search(_mapper, chain):
|
||||
inspected.add(_mapper)
|
||||
relationships = _mapper.relationships
|
||||
try:
|
||||
return chain + (relationships[keyword],)
|
||||
except KeyError:
|
||||
for _relationship in set(relationships):
|
||||
if _relationship.mapper in inspected:
|
||||
continue
|
||||
result = search(_relationship.mapper, chain + (_relationship,))
|
||||
if result is not None:
|
||||
return result
|
||||
return None
|
||||
|
||||
return search(inspect(_class), tuple())
|
||||
|
||||
|
||||
def relationship_link_chain(starting_class, ending_class) -> typing.Optional[tuple]:
|
||||
"""Find the path to follow to get from the starting table to the ending table."""
|
||||
inspected = set()
|
||||
|
||||
def search(_mapper, chain):
|
||||
inspected.add(_mapper)
|
||||
if _mapper.class_ == ending_class:
|
||||
return chain
|
||||
relationships = _mapper.relationships
|
||||
for _relationship in set(relationships):
|
||||
if _relationship.mapper in inspected:
|
||||
continue
|
||||
try:
|
||||
return search(_relationship.mapper, chain + (_relationship,))
|
||||
except errors.NotFoundError:
|
||||
continue
|
||||
raise errors.NotFoundError()
|
||||
|
||||
return search(inspect(starting_class), tuple())
|
||||
|
||||
|
||||
class Mini(object):
|
||||
"""Mixin for every table that has an associated mini."""
|
||||
_mini_full_name = NotImplemented
|
||||
_mini_name = NotImplemented
|
||||
_mini_order = NotImplemented
|
||||
|
||||
@classmethod
|
||||
def mini_get_all(cls, session: Session) -> list:
|
||||
return session.query(cls).order_by(*cls._mini_order).all()
|
||||
|
||||
@classmethod
|
||||
def mini_get_single(cls, session: Session, **kwargs):
|
||||
return session.query(cls).filter_by(**kwargs).one_or_none()
|
||||
|
||||
@classmethod
|
||||
def mini_get_single_from_royal(cls, session: Session, royal: "Royal"):
|
||||
chain = relationship_link_chain(cls, Royal)
|
||||
if chain is None:
|
||||
chain = tuple()
|
||||
start = session.query(cls)
|
||||
for connection in chain:
|
||||
start = start.join(connection.mapper.class_)
|
||||
start = start.filter(Royal.id == royal.id)
|
||||
mini = start.one()
|
||||
return mini
|
||||
|
||||
|
||||
class Royal(Base, Mini):
|
||||
__tablename__ = "royals"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
@ -47,6 +122,11 @@ class Royal(Base):
|
|||
role = Column(String)
|
||||
fiorygi = Column(Integer, default=0)
|
||||
member_since = Column(Date)
|
||||
special_title = Column(String)
|
||||
|
||||
_mini_full_name = "Royalnet"
|
||||
_mini_name = "ryg"
|
||||
_mini_order = [fiorygi.desc()]
|
||||
|
||||
@staticmethod
|
||||
def create(session: Session, username: str):
|
||||
|
@ -58,8 +138,12 @@ class Royal(Base):
|
|||
def __repr__(self):
|
||||
return f"<db.Royal {self.username}>"
|
||||
|
||||
@classmethod
|
||||
def mini_get_single_from_royal(cls, session: Session, royal: "Royal"):
|
||||
return royal
|
||||
|
||||
class Telegram(Base):
|
||||
|
||||
class Telegram(Base, Mini):
|
||||
__tablename__ = "telegram"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"))
|
||||
|
@ -70,8 +154,12 @@ class Telegram(Base):
|
|||
last_name = Column(String)
|
||||
username = Column(String)
|
||||
|
||||
_mini_full_name = "Telegram"
|
||||
_mini_name = "tg"
|
||||
_mini_order = [telegram_id]
|
||||
|
||||
@staticmethod
|
||||
def create(session: Session, royal_username, telegram_user: TelegramUser):
|
||||
def create(session: Session, royal_username, telegram_user: "TelegramUser"):
|
||||
t = session.query(Telegram).filter_by(telegram_id=telegram_user.id).first()
|
||||
if t is not None:
|
||||
raise AlreadyExistingError(repr(t))
|
||||
|
@ -104,8 +192,12 @@ class Telegram(Base):
|
|||
else:
|
||||
return self.first_name
|
||||
|
||||
@classmethod
|
||||
def mini_get_single_from_royal(cls, session: Session, royal: "Royal"):
|
||||
return royal.telegram
|
||||
|
||||
class Steam(Base):
|
||||
|
||||
class Steam(Base, Mini):
|
||||
__tablename__ = "steam"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"))
|
||||
|
@ -117,6 +209,10 @@ class Steam(Base):
|
|||
trade_token = Column(String)
|
||||
most_played_game_id = Column(BigInteger)
|
||||
|
||||
_mini_full_name = "Steam"
|
||||
_mini_name = "steam"
|
||||
_mini_order = [steam_id]
|
||||
|
||||
def __repr__(self):
|
||||
if not self.persona_name:
|
||||
return f"<db.Steam {self.steam_id}>"
|
||||
|
@ -192,8 +288,12 @@ class Steam(Base):
|
|||
return
|
||||
self.most_played_game_id = j["response"]["games"][0]["appid"]
|
||||
|
||||
@classmethod
|
||||
def mini_get_single_from_royal(cls, session: Session, royal: "Royal"):
|
||||
return royal.steam
|
||||
|
||||
class RocketLeague(Base):
|
||||
|
||||
class RocketLeague(Base, Mini):
|
||||
__tablename__ = "rocketleague"
|
||||
|
||||
steam_id = Column(String, ForeignKey("steam.steam_id"), primary_key=True)
|
||||
|
@ -219,6 +319,13 @@ class RocketLeague(Base):
|
|||
|
||||
wins = Column(Integer)
|
||||
|
||||
_mini_full_name = "Rocket League"
|
||||
_mini_name = "rl"
|
||||
_mini_order = [solo_std_mmr.desc().nullslast(),
|
||||
doubles_mmr.desc().nullslast(),
|
||||
standard_mmr.desc().nullslast(),
|
||||
single_mmr.desc().nullslast()]
|
||||
|
||||
def __repr__(self):
|
||||
return f"<db.RocketLeague {self.steam_id}>"
|
||||
|
||||
|
@ -254,19 +361,21 @@ class RocketLeague(Base):
|
|||
return f"https://rocketleaguestats.com/assets/img/rocket_league/ranked/season_four/{rank}.png"
|
||||
|
||||
|
||||
class Dota(Base):
|
||||
class Dota(Base, Mini):
|
||||
__tablename__ = "dota"
|
||||
|
||||
steam_id = Column(String, ForeignKey("steam.steam_id"), primary_key=True)
|
||||
steam = relationship("Steam", backref="dota", lazy="joined")
|
||||
|
||||
rank_tier = Column(Integer)
|
||||
|
||||
wins = Column(Integer)
|
||||
losses = Column(Integer)
|
||||
|
||||
most_played_hero = Column(Integer)
|
||||
|
||||
_mini_full_name = "DOTA 2"
|
||||
_mini_name = "dota"
|
||||
_mini_order = [rank_tier.desc().nullslast(), wins.desc().nullslast()]
|
||||
|
||||
def __repr__(self):
|
||||
return f"<db.Dota {self.steam_id}>"
|
||||
|
||||
|
@ -365,7 +474,7 @@ class RomanNumerals(enum.Enum):
|
|||
return self.name
|
||||
|
||||
|
||||
class LeagueOfLegends(Base):
|
||||
class LeagueOfLegends(Base, Mini):
|
||||
__tablename__ = "leagueoflegends"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"))
|
||||
|
@ -375,7 +484,6 @@ class LeagueOfLegends(Base):
|
|||
summoner_id = Column(String, primary_key=True)
|
||||
account_id = Column(String)
|
||||
summoner_name = Column(String)
|
||||
|
||||
level = Column(Integer)
|
||||
solo_division = Column(Enum(LeagueOfLegendsRanks))
|
||||
solo_rank = Column(Enum(RomanNumerals))
|
||||
|
@ -383,9 +491,17 @@ class LeagueOfLegends(Base):
|
|||
flex_rank = Column(Enum(RomanNumerals))
|
||||
twtr_division = Column(Enum(LeagueOfLegendsRanks))
|
||||
twtr_rank = Column(Enum(RomanNumerals))
|
||||
|
||||
highest_mastery_champ = Column(Integer)
|
||||
|
||||
_mini_full_name = "League of Legends"
|
||||
_mini_name = "lol"
|
||||
_mini_order = [solo_division.desc().nullslast(),
|
||||
solo_rank.desc().nullslast(),
|
||||
flex_division.desc().nullslast(),
|
||||
flex_rank.desc().nullslast(),
|
||||
twtr_division.desc().nullslast(),
|
||||
twtr_rank.desc().nullslast()]
|
||||
|
||||
def __repr__(self):
|
||||
if not self.summoner_name:
|
||||
return f"<LeagueOfLegends {self.summoner_id}>"
|
||||
|
@ -455,14 +571,14 @@ class LeagueOfLegends(Base):
|
|||
|
||||
def highest_mastery_champ_name(self):
|
||||
champ = loldata.get_champ_by_key(self.highest_mastery_champ)
|
||||
return champ["name"]
|
||||
return champ["id"]
|
||||
|
||||
def highest_mastery_champ_image(self):
|
||||
champ = loldata.get_champ_by_key(self.highest_mastery_champ)
|
||||
return loldata.get_champ_icon(champ["name"])
|
||||
return loldata.get_champ_icon(champ["id"])
|
||||
|
||||
|
||||
class Osu(Base):
|
||||
class Osu(Base, Mini):
|
||||
__tablename__ = "osu"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False)
|
||||
|
@ -470,11 +586,21 @@ class Osu(Base):
|
|||
|
||||
osu_id = Column(Integer, primary_key=True)
|
||||
osu_name = Column(String)
|
||||
std_pp = Column(Float, default=0)
|
||||
std_best_song = Column(BigInteger)
|
||||
taiko_pp = Column(Float, default=0)
|
||||
taiko_best_song = Column(BigInteger)
|
||||
catch_pp = Column(Float, default=0)
|
||||
catch_best_song = Column(BigInteger)
|
||||
mania_pp = Column(Float, default=0)
|
||||
mania_best_song = Column(BigInteger)
|
||||
|
||||
std_pp = Column(Float)
|
||||
taiko_pp = Column(Float)
|
||||
catch_pp = Column(Float)
|
||||
mania_pp = Column(Float)
|
||||
_mini_full_name = "osu!"
|
||||
_mini_name = "osu"
|
||||
_mini_order = [mania_pp.desc().nullslast(),
|
||||
std_pp.desc().nullslast(),
|
||||
taiko_pp.desc().nullslast(),
|
||||
catch_pp.desc().nullslast()]
|
||||
|
||||
@staticmethod
|
||||
def create(session: Session, royal_id, osu_name):
|
||||
|
@ -504,23 +630,32 @@ class Osu(Base):
|
|||
|
||||
# noinspection PyUnusedLocal
|
||||
def update(self, session=None):
|
||||
std = DirtyDelta(self.std_pp)
|
||||
taiko = DirtyDelta(self.taiko_pp)
|
||||
catch = DirtyDelta(self.catch_pp)
|
||||
mania = DirtyDelta(self.mania_pp)
|
||||
r0 = requests.get(f"https://osu.ppy.sh/api/get_user?k={config['Osu!']['ppy_api_key']}&u={self.osu_name}&m=0")
|
||||
r0.raise_for_status()
|
||||
j0 = r0.json()[0]
|
||||
r1 = requests.get(f"https://osu.ppy.sh/api/get_user?k={config['Osu!']['ppy_api_key']}&u={self.osu_name}&m=1")
|
||||
r1.raise_for_status()
|
||||
j1 = r1.json()[0]
|
||||
r2 = requests.get(f"https://osu.ppy.sh/api/get_user?k={config['Osu!']['ppy_api_key']}&u={self.osu_name}&m=2")
|
||||
r2.raise_for_status()
|
||||
j2 = r2.json()[0]
|
||||
r3 = requests.get(f"https://osu.ppy.sh/api/get_user?k={config['Osu!']['ppy_api_key']}&u={self.osu_name}&m=3")
|
||||
r3.raise_for_status()
|
||||
j0 = r0.json()[0]
|
||||
j1 = r1.json()[0]
|
||||
j2 = r2.json()[0]
|
||||
j3 = r3.json()[0]
|
||||
self.osu_name = j0["username"]
|
||||
self.std_pp = j0["pp_raw"]
|
||||
self.taiko_pp = j1["pp_raw"]
|
||||
self.catch_pp = j2["pp_raw"]
|
||||
self.mania_pp = j3["pp_raw"]
|
||||
std.value = float(j0["pp_raw"] or 0)
|
||||
taiko.value = float(j1["pp_raw"] or 0)
|
||||
catch.value = float(j2["pp_raw"] or 0)
|
||||
mania.value = float(j3["pp_raw"] or 0)
|
||||
self.std_pp = std.value
|
||||
self.taiko_pp = taiko.value
|
||||
self.catch_pp = catch.value
|
||||
self.mania_pp = mania.value
|
||||
return std, taiko, catch, mania
|
||||
|
||||
def __repr__(self):
|
||||
if not self.osu_name:
|
||||
|
@ -528,7 +663,7 @@ class Osu(Base):
|
|||
return f"<db.Osu {self.osu_name}>"
|
||||
|
||||
|
||||
class Discord(Base):
|
||||
class Discord(Base, Mini):
|
||||
__tablename__ = "discord"
|
||||
__table_args__ = tuple(UniqueConstraint("name", "discriminator"))
|
||||
|
||||
|
@ -540,6 +675,10 @@ class Discord(Base):
|
|||
discriminator = Column(Integer)
|
||||
avatar_hex = Column(String)
|
||||
|
||||
_mini_full_name = "Discord"
|
||||
_mini_name = "discord"
|
||||
_mini_order = [discord_id]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}#{self.discriminator}"
|
||||
|
||||
|
@ -547,7 +686,7 @@ class Discord(Base):
|
|||
return f"<db.Discord {self.discord_id}>"
|
||||
|
||||
@staticmethod
|
||||
def create(session: Session, royal_username, discord_user: DiscordUser):
|
||||
def create(session: Session, royal_username, discord_user: "DiscordUser"):
|
||||
d = session.query(Discord).filter(Discord.discord_id == discord_user.id).first()
|
||||
if d is not None:
|
||||
raise AlreadyExistingError(repr(d))
|
||||
|
@ -572,8 +711,20 @@ class Discord(Base):
|
|||
return "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"
|
||||
return f"https://cdn.discordapp.com/avatars/{self.discord_id}/{self.avatar_hex}.png?size={size}"
|
||||
|
||||
@classmethod
|
||||
def mini_get_all(cls, session: Session):
|
||||
return [dict(row) for row in session.execute(sql_queries.all_music_query)]
|
||||
|
||||
class Overwatch(Base):
|
||||
@classmethod
|
||||
def mini_get_single(cls, session: Session, **kwargs):
|
||||
return session.execute(sql_queries.one_music_query, {"royal": kwargs["royal"].id}).fetchone()
|
||||
|
||||
@classmethod
|
||||
def mini_get_single_from_royal(cls, session: Session, royal: "Royal"):
|
||||
return cls.mini_get_single(session, royal=royal)
|
||||
|
||||
|
||||
class Overwatch(Base, Mini):
|
||||
__tablename__ = "overwatch"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"), nullable=False)
|
||||
|
@ -582,10 +733,13 @@ class Overwatch(Base):
|
|||
battletag = Column(String, primary_key=True)
|
||||
discriminator = Column(Integer, primary_key=True)
|
||||
icon = Column(String)
|
||||
|
||||
level = Column(Integer)
|
||||
rank = Column(Integer)
|
||||
|
||||
_mini_full_name = "Overwatch"
|
||||
_mini_name = "ow"
|
||||
_mini_order = [rank.desc().nullslast(), level.desc()]
|
||||
|
||||
def __str__(self, separator="#"):
|
||||
return f"{self.battletag}{separator}{self.discriminator}"
|
||||
|
||||
|
@ -594,45 +748,14 @@ class Overwatch(Base):
|
|||
|
||||
@staticmethod
|
||||
def create(session: Session, royal_id, battletag, discriminator=None):
|
||||
if discriminator is None:
|
||||
battletag, discriminator = battletag.split("#", 1)
|
||||
o = session.query(Overwatch).filter_by(battletag=battletag, discriminator=discriminator).first()
|
||||
if o is not None:
|
||||
raise AlreadyExistingError(repr(o))
|
||||
o = Overwatch(royal_id=royal_id,
|
||||
battletag=battletag,
|
||||
discriminator=discriminator)
|
||||
o.update()
|
||||
return o
|
||||
raise NotImplementedError()
|
||||
|
||||
def icon_url(self):
|
||||
return f"https://d1u1mce87gyfbn.cloudfront.net/game/unlocks/{self.icon}.png"
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def update(self, session=None):
|
||||
r = requests.get(f"https://owapi.net/api/v3/u/{self.battletag}-{self.discriminator}/stats", headers={
|
||||
"User-Agent": "Royal-Bot/4.1",
|
||||
"From": "ste.pigozzi@gmail.com"
|
||||
})
|
||||
r.raise_for_status()
|
||||
try:
|
||||
j = r.json()["eu"]["stats"].get("competitive")
|
||||
if j is None:
|
||||
logger.debug(f"No stats for {repr(self)}, skipping...")
|
||||
return
|
||||
if not j["game_stats"]:
|
||||
logger.debug(f"No stats for {repr(self)}, skipping...")
|
||||
return
|
||||
j = j["overall_stats"]
|
||||
except TypeError:
|
||||
logger.debug(f"No stats for {repr(self)}, skipping...")
|
||||
return
|
||||
try:
|
||||
self.icon = re.search(r"https://.+\.cloudfront\.net/game/unlocks/(0x[0-9A-F]+)\.png", j["avatar"]).group(1)
|
||||
except AttributeError:
|
||||
logger.debug(f"No icon available for {repr(self)}.")
|
||||
self.level = j["prestige"] * 100 + j["level"]
|
||||
self.rank = j["comprank"]
|
||||
raise NotImplementedError()
|
||||
|
||||
def rank_url(self):
|
||||
if self.rank < 1500:
|
||||
|
@ -686,48 +809,15 @@ class Diario(Base):
|
|||
def __str__(self):
|
||||
return f"{self.id} - {self.timestamp} - {self.author}: {self.text}"
|
||||
|
||||
def to_telegram(self):
|
||||
return '<a href="https://ryg.steffo.eu/diario#entry-{id}">#{id}</a> di {author}\n{text}'.format(
|
||||
id=self.id,
|
||||
author=f"<b>{self.author}</b>" if self.author is not None else strings.DIARIO.ANONYMOUS,
|
||||
text=escape(self.text))
|
||||
|
||||
def to_html(self):
|
||||
return str(escape(self.text)).replace("\n", "<br>")
|
||||
|
||||
@staticmethod
|
||||
def import_from_json(file):
|
||||
import json
|
||||
session = Session()
|
||||
file = open(file, "r")
|
||||
j = json.load(file)
|
||||
author_ids = {
|
||||
"@Steffo": 25167391,
|
||||
"@GoodBalu": 19611986,
|
||||
"@gattopandacorno": 200821462,
|
||||
"@Albertino04": 131057096,
|
||||
"@Francesco_Cuoghi": 48371848,
|
||||
"@VenomousDoc": 48371848,
|
||||
"@MaxSensei": 1258401,
|
||||
"@Protoh": 125711787,
|
||||
"@McspKap": 304117728,
|
||||
"@FrankRekt": 31436195,
|
||||
"@EvilBalu": 26842090,
|
||||
"@Dailir": 135816455,
|
||||
"@Paltri": 186843362,
|
||||
"@Doom_darth_vader": 165792255,
|
||||
"@httpIma": 292086686,
|
||||
"@DavidoMessori": 509208316,
|
||||
"@DavidoNiichan": 509208316,
|
||||
"@Peraemela99": 63804599,
|
||||
"@infopz": 20403805,
|
||||
"@Baithoven": 121537369,
|
||||
"@Tauei": 102833717
|
||||
}
|
||||
for n, entry in enumerate(j):
|
||||
author = author_ids[entry["sender"]] if "sender" in entry and entry["sender"] in author_ids else None
|
||||
d = Diario(timestamp=datetime.datetime.fromtimestamp(float(entry["timestamp"])),
|
||||
author_id=author,
|
||||
text=entry["text"])
|
||||
print(f"{n} - {d}")
|
||||
session.add(d)
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
|
||||
class BaluRage(Base):
|
||||
__tablename__ = "balurage"
|
||||
|
@ -770,7 +860,7 @@ class VoteQuestion(Base):
|
|||
text = f"<b>{self.question}</b>\n\n"
|
||||
none, yes, no, abstain = 0, 0, 0, 0
|
||||
if self.message_id is not None:
|
||||
query = session.execute(query_discord_music.vote_answers, {"message_id": self.message_id})
|
||||
query = session.execute(sql_queries.vote_answers, {"message_id": self.message_id})
|
||||
for record in query:
|
||||
if record["username"] == "royalgamesbot":
|
||||
continue
|
||||
|
@ -837,6 +927,7 @@ class WikiEntry(Base):
|
|||
|
||||
key = Column(String, primary_key=True)
|
||||
content = Column(Text, nullable=False)
|
||||
locked = Column(Boolean, default=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<WikiEntry {self.key}>"
|
||||
|
@ -894,23 +985,6 @@ class Reddit(Base):
|
|||
return f"<Reddit u/{self.username}>"
|
||||
|
||||
|
||||
class GameLog(Base):
|
||||
__tablename__ = "gamelog"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"))
|
||||
royal = relationship("Royal", backref="gamelog", lazy="joined")
|
||||
|
||||
username = Column(String, primary_key=True)
|
||||
owned_games = Column(Integer)
|
||||
unfinished_games = Column(Integer)
|
||||
beaten_games = Column(Integer)
|
||||
completed_games = Column(Integer)
|
||||
mastered_games = Column(Integer)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<GameLog {self.username}>"
|
||||
|
||||
|
||||
class ParsedRedditPost(Base):
|
||||
__tablename__ = "parsedredditposts"
|
||||
|
||||
|
@ -935,7 +1009,7 @@ class LoginToken(Base):
|
|||
return f"<LoginToken for {self.royal.username}>"
|
||||
|
||||
|
||||
class Halloween(Base):
|
||||
class Halloween(Base, Mini):
|
||||
"""This is some nice spaghetti, don't you think?"""
|
||||
__tablename__ = "halloween"
|
||||
|
||||
|
@ -943,7 +1017,6 @@ class Halloween(Base):
|
|||
royal = relationship("Royal", backref="halloween", lazy="joined")
|
||||
|
||||
first_trigger = Column(DateTime)
|
||||
|
||||
puzzle_piece_a = Column(DateTime)
|
||||
puzzle_piece_b = Column(DateTime)
|
||||
puzzle_piece_c = Column(DateTime)
|
||||
|
@ -951,9 +1024,12 @@ class Halloween(Base):
|
|||
puzzle_piece_e = Column(DateTime)
|
||||
puzzle_piece_f = Column(DateTime)
|
||||
puzzle_piece_g = Column(DateTime)
|
||||
|
||||
boss_battle = Column(DateTime)
|
||||
|
||||
_mini_full_name = "Halloween 2018"
|
||||
_mini_name = "halloween2018"
|
||||
_mini_order = [first_trigger]
|
||||
|
||||
def __getitem__(self, item):
|
||||
if not isinstance(item, int):
|
||||
raise TypeError("The index should be an int")
|
||||
|
@ -1036,6 +1112,267 @@ class ActivityReport(Base):
|
|||
return f"<ActivityReport at {self.timestamp.isoformat()}>"
|
||||
|
||||
|
||||
class Quest(Base):
|
||||
__tablename__ = "quests"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
||||
title = Column(String)
|
||||
description = Column(Text)
|
||||
reward = Column(Integer)
|
||||
expiration_date = Column(DateTime)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Quest {self.id}: {self.title}>"
|
||||
|
||||
|
||||
class Terraria13(Base, Mini):
|
||||
__tablename__ = "terraria13"
|
||||
|
||||
game_name = "Terraria 13"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"), primary_key=True)
|
||||
royal = relationship("Royal", backref="terraria13", lazy="joined")
|
||||
|
||||
character_name = Column(String)
|
||||
contribution = Column(Integer)
|
||||
|
||||
_mini_full_name = "Terraria 13"
|
||||
_mini_name = "terraria13"
|
||||
_mini_order = [contribution.desc()]
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Terraria13 {self.character_name} {self.contribution}>"
|
||||
|
||||
|
||||
class Minecraft2019(Base, Mini):
|
||||
__tablename__ = "minecraft2019"
|
||||
|
||||
game_name = "Minecraft 2019"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.id"), primary_key=True)
|
||||
royal = relationship("Royal", backref="minecraft2019", lazy="joined")
|
||||
|
||||
character_name = Column(String)
|
||||
contribution = Column(Integer)
|
||||
|
||||
_mini_full_name = "Minecraft 2019"
|
||||
_mini_name = "minecraft2019"
|
||||
_mini_order = [contribution.desc()]
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Terraria13 {self.character_name} {self.contribution}>"
|
||||
|
||||
|
||||
mini_list = [Royal, Telegram, Steam, Dota, LeagueOfLegends, Osu, Discord, Overwatch, Halloween,
|
||||
Terraria13]
|
||||
|
||||
|
||||
class Match(Base):
|
||||
__tablename__ = "matches"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
timestamp = Column(DateTime)
|
||||
creator_id = Column(BigInteger, ForeignKey("telegram.telegram_id"))
|
||||
creator = relationship("Telegram", backref="matches_created", lazy="joined")
|
||||
|
||||
match_title = Column(String)
|
||||
match_desc = Column(Text)
|
||||
min_players = Column(Integer)
|
||||
max_players = Column(Integer)
|
||||
closed = Column(Boolean, default=False)
|
||||
|
||||
message_id = Column(BigInteger)
|
||||
|
||||
def active_players_count(self):
|
||||
count = 0
|
||||
for player in self.players:
|
||||
if player.status == MatchmakingStatus.READY \
|
||||
or player.status == MatchmakingStatus.WAIT_FOR_ME \
|
||||
or player.status == MatchmakingStatus.SOMEONE_ELSE:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def generate_text(self, session):
|
||||
player_list = session.query(MatchPartecipation).filter_by(match=self).all()
|
||||
title = f"<b>{self.match_title}</b>"
|
||||
description = f"{self.match_desc}\n" if self.match_desc else ""
|
||||
if self.min_players:
|
||||
minimum = f" <i>(minimo {self.min_players})</i>"
|
||||
else:
|
||||
minimum = ""
|
||||
plist = f"Giocatori{minimum}:\n"
|
||||
ignore_count = 0
|
||||
for player in player_list:
|
||||
icon = strings.MATCHMAKING.ENUM_TO_EMOJIS[player.status]
|
||||
if player.status == MatchmakingStatus.IGNORED:
|
||||
ignore_count += 1
|
||||
continue
|
||||
plist += f"{icon} {player.user.royal.username}\n"
|
||||
if ignore_count:
|
||||
ignored = f"❌ <i>{ignore_count} persone non sono interessate.</i>\n"
|
||||
else:
|
||||
ignored = ""
|
||||
if self.max_players:
|
||||
players = f"[{self.active_players_count()}/{self.max_players}]"
|
||||
else:
|
||||
players = f"[{self.active_players_count()}]"
|
||||
close = f"[matchmaking terminato]\n" if self.closed else ""
|
||||
message = f"{title} {players}\n" \
|
||||
f"{description}\n" \
|
||||
f"{plist}\n" \
|
||||
f"{ignored}" \
|
||||
f"{close}"
|
||||
return message
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Match {self.match_title}>"
|
||||
|
||||
def format_dict(self) -> typing.Dict[str, str]:
|
||||
return {
|
||||
"id": str(self.id),
|
||||
"timestamp": self.timestamp.isoformat(),
|
||||
"creator_id": str(self.creator_id),
|
||||
"creator_name": self.creator.mention(),
|
||||
"match_title": self.match_title,
|
||||
"match_desc": self.match_desc if self.match_desc is not None else "",
|
||||
"min_players": str(self.min_players) if self.min_players is not None else "",
|
||||
"max_players": str(self.max_players) if self.max_players is not None else "",
|
||||
"active_players": str(self.active_players_count()),
|
||||
"players": str(len(self.players))
|
||||
}
|
||||
|
||||
|
||||
class MatchPartecipation(Base):
|
||||
__tablename__ = "matchpartecipations"
|
||||
__table_args__ = (PrimaryKeyConstraint("user_id", "match_id"),)
|
||||
|
||||
user_id = Column(BigInteger, ForeignKey("telegram.telegram_id"))
|
||||
user = relationship("Telegram", backref="match_partecipations", lazy="joined")
|
||||
|
||||
match_id = Column(Integer, ForeignKey("matches.id"))
|
||||
match = relationship("Match", backref="players", lazy="joined")
|
||||
|
||||
status = Column(Integer)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<MatchPartecipation {self.user.username} in {self.match.match_title}>"
|
||||
|
||||
|
||||
class BindingOfIsaac(Base, Mini):
|
||||
__tablename__ = "bindingofisaac"
|
||||
|
||||
steam_id = Column(String, ForeignKey("steam.steam_id"), primary_key=True)
|
||||
steam = relationship("Steam", backref="binding_of_isaac", lazy="joined")
|
||||
|
||||
daily_victories = Column(Integer, default=0)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<db.BindingOfIsaac {self.steam_id}>"
|
||||
|
||||
def recalc_victories(self):
|
||||
raise NotImplementedError() # TODO
|
||||
|
||||
|
||||
class BindingOfIsaacRun(Base):
|
||||
__tablename__ = "bindingofisaacruns"
|
||||
__table_args__ = (PrimaryKeyConstraint("date", "player_id"),)
|
||||
|
||||
date = Column(Date)
|
||||
|
||||
player_id = Column(String, ForeignKey("bindingofisaac.steam_id"))
|
||||
player = relationship("BindingOfIsaac", backref="runs", lazy="joined")
|
||||
|
||||
score = Column(BigInteger)
|
||||
# time = Column(???)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<db.BindingOfIsaacRun {self.player_id}: {self.score}>"
|
||||
|
||||
|
||||
class Brawlhalla(Base, Mini):
|
||||
__tablename__ = "brawlhalla"
|
||||
|
||||
steam_id = Column(String, ForeignKey("steam.steam_id"), primary_key=True)
|
||||
steam = relationship("Steam", backref="brawlhalla", lazy="joined")
|
||||
brawlhalla_id = Column(BigInteger)
|
||||
name = Column(String)
|
||||
|
||||
level = Column(Integer)
|
||||
|
||||
main_legend_name = Column(String)
|
||||
main_legend_level = Column(Integer)
|
||||
|
||||
ranked_plays = Column(Integer)
|
||||
ranked_wins = Column(Integer)
|
||||
rating = Column(Integer)
|
||||
|
||||
best_team_partner_id = Column(BigInteger)
|
||||
best_team_rating = Column(Integer)
|
||||
|
||||
_mini_full_name = "Brawlhalla"
|
||||
_mini_name = "brawlhalla"
|
||||
_mini_order = [rating.desc(), level.desc()]
|
||||
|
||||
def __repr__(self):
|
||||
return f"<db.Brawlhalla {self.name}>"
|
||||
|
||||
@hybrid_property
|
||||
def best_team_partner(self) -> typing.Optional["Brawlhalla"]:
|
||||
# FIXME: dirty hack here
|
||||
session = Session()
|
||||
b = session.query(Brawlhalla).filter_by(brawlhalla_id=self.best_team_partner_id).one_or_none()
|
||||
session.close()
|
||||
return b
|
||||
|
||||
@staticmethod
|
||||
def init_table():
|
||||
session = Session()
|
||||
steam = session.query(Steam).all()
|
||||
for user in steam:
|
||||
j = requests.get("https://api.brawlhalla.com/search", params={
|
||||
"steamid": user.steam_id,
|
||||
"api_key": config["Brawlhalla"]["brawlhalla_api_key"]
|
||||
}).json()
|
||||
if not j:
|
||||
continue
|
||||
b = session.query(Brawlhalla).filter_by(steam=user).one_or_none()
|
||||
if b is None:
|
||||
b = Brawlhalla(steam_id=user.steam_id, brawlhalla_id=j["brawlhalla_id"], name=j["name"])
|
||||
session.add(b)
|
||||
time.sleep(1)
|
||||
session.commit()
|
||||
|
||||
def update(self, session=None):
|
||||
j = requests.get(f"https://api.brawlhalla.com/player/{self.brawlhalla_id}/stats?api_key={config['Brawlhalla']['brawlhalla_api_key']}").json()
|
||||
self.name = j.get("name", "unknown")
|
||||
self.level = j.get("level", 0)
|
||||
try:
|
||||
main_legend = max(j.get("legends", []), key=lambda l: l.get("level", 0))
|
||||
self.main_legend_level = main_legend.get("level", 0)
|
||||
self.main_legend_name = main_legend.get("legend_name_key", "unknown")
|
||||
except ValueError:
|
||||
pass
|
||||
j = requests.get(f"https://api.brawlhalla.com/player/{self.brawlhalla_id}/ranked?api_key={config['Brawlhalla']['brawlhalla_api_key']}").json()
|
||||
self.ranked_plays = j.get("games", 0)
|
||||
self.ranked_wins = j.get("wins", 0)
|
||||
rating = DirtyDelta(self.rating)
|
||||
rating.value = j.get("rating")
|
||||
self.rating = rating.value
|
||||
best_team_data = Dirty((self.best_team_partner_id, self.best_team_rating))
|
||||
try:
|
||||
current_best_team = max(j.get("2v2", []), key=lambda t: t.get("rating", 0))
|
||||
if current_best_team["brawlhalla_id_one"] == self.brawlhalla_id:
|
||||
self.best_team_partner_id = current_best_team["brawlhalla_id_two"]
|
||||
else:
|
||||
self.best_team_partner_id = current_best_team["brawlhalla_id_one"]
|
||||
self.best_team_rating = current_best_team["rating"]
|
||||
best_team_data.value = (self.best_team_partner_id, self.best_team_rating)
|
||||
except ValueError:
|
||||
pass
|
||||
return rating, best_team_data
|
||||
|
||||
|
||||
# If run as script, create all the tables in the db
|
||||
if __name__ == "__main__":
|
||||
print("Creating new tables...")
|
||||
|
|
13
dirty.py
|
@ -1,13 +0,0 @@
|
|||
class Dirty:
|
||||
def __init__(self, initial_value):
|
||||
self.initial_value = initial_value
|
||||
self.value = initial_value
|
||||
|
||||
def is_clean(self):
|
||||
return self.initial_value == self.value
|
||||
|
||||
def is_dirty(self):
|
||||
return not self.is_clean()
|
||||
|
||||
def __bool__(self):
|
||||
return self.is_dirty()
|
55
isaacfetcher.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
import steamleaderboards
|
||||
import datetime
|
||||
import db
|
||||
import time
|
||||
import telegram
|
||||
import configparser
|
||||
|
||||
|
||||
def dates_generator(last_date: datetime.date):
|
||||
date = datetime.date.today()
|
||||
while True:
|
||||
if date < last_date:
|
||||
return
|
||||
yield date
|
||||
date -= datetime.timedelta(days=1)
|
||||
|
||||
|
||||
session = db.Session()
|
||||
players = session.query(db.BindingOfIsaac).all()
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read("config.ini")
|
||||
|
||||
print("Fetching leaderboardgroup...")
|
||||
isaac = steamleaderboards.LeaderboardGroup(250900)
|
||||
|
||||
telegram_bot = telegram.Bot(config["Telegram"]["bot_token"])
|
||||
|
||||
for date in dates_generator(datetime.date(year=2017, month=1, day=3)):
|
||||
lb_name = "{year:04d}{month:02d}{day:02d}_scores+".format(year=date.year, month=date.month, day=date.day)
|
||||
print(f"Fetching {lb_name}...")
|
||||
leaderboard = isaac.get(name=lb_name)
|
||||
print(f"Finding players...")
|
||||
runs = []
|
||||
for player in players:
|
||||
entry = leaderboard.find_entry(player.steam_id)
|
||||
if entry is None:
|
||||
continue
|
||||
print(f"Found new entry: {entry}")
|
||||
run = db.BindingOfIsaacRun(player=player, score=entry.score, date=date)
|
||||
runs.append(run)
|
||||
session.add(run)
|
||||
if len(runs) > 1:
|
||||
runs.sort(key=lambda x: x.score)
|
||||
best = runs[-1]
|
||||
best.player.daily_victories += 1
|
||||
try:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
f"🏆 <b>{best.player.steam.persona_name}</b> ha vinto la Daily Run di Isaac del {date.isoformat()}!",
|
||||
parse_mode="HTML", disable_web_page_preview=True, disable_notification=True)
|
||||
except Exception:
|
||||
pass
|
||||
session.commit()
|
||||
print("Sleeping 5s...")
|
||||
time.sleep(5)
|
|
@ -1,4 +1,4 @@
|
|||
import errors
|
||||
from utils import errors
|
||||
|
||||
champions = {"type": "champion", "format": "standAloneComplex", "version": "8.19.1", "data": {
|
||||
"Aatrox": {"version": "8.19.1", "id": "Aatrox", "key": "266", "name": "Aatrox", "title": "the Darkin Blade",
|
||||
|
|
|
@ -6,7 +6,7 @@ user = session.query(db.Royal).filter_by(username=username).one_or_none()
|
|||
if user is None:
|
||||
user = db.Royal.create(session, username)
|
||||
session.add(user)
|
||||
session.commit()
|
||||
session.flush()
|
||||
try:
|
||||
steam = db.Steam.create(session, user.id, input("Steam ID 1: "))
|
||||
except Exception as e:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
python-telegram-bot
|
||||
flask
|
||||
sqlalchemy
|
||||
youtube-dl
|
||||
youtube_dl==2019.02.18
|
||||
requests
|
||||
psycopg2-binary
|
||||
PyNaCl
|
||||
|
@ -16,3 +16,5 @@ dice
|
|||
raven[flask]
|
||||
coloredlogs
|
||||
sentry_sdk
|
||||
steamleaderboards
|
||||
git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
all_query = """SELECT
|
||||
all_music_query = """SELECT
|
||||
discord.royal_id,
|
||||
discord.discord_id,
|
||||
discord.name,
|
||||
|
@ -59,7 +59,7 @@ LEFT JOIN
|
|||
|
||||
|
||||
# TODO: can and should be optimized, but I'm too lazy for that
|
||||
one_query = """SELECT
|
||||
one_music_query = """SELECT
|
||||
discord.royal_id,
|
||||
discord.discord_id,
|
||||
discord.name,
|
||||
|
@ -141,3 +141,18 @@ LEFT JOIN
|
|||
WHERE votequestion.message_id = :message_id
|
||||
) answer ON telegram.telegram_id = answer.user_id
|
||||
ORDER BY answer.choice;"""
|
||||
|
||||
activity_by_hour = """SELECT AVG(discord_members_online) online_members_avg,
|
||||
AVG(discord_members_ingame) ingame_members_avg,
|
||||
AVG(discord_members_cv) cv_members_avg,
|
||||
AVG(discord_channels_used) channels_used_avg,
|
||||
AVG(discord_cv) cv_avg,
|
||||
extract(hour from timestamp) h
|
||||
FROM (
|
||||
SELECT *,
|
||||
extract(month from timestamp) month_
|
||||
FROM activityreports
|
||||
) withmonth
|
||||
WHERE withmonth.month_ = :current_month
|
||||
GROUP BY h
|
||||
ORDER BY h;"""
|
46
stagismo.py
|
@ -1,46 +0,0 @@
|
|||
listona = ["della secca", "del seccatore", "del secchiello", "del secchio", "del secchione", "del secondino",
|
||||
"del sedano", "del sedativo", "della sedia", "del sedicente", "del sedile", "della sega", "del segale",
|
||||
"della segatura", "della seggiola", "del seggiolino", "della seggiovia", "della segheria", "del seghetto",
|
||||
"del segnalibro", "del segnaposto", "del segno", "del segretario", "della segreteria", "del seguace",
|
||||
"del segugio", "della selce", "della sella", "della selz", "della selva", "della selvaggina", "del semaforo",
|
||||
"del seme", "del semifreddo", "del seminario", "della seminarista", "della semola", "del semolino",
|
||||
"del semplicione", "della senape", "del senatore", "del seno", "del sensore", "della sentenza",
|
||||
"della sentinella", "del sentore", "della seppia", "del sequestratore", "della serenata", "del sergente",
|
||||
"del sermone", "della serpe", "del serpente", "della serpentina", "della serra", "del serraglio",
|
||||
"del serramanico", "della serranda", "della serratura", "del servitore", "della servitù", "del servizievole",
|
||||
"del servo", "del set", "della seta", "della setola", "del sidecar", "del siderurgico", "del sidro",
|
||||
"della siepe", "del sifone", "della sigaretta", "del sigaro", "del sigillo", "della signora",
|
||||
"della signorina", "del silenziatore", "della silhouette", "del silicio", "del silicone", "del siluro",
|
||||
"della sinagoga", "della sindacalista", "del sindacato", "del sindaco", "della sindrome", "della sinfonia",
|
||||
"del sipario", "del sire", "della sirena", "della siringa", "del sismografo", "del sobborgo",
|
||||
"del sobillatore", "del sobrio", "del soccorritore", "del socio", "del sociologo", "della soda", "del sofà",
|
||||
"della soffitta", "del software", "dello sogghignare", "del soggiorno", "della sogliola", "del sognatore",
|
||||
"della soia", "del solaio", "del solco", "del soldato", "del soldo", "del sole", "della soletta",
|
||||
"della solista", "del solitario", "del sollazzare", "del sollazzo", "del sollecito", "del solleone",
|
||||
"del solletico", "del sollevare", "del sollievo", "del solstizio", "del solubile", "del solvente",
|
||||
"della soluzione", "del somaro", "del sombrero", "del sommergibile", "del sommo", "della sommossa",
|
||||
"del sommozzatore", "del sonar", "della sonda", "del sondaggio", "del sondare", "del sonnacchioso",
|
||||
"del sonnambulo", "del sonnellino", "del sonnifero", "del sonno", "della sonnolenza", "del sontuoso",
|
||||
"del soppalco", "del soprabito", "del sopracciglio", "del sopraffare", "del sopraffino", "del sopraluogo",
|
||||
"del sopramobile", "del soprannome", "del soprano", "del soprappensiero", "del soprassalto",
|
||||
"del soprassedere", "del sopravvento", "del sopravvivere", "del soqquadro", "del sorbetto", "del sordido",
|
||||
"della sordina", "del sordo", "della sorella", "della sorgente", "del sornione", "del sorpasso",
|
||||
"della sorpresa", "del sorreggere", "del sorridere", "della sorsata", "del sorteggio", "del sortilegio",
|
||||
"del sorvegliante", "del sorvolare", "del sosia", "del sospettoso", "del sospirare", "della sosta",
|
||||
"della sostanza", "del sostegno", "del sostenitore", "del sostituto", "del sottaceto", "della sottana",
|
||||
"del sotterfugio", "del sotterraneo", "del sottile", "del sottilizzare", "del sottintendere",
|
||||
"del sottobanco", "del sottobosco", "del sottomarino", "del sottopassaggio", "del sottoposto",
|
||||
"del sottoscala", "della sottoscrizione", "del sottostare", "del sottosuolo", "del sottotetto",
|
||||
"del sottotitolo", "del sottovalutare", "del sottovaso", "della sottoveste", "del sottovuoto",
|
||||
"del sottufficiale", "della soubrette", "del souvenir", "del soverchiare", "del sovrano", "del sovrapprezzo",
|
||||
"della sovvenzione", "del sovversivo", "del sozzo", "dello suadente", "del sub", "del subalterno",
|
||||
"del subbuglio", "del subdolo", "del sublime", "del suburbano", "del successore", "del succo",
|
||||
"della succube", "del succulento", "della succursale", "del sudario", "della sudditanza", "del suddito",
|
||||
"del sudicio", "del suffisso", "del suffragio", "del suffumigio", "del suggeritore", "del sughero",
|
||||
"del sugo", "del suino", "della suite", "del sulfureo", "del sultano", "di Steffo", "di Spaggia",
|
||||
"di Sabrina", "del sas", "del ses", "del sis", "del sos", "del sus", "della supremazia", "del Santissimo",
|
||||
"della scatola", "del supercalifragilistichespiralidoso", "del sale", "del salame", "di (Town of) Salem",
|
||||
"di Stronghold", "di SOMA", "dei Saints", "di S.T.A.L.K.E.R.", "di Sanctum", "dei Sims", "di Sid",
|
||||
"delle Skullgirls", "di Sonic", "di Spiral (Knights)", "di Spore", "di Starbound", "di SimCity", "di Sensei",
|
||||
"di Ssssssssssssss... Boom! E' esploso il dizionario", "della scala", "di Sakura", "di Suzie", "di Shinji",
|
||||
"del senpai", "del support", "di Superman"]
|
Before Width: | Height: | Size: 21 KiB |
3
static/LogoRoyalGames.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dea386e1d6ef2f0004aa045385f37f559247d9f5a17010174b4be5b6465dfeb6
|
||||
size 50018
|
219
static/LogoRoyalGames.svg
Normal file
|
@ -0,0 +1,219 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1000"
|
||||
height="1000"
|
||||
viewBox="0 0 264.58332 264.58333"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="LogoRoyalGames.svg"
|
||||
inkscape:export-filename="C:\Users\stepi\Pictures\LogoRoyalGames.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<title
|
||||
id="title5190">Royal Games</title>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient5149">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5147" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5042">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5040" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4971">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4969" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Principale"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#a1ccff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4895" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Sfondo"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#0d193b;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop817" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient821"
|
||||
x1="34.745037"
|
||||
y1="124.61114"
|
||||
x2="175.3288"
|
||||
y2="124.61114"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.8820335,0,0,2.1427478,-65.391324,-102.30192)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5332"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.9722906,-1.7276436,1.7276436,4.9722906,-481.91887,-479.70806)"
|
||||
x1="55.743366"
|
||||
y1="152.60051"
|
||||
x2="62.71452"
|
||||
y2="152.60051" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5334"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.8721103,-1.6928355,1.6928355,4.8721103,-559.10679,-570.69534)"
|
||||
x1="65.251831"
|
||||
y1="186.99634"
|
||||
x2="72.946449"
|
||||
y2="186.99634" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient5336"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(5.0448436,-1.7528523,1.7528523,5.0448436,-614.18765,-850.35741)"
|
||||
x1="63.593018"
|
||||
y1="224.03799"
|
||||
x2="71.024086"
|
||||
y2="224.03799" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath5457">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g5453"
|
||||
id="use5459"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="287.44765"
|
||||
inkscape:cy="453.73086"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="main-layer"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:measure-start="384.018,406.607"
|
||||
inkscape:measure-end="388.429,418.649"
|
||||
showguides="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-page="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1186"
|
||||
originx="0"
|
||||
originy="1.5e-005" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Royal Games</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Main Layer"
|
||||
inkscape:groupmode="layer"
|
||||
id="main-layer"
|
||||
transform="translate(0,-32.416689)"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="fill:url(#linearGradient821);fill-opacity:1;stroke-width:0.53132677"
|
||||
id="background"
|
||||
width="264.58334"
|
||||
height="264.58334"
|
||||
x="0"
|
||||
y="32.416656" />
|
||||
<g
|
||||
id="logo"
|
||||
transform="matrix(0.88827897,0,0,0.88827923,7.5532469,20.037367)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="star"
|
||||
d="m 55.674623,47.499965 23.70863,68.248035 5.283398,-7.9251 5.291666,7.9375 5.291667,-7.9375 v 27.78125 c 0,0 -3.96081,0.36871 -8.719881,0.71727 l 36.012267,103.66498 105.39511,38.24676 -69.9983,-88.16309 66.02232,-87.15178 -103.69547,36.69078 z"
|
||||
style="display:inline;opacity:0.98999999;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="crown"
|
||||
d="m 86.530103,136.32142 -7.14685,-20.57342 -0.0083,0.0124 -5.291667,-7.93751 -5.291666,7.93751 -5.291622,-7.9375 -5.291667,7.93751 -5.291666,-7.93751 v 27.78126 c 0,0 14.097344,1.32291 21.166666,1.32291 3.331782,0 8.204375,-0.29493 12.446786,-0.60565 z"
|
||||
style="display:inline;opacity:1;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
d="m 72.507099,179.7588 3.39258,9.76411 q 0.982062,2.82645 1.575007,3.45555 0.609709,0.59447 1.635113,0.72773 1.025404,0.13327 3.415041,-0.69702 l 0.330331,0.95072 -17.832346,6.19592 -0.330331,-0.95071 q 2.415332,-0.83922 3.111495,-1.57065 0.712931,-0.76606 0.796984,-1.60159 0.109751,-0.84445 -0.872311,-3.6709 l -7.856504,-22.61162 q -0.982062,-2.82645 -1.591772,-3.42092 -0.592945,-0.6291 -1.618348,-0.76236 -1.025404,-0.13327 -3.415041,0.69702 l -0.330331,-0.95072 16.187864,-5.62454 q 6.320976,-2.19625 9.553754,-2.3404 3.232782,-0.14414 5.904185,1.577 2.662477,1.69545 3.7606,4.85593 1.339177,3.85425 -0.560957,7.33657 -1.219429,2.20912 -4.128851,4.11271 l 12.474459,8.88354 q 2.439061,1.71548 3.329239,2.03972 1.330261,0.4305 2.744571,0.0255 l 0.33033,0.95072 -10.971772,3.81219 -16.746132,-11.97806 z m -5.937017,-17.08719 5.303137,15.26284 1.464616,-0.50889 q 3.571608,-1.24097 5.121371,-2.49936 1.540832,-1.2841 1.953701,-3.32815 0.429633,-2.07869 -0.525644,-4.82805 -1.383817,-3.98273 -3.920215,-5.23243 -2.5107,-1.25862 -6.647599,0.17876 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5332);fill-opacity:1;stroke:none;stroke-width:1.39273477"
|
||||
id="letter-r"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 130.68189,137.70908 0.33514,0.96457 q -1.66517,0.84148 -2.33195,1.94973 -0.92304,1.54784 -2.04475,7.40121 l -3.217,15.4634 2.97106,8.55096 q 0.9511,2.73733 1.47316,3.3156 0.513,0.55218 1.52862,0.78362 1.03243,0.19649 2.4402,-0.29264 l 1.98136,-0.68843 0.33514,0.96457 -19.83925,6.89323 -0.33514,-0.96457 1.85095,-0.64312 q 1.5642,-0.54349 2.28645,-1.408 0.55091,-0.60076 0.63405,-1.62275 0.0692,-0.72522 -0.85477,-3.38436 l -2.46381,-7.09103 -13.57909,-12.2571 q -4.034666,-3.62353 -5.323131,-4.05231 -1.297544,-0.45491 -3.001119,0.10777 l -0.335146,-0.96457 16.945476,-5.88778 0.33515,0.96457 -0.75607,0.2627 q -1.53812,0.53443 -2.00989,1.19475 -0.44555,0.65179 -0.27353,1.14689 0.32609,0.93849 3.72516,3.99398 l 10.45421,9.48617 2.65629,-12.87275 q 1.01366,-4.73481 0.5698,-6.01227 -0.24455,-0.70385 -1.08543,-0.93761 -1.11283,-0.34377 -3.53051,0.35017 l -0.33515,-0.96457 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5336);fill-opacity:1;stroke:none;stroke-width:1.41305673"
|
||||
id="letter-y"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 102.64486,200.4253 4.18153,12.03476 -0.93156,0.32368 q -3.40148,-4.34864 -7.667536,-5.7445 -4.266052,-1.39586 -8.269247,-0.005 -3.826954,1.32969 -5.617541,4.37848 -1.79933,3.02363 -1.518338,7.24317 0.280991,4.21955 1.689414,8.2731 1.705854,4.90957 4.149964,8.20824 2.444105,3.29865 5.615805,4.1436 3.196874,0.83619 6.746879,-0.39727 1.23369,-0.42865 2.43025,-1.12657 1.21299,-0.73185 2.39761,-1.70779 l -2.46693,-7.1 q -0.69983,-2.01419 -1.17799,-2.49704 -0.4869,-0.50803 -1.53432,-0.68021 -1.022237,-0.18094 -2.255926,0.24771 l -0.881207,0.30618 -0.323675,-0.93156 16.591858,-5.76491 0.32368,0.93156 q -1.84457,0.78197 -2.45992,1.44726 -0.59892,0.63134 -0.68683,1.6777 -0.0604,0.5571 0.58696,2.42022 l 2.46693,7.1 q -2.76567,2.59752 -6.06198,4.56113 -3.26239,1.98004 -7.06416,3.30099 -4.859227,1.68835 -8.536819,1.49887 -3.661163,-0.22341 -6.872121,-1.50618 -3.194524,-1.3167 -5.515311,-3.52953 -2.969632,-2.86211 -4.465535,-7.16744 -2.676879,-7.70426 0.890426,-14.89749 3.567304,-7.19323 11.775112,-10.04506 2.54291,-0.88355 4.722241,-1.1893 1.177786,-0.18349 3.977586,-0.0841 2.81623,0.0655 3.269421,-0.0919 0.70497,-0.24494 1.13426,-0.95843 0.42055,-0.73868 0.42546,-2.34875 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'times new roman';-inkscape-font-specification:'times new roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5334);fill-opacity:1;stroke:none;stroke-width:1.36467421"
|
||||
id="letter-g"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
3
static/LogoRoyalGamesDota.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d91f90f19b96654c753f515c19f4191ad9881cefec249ac4decb5f872d344049
|
||||
size 6499
|
219
static/LogoRoyalGamesDota.svg
Normal file
|
@ -0,0 +1,219 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="250"
|
||||
height="150"
|
||||
viewBox="0 0 66.145827 39.687498"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="LogoRoyalGamesDota.svg"
|
||||
inkscape:export-filename="C:\Users\stepi\PycharmProjects\royalnet\static\LogoRoyalGamesDota.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<title
|
||||
id="title5190">Royal Games</title>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient5149">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5147" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5042">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5040" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4971">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4969" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Principale"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#a1ccff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4895" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Sfondo"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#0d193b;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop817" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient821"
|
||||
x1="34.745037"
|
||||
y1="124.61114"
|
||||
x2="175.3288"
|
||||
y2="124.61114"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.47050836,0,0,0.32141214,-16.347828,237.10472)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5332"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.9722906,-1.7276436,1.7276436,4.9722906,-481.91887,-479.70806)"
|
||||
x1="55.743366"
|
||||
y1="152.60051"
|
||||
x2="62.71452"
|
||||
y2="152.60051" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5334"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.8721103,-1.6928355,1.6928355,4.8721103,-559.10679,-570.69534)"
|
||||
x1="65.251831"
|
||||
y1="186.99634"
|
||||
x2="72.946449"
|
||||
y2="186.99634" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient5336"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(5.0448436,-1.7528523,1.7528523,5.0448436,-614.18765,-850.35741)"
|
||||
x1="63.593018"
|
||||
y1="224.03799"
|
||||
x2="71.024086"
|
||||
y2="224.03799" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath5457">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g5453"
|
||||
id="use5459"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="122.82373"
|
||||
inkscape:cy="83.346105"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="main-layer"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:measure-start="384.018,406.607"
|
||||
inkscape:measure-end="388.429,418.649"
|
||||
showguides="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-page="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1186"
|
||||
originx="0"
|
||||
originy="1e-006" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Royal Games</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Main Layer"
|
||||
inkscape:groupmode="layer"
|
||||
id="main-layer"
|
||||
transform="translate(0,-257.3125)"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="fill:url(#linearGradient821);fill-opacity:1;stroke-width:0.10289098"
|
||||
id="background"
|
||||
width="66.145828"
|
||||
height="39.687496"
|
||||
x="0"
|
||||
y="257.31253" />
|
||||
<g
|
||||
id="logo"
|
||||
transform="matrix(0.13324183,0,0,0.13324186,14.362153,255.4556)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="star"
|
||||
d="m 55.674623,47.499965 23.70863,68.248035 5.283398,-7.9251 5.291666,7.9375 5.291667,-7.9375 v 27.78125 c 0,0 -3.96081,0.36871 -8.719881,0.71727 l 36.012267,103.66498 105.39511,38.24676 -69.9983,-88.16309 66.02232,-87.15178 -103.69547,36.69078 z"
|
||||
style="display:inline;opacity:0.98999999;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="crown"
|
||||
d="m 86.530103,136.32142 -7.14685,-20.57342 -0.0083,0.0124 -5.291667,-7.93751 -5.291666,7.93751 -5.291622,-7.9375 -5.291667,7.93751 -5.291666,-7.93751 v 27.78126 c 0,0 14.097344,1.32291 21.166666,1.32291 3.331782,0 8.204375,-0.29493 12.446786,-0.60565 z"
|
||||
style="display:inline;opacity:1;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
d="m 72.507099,179.7588 3.39258,9.76411 q 0.982062,2.82645 1.575007,3.45555 0.609709,0.59447 1.635113,0.72773 1.025404,0.13327 3.415041,-0.69702 l 0.330331,0.95072 -17.832346,6.19592 -0.330331,-0.95071 q 2.415332,-0.83922 3.111495,-1.57065 0.712931,-0.76606 0.796984,-1.60159 0.109751,-0.84445 -0.872311,-3.6709 l -7.856504,-22.61162 q -0.982062,-2.82645 -1.591772,-3.42092 -0.592945,-0.6291 -1.618348,-0.76236 -1.025404,-0.13327 -3.415041,0.69702 l -0.330331,-0.95072 16.187864,-5.62454 q 6.320976,-2.19625 9.553754,-2.3404 3.232782,-0.14414 5.904185,1.577 2.662477,1.69545 3.7606,4.85593 1.339177,3.85425 -0.560957,7.33657 -1.219429,2.20912 -4.128851,4.11271 l 12.474459,8.88354 q 2.439061,1.71548 3.329239,2.03972 1.330261,0.4305 2.744571,0.0255 l 0.33033,0.95072 -10.971772,3.81219 -16.746132,-11.97806 z m -5.937017,-17.08719 5.303137,15.26284 1.464616,-0.50889 q 3.571608,-1.24097 5.121371,-2.49936 1.540832,-1.2841 1.953701,-3.32815 0.429633,-2.07869 -0.525644,-4.82805 -1.383817,-3.98273 -3.920215,-5.23243 -2.5107,-1.25862 -6.647599,0.17876 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5332);fill-opacity:1;stroke:none;stroke-width:1.39273477"
|
||||
id="letter-r"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 130.68189,137.70908 0.33514,0.96457 q -1.66517,0.84148 -2.33195,1.94973 -0.92304,1.54784 -2.04475,7.40121 l -3.217,15.4634 2.97106,8.55096 q 0.9511,2.73733 1.47316,3.3156 0.513,0.55218 1.52862,0.78362 1.03243,0.19649 2.4402,-0.29264 l 1.98136,-0.68843 0.33514,0.96457 -19.83925,6.89323 -0.33514,-0.96457 1.85095,-0.64312 q 1.5642,-0.54349 2.28645,-1.408 0.55091,-0.60076 0.63405,-1.62275 0.0692,-0.72522 -0.85477,-3.38436 l -2.46381,-7.09103 -13.57909,-12.2571 q -4.034666,-3.62353 -5.323131,-4.05231 -1.297544,-0.45491 -3.001119,0.10777 l -0.335146,-0.96457 16.945476,-5.88778 0.33515,0.96457 -0.75607,0.2627 q -1.53812,0.53443 -2.00989,1.19475 -0.44555,0.65179 -0.27353,1.14689 0.32609,0.93849 3.72516,3.99398 l 10.45421,9.48617 2.65629,-12.87275 q 1.01366,-4.73481 0.5698,-6.01227 -0.24455,-0.70385 -1.08543,-0.93761 -1.11283,-0.34377 -3.53051,0.35017 l -0.33515,-0.96457 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5336);fill-opacity:1;stroke:none;stroke-width:1.41305673"
|
||||
id="letter-y"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 102.64486,200.4253 4.18153,12.03476 -0.93156,0.32368 q -3.40148,-4.34864 -7.667536,-5.7445 -4.266052,-1.39586 -8.269247,-0.005 -3.826954,1.32969 -5.617541,4.37848 -1.79933,3.02363 -1.518338,7.24317 0.280991,4.21955 1.689414,8.2731 1.705854,4.90957 4.149964,8.20824 2.444105,3.29865 5.615805,4.1436 3.196874,0.83619 6.746879,-0.39727 1.23369,-0.42865 2.43025,-1.12657 1.21299,-0.73185 2.39761,-1.70779 l -2.46693,-7.1 q -0.69983,-2.01419 -1.17799,-2.49704 -0.4869,-0.50803 -1.53432,-0.68021 -1.022237,-0.18094 -2.255926,0.24771 l -0.881207,0.30618 -0.323675,-0.93156 16.591858,-5.76491 0.32368,0.93156 q -1.84457,0.78197 -2.45992,1.44726 -0.59892,0.63134 -0.68683,1.6777 -0.0604,0.5571 0.58696,2.42022 l 2.46693,7.1 q -2.76567,2.59752 -6.06198,4.56113 -3.26239,1.98004 -7.06416,3.30099 -4.859227,1.68835 -8.536819,1.49887 -3.661163,-0.22341 -6.872121,-1.50618 -3.194524,-1.3167 -5.515311,-3.52953 -2.969632,-2.86211 -4.465535,-7.16744 -2.676879,-7.70426 0.890426,-14.89749 3.567304,-7.19323 11.775112,-10.04506 2.54291,-0.88355 4.722241,-1.1893 1.177786,-0.18349 3.977586,-0.0841 2.81623,0.0655 3.269421,-0.0919 0.70497,-0.24494 1.13426,-0.95843 0.42055,-0.73868 0.42546,-2.34875 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'times new roman';-inkscape-font-specification:'times new roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5334);fill-opacity:1;stroke:none;stroke-width:1.36467421"
|
||||
id="letter-g"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
3
static/LogoRoyalGamesDotaBanner.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:af8a851565bba2e4a20bb0ad0492249941c220d1b3e6d6f480406f9488728e50
|
||||
size 11441
|
346
static/LogoRoyalGamesDotaBanner.svg
Normal file
|
@ -0,0 +1,346 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.73333 67.733333"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="LogoRoyalGamesDotaBanner.svg"
|
||||
inkscape:export-filename="C:\Users\stepi\PycharmProjects\royalnet\static\LogoRoyalGamesDotaBanner.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<title
|
||||
id="title5190">Royal Games</title>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient5149">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5147" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5042">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5040" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4971">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4969" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Principale"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#a1ccff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4895" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Sfondo"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#0d193b;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop817" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient821"
|
||||
x1="34.745037"
|
||||
y1="124.61114"
|
||||
x2="175.3288"
|
||||
y2="124.61114"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.24090027,0,0,0.2742717,-8.3700906,212.02064)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5332"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.9722906,-1.7276436,1.7276436,4.9722906,-481.91887,-479.70806)"
|
||||
x1="55.743366"
|
||||
y1="152.60051"
|
||||
x2="62.71452"
|
||||
y2="152.60051" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5334"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.8721103,-1.6928355,1.6928355,4.8721103,-559.10679,-570.69534)"
|
||||
x1="65.251831"
|
||||
y1="186.99634"
|
||||
x2="72.946449"
|
||||
y2="186.99634" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient5336"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(5.0448436,-1.7528523,1.7528523,5.0448436,-614.18765,-850.35741)"
|
||||
x1="63.593018"
|
||||
y1="224.03799"
|
||||
x2="71.024086"
|
||||
y2="224.03799" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath5457">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g5453"
|
||||
id="use5459"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5332-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.9722906,-1.7276436,1.7276436,4.9722906,-481.91887,-479.70806)"
|
||||
x1="55.743366"
|
||||
y1="152.60051"
|
||||
x2="62.71452"
|
||||
y2="152.60051" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient5336-0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(5.0448436,-1.7528523,1.7528523,5.0448436,-614.18765,-850.35741)"
|
||||
x1="63.593018"
|
||||
y1="224.03799"
|
||||
x2="71.024086"
|
||||
y2="224.03799" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Principale"
|
||||
id="linearGradient5334-8"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.8721103,-1.6928355,1.6928355,4.8721103,-559.10679,-570.69534)"
|
||||
x1="65.251831"
|
||||
y1="186.99634"
|
||||
x2="72.946449"
|
||||
y2="186.99634" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient821-3"
|
||||
x1="34.745037"
|
||||
y1="124.61114"
|
||||
x2="175.3288"
|
||||
y2="124.61114"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.24090028,0,0,0.27427171,25.496575,212.02064)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient821-8"
|
||||
x1="34.745037"
|
||||
y1="124.61114"
|
||||
x2="175.3288"
|
||||
y2="124.61114"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.24090028,0,0,0.27427171,-8.3700894,245.8873)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Sfondo"
|
||||
id="linearGradient821-8-2"
|
||||
x1="34.745037"
|
||||
y1="124.61114"
|
||||
x2="175.3288"
|
||||
y2="124.61114"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.24090029,0,0,0.27427171,25.496574,245.8873)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="280.19406"
|
||||
inkscape:cy="207.76729"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="main-layer"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:measure-start="384.018,406.607"
|
||||
inkscape:measure-end="388.429,418.649"
|
||||
showguides="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-page="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:lockguides="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1186"
|
||||
originx="0"
|
||||
originy="1.5e-005" />
|
||||
<sodipodi:guide
|
||||
position="33.866664,33.868736"
|
||||
orientation="1,0"
|
||||
id="guide1482"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="33.866664,33.868736"
|
||||
orientation="0,1"
|
||||
id="guide1549"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="16.933333,6.5481033"
|
||||
orientation="1,0"
|
||||
id="guide1597"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Royal Games</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Main Layer"
|
||||
inkscape:groupmode="layer"
|
||||
id="main-layer"
|
||||
transform="translate(0,-229.26669)"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="fill:url(#linearGradient821);fill-opacity:1;stroke-width:0.06800982"
|
||||
id="background"
|
||||
width="33.866665"
|
||||
height="33.866665"
|
||||
x="-1.772949e-006"
|
||||
y="229.26462" />
|
||||
<g
|
||||
id="logo"
|
||||
transform="matrix(0.1136997,0,0,0.11369973,0.96681376,227.68007)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="star"
|
||||
d="m 55.674623,47.499965 23.70863,68.248035 5.283398,-7.9251 5.291666,7.9375 5.291667,-7.9375 v 27.78125 c 0,0 -3.96081,0.36871 -8.719881,0.71727 l 36.012267,103.66498 105.39511,38.24676 -69.9983,-88.16309 66.02232,-87.15178 -103.69547,36.69078 z"
|
||||
style="display:inline;opacity:0.98999999;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="crown"
|
||||
d="m 86.530103,136.32142 -7.14685,-20.57342 -0.0083,0.0124 -5.291667,-7.93751 -5.291666,7.93751 -5.291622,-7.9375 -5.291667,7.93751 -5.291666,-7.93751 v 27.78126 c 0,0 14.097344,1.32291 21.166666,1.32291 3.331782,0 8.204375,-0.29493 12.446786,-0.60565 z"
|
||||
style="display:inline;opacity:1;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
d="m 72.507099,179.7588 3.39258,9.76411 q 0.982062,2.82645 1.575007,3.45555 0.609709,0.59447 1.635113,0.72773 1.025404,0.13327 3.415041,-0.69702 l 0.330331,0.95072 -17.832346,6.19592 -0.330331,-0.95071 q 2.415332,-0.83922 3.111495,-1.57065 0.712931,-0.76606 0.796984,-1.60159 0.109751,-0.84445 -0.872311,-3.6709 l -7.856504,-22.61162 q -0.982062,-2.82645 -1.591772,-3.42092 -0.592945,-0.6291 -1.618348,-0.76236 -1.025404,-0.13327 -3.415041,0.69702 l -0.330331,-0.95072 16.187864,-5.62454 q 6.320976,-2.19625 9.553754,-2.3404 3.232782,-0.14414 5.904185,1.577 2.662477,1.69545 3.7606,4.85593 1.339177,3.85425 -0.560957,7.33657 -1.219429,2.20912 -4.128851,4.11271 l 12.474459,8.88354 q 2.439061,1.71548 3.329239,2.03972 1.330261,0.4305 2.744571,0.0255 l 0.33033,0.95072 -10.971772,3.81219 -16.746132,-11.97806 z m -5.937017,-17.08719 5.303137,15.26284 1.464616,-0.50889 q 3.571608,-1.24097 5.121371,-2.49936 1.540832,-1.2841 1.953701,-3.32815 0.429633,-2.07869 -0.525644,-4.82805 -1.383817,-3.98273 -3.920215,-5.23243 -2.5107,-1.25862 -6.647599,0.17876 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5332);fill-opacity:1;stroke:none;stroke-width:1.39273477"
|
||||
id="letter-r"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 130.68189,137.70908 0.33514,0.96457 q -1.66517,0.84148 -2.33195,1.94973 -0.92304,1.54784 -2.04475,7.40121 l -3.217,15.4634 2.97106,8.55096 q 0.9511,2.73733 1.47316,3.3156 0.513,0.55218 1.52862,0.78362 1.03243,0.19649 2.4402,-0.29264 l 1.98136,-0.68843 0.33514,0.96457 -19.83925,6.89323 -0.33514,-0.96457 1.85095,-0.64312 q 1.5642,-0.54349 2.28645,-1.408 0.55091,-0.60076 0.63405,-1.62275 0.0692,-0.72522 -0.85477,-3.38436 l -2.46381,-7.09103 -13.57909,-12.2571 q -4.034666,-3.62353 -5.323131,-4.05231 -1.297544,-0.45491 -3.001119,0.10777 l -0.335146,-0.96457 16.945476,-5.88778 0.33515,0.96457 -0.75607,0.2627 q -1.53812,0.53443 -2.00989,1.19475 -0.44555,0.65179 -0.27353,1.14689 0.32609,0.93849 3.72516,3.99398 l 10.45421,9.48617 2.65629,-12.87275 q 1.01366,-4.73481 0.5698,-6.01227 -0.24455,-0.70385 -1.08543,-0.93761 -1.11283,-0.34377 -3.53051,0.35017 l -0.33515,-0.96457 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5336);fill-opacity:1;stroke:none;stroke-width:1.41305673"
|
||||
id="letter-y"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 102.64486,200.4253 4.18153,12.03476 -0.93156,0.32368 q -3.40148,-4.34864 -7.667536,-5.7445 -4.266052,-1.39586 -8.269247,-0.005 -3.826954,1.32969 -5.617541,4.37848 -1.79933,3.02363 -1.518338,7.24317 0.280991,4.21955 1.689414,8.2731 1.705854,4.90957 4.149964,8.20824 2.444105,3.29865 5.615805,4.1436 3.196874,0.83619 6.746879,-0.39727 1.23369,-0.42865 2.43025,-1.12657 1.21299,-0.73185 2.39761,-1.70779 l -2.46693,-7.1 q -0.69983,-2.01419 -1.17799,-2.49704 -0.4869,-0.50803 -1.53432,-0.68021 -1.022237,-0.18094 -2.255926,0.24771 l -0.881207,0.30618 -0.323675,-0.93156 16.591858,-5.76491 0.32368,0.93156 q -1.84457,0.78197 -2.45992,1.44726 -0.59892,0.63134 -0.68683,1.6777 -0.0604,0.5571 0.58696,2.42022 l 2.46693,7.1 q -2.76567,2.59752 -6.06198,4.56113 -3.26239,1.98004 -7.06416,3.30099 -4.859227,1.68835 -8.536819,1.49887 -3.661163,-0.22341 -6.872121,-1.50618 -3.194524,-1.3167 -5.515311,-3.52953 -2.969632,-2.86211 -4.465535,-7.16744 -2.676879,-7.70426 0.890426,-14.89749 3.567304,-7.19323 11.775112,-10.04506 2.54291,-0.88355 4.722241,-1.1893 1.177786,-0.18349 3.977586,-0.0841 2.81623,0.0655 3.269421,-0.0919 0.70497,-0.24494 1.13426,-0.95843 0.42055,-0.73868 0.42546,-2.34875 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'times new roman';-inkscape-font-specification:'times new roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5334);fill-opacity:1;stroke:none;stroke-width:1.36467421"
|
||||
id="letter-g"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<rect
|
||||
style="display:inline;fill:url(#linearGradient821-3);fill-opacity:1;stroke-width:0.06800982"
|
||||
id="background-1"
|
||||
width="33.866665"
|
||||
height="33.866665"
|
||||
x="33.866665"
|
||||
y="229.26462" />
|
||||
<g
|
||||
style="display:inline"
|
||||
id="logo-3"
|
||||
transform="matrix(-0.1136997,0,0,0.11369973,66.766512,227.68007)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="star-7"
|
||||
d="m 55.674623,47.499965 23.70863,68.248035 5.283398,-7.9251 5.291666,7.9375 5.291667,-7.9375 v 27.78125 c 0,0 -3.96081,0.36871 -8.719881,0.71727 l 36.012267,103.66498 105.39511,38.24676 -69.9983,-88.16309 66.02232,-87.15178 -103.69547,36.69078 z"
|
||||
style="display:inline;opacity:0.98999999;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="crown-7"
|
||||
d="m 86.530103,136.32142 -7.14685,-20.57342 -0.0083,0.0124 -5.291667,-7.93751 -5.291666,7.93751 -5.291622,-7.9375 -5.291667,7.93751 -5.291666,-7.93751 v 27.78126 c 0,0 14.097344,1.32291 21.166666,1.32291 3.331782,0 8.204375,-0.29493 12.446786,-0.60565 z"
|
||||
style="display:inline;opacity:1;fill:#a1ccff;fill-opacity:1;stroke-width:0.33488649" />
|
||||
<path
|
||||
d="m 72.507099,179.7588 3.39258,9.76411 q 0.982062,2.82645 1.575007,3.45555 0.609709,0.59447 1.635113,0.72773 1.025404,0.13327 3.415041,-0.69702 l 0.330331,0.95072 -17.832346,6.19592 -0.330331,-0.95071 q 2.415332,-0.83922 3.111495,-1.57065 0.712931,-0.76606 0.796984,-1.60159 0.109751,-0.84445 -0.872311,-3.6709 l -7.856504,-22.61162 q -0.982062,-2.82645 -1.591772,-3.42092 -0.592945,-0.6291 -1.618348,-0.76236 -1.025404,-0.13327 -3.415041,0.69702 l -0.330331,-0.95072 16.187864,-5.62454 q 6.320976,-2.19625 9.553754,-2.3404 3.232782,-0.14414 5.904185,1.577 2.662477,1.69545 3.7606,4.85593 1.339177,3.85425 -0.560957,7.33657 -1.219429,2.20912 -4.128851,4.11271 l 12.474459,8.88354 q 2.439061,1.71548 3.329239,2.03972 1.330261,0.4305 2.744571,0.0255 l 0.33033,0.95072 -10.971772,3.81219 -16.746132,-11.97806 z m -5.937017,-17.08719 5.303137,15.26284 1.464616,-0.50889 q 3.571608,-1.24097 5.121371,-2.49936 1.540832,-1.2841 1.953701,-3.32815 0.429633,-2.07869 -0.525644,-4.82805 -1.383817,-3.98273 -3.920215,-5.23243 -2.5107,-1.25862 -6.647599,0.17876 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5332-9);fill-opacity:1;stroke:none;stroke-width:1.39273477"
|
||||
id="letter-r-1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 130.68189,137.70908 0.33514,0.96457 q -1.66517,0.84148 -2.33195,1.94973 -0.92304,1.54784 -2.04475,7.40121 l -3.217,15.4634 2.97106,8.55096 q 0.9511,2.73733 1.47316,3.3156 0.513,0.55218 1.52862,0.78362 1.03243,0.19649 2.4402,-0.29264 l 1.98136,-0.68843 0.33514,0.96457 -19.83925,6.89323 -0.33514,-0.96457 1.85095,-0.64312 q 1.5642,-0.54349 2.28645,-1.408 0.55091,-0.60076 0.63405,-1.62275 0.0692,-0.72522 -0.85477,-3.38436 l -2.46381,-7.09103 -13.57909,-12.2571 q -4.034666,-3.62353 -5.323131,-4.05231 -1.297544,-0.45491 -3.001119,0.10777 l -0.335146,-0.96457 16.945476,-5.88778 0.33515,0.96457 -0.75607,0.2627 q -1.53812,0.53443 -2.00989,1.19475 -0.44555,0.65179 -0.27353,1.14689 0.32609,0.93849 3.72516,3.99398 l 10.45421,9.48617 2.65629,-12.87275 q 1.01366,-4.73481 0.5698,-6.01227 -0.24455,-0.70385 -1.08543,-0.93761 -1.11283,-0.34377 -3.53051,0.35017 l -0.33515,-0.96457 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5336-0);fill-opacity:1;stroke:none;stroke-width:1.41305673"
|
||||
id="letter-y-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 102.64486,200.4253 4.18153,12.03476 -0.93156,0.32368 q -3.40148,-4.34864 -7.667536,-5.7445 -4.266052,-1.39586 -8.269247,-0.005 -3.826954,1.32969 -5.617541,4.37848 -1.79933,3.02363 -1.518338,7.24317 0.280991,4.21955 1.689414,8.2731 1.705854,4.90957 4.149964,8.20824 2.444105,3.29865 5.615805,4.1436 3.196874,0.83619 6.746879,-0.39727 1.23369,-0.42865 2.43025,-1.12657 1.21299,-0.73185 2.39761,-1.70779 l -2.46693,-7.1 q -0.69983,-2.01419 -1.17799,-2.49704 -0.4869,-0.50803 -1.53432,-0.68021 -1.022237,-0.18094 -2.255926,0.24771 l -0.881207,0.30618 -0.323675,-0.93156 16.591858,-5.76491 0.32368,0.93156 q -1.84457,0.78197 -2.45992,1.44726 -0.59892,0.63134 -0.68683,1.6777 -0.0604,0.5571 0.58696,2.42022 l 2.46693,7.1 q -2.76567,2.59752 -6.06198,4.56113 -3.26239,1.98004 -7.06416,3.30099 -4.859227,1.68835 -8.536819,1.49887 -3.661163,-0.22341 -6.872121,-1.50618 -3.194524,-1.3167 -5.515311,-3.52953 -2.969632,-2.86211 -4.465535,-7.16744 -2.676879,-7.70426 0.890426,-14.89749 3.567304,-7.19323 11.775112,-10.04506 2.54291,-0.88355 4.722241,-1.1893 1.177786,-0.18349 3.977586,-0.0841 2.81623,0.0655 3.269421,-0.0919 0.70497,-0.24494 1.13426,-0.95843 0.42055,-0.73868 0.42546,-2.34875 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:1.25;font-family:'times new roman';-inkscape-font-specification:'times new roman, Bold';letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5334-8);fill-opacity:1;stroke:none;stroke-width:1.36467421"
|
||||
id="letter-g-3"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
style="display:inline;fill:url(#linearGradient821-8);fill-opacity:1;stroke-width:0.06800982"
|
||||
d="M 6.7199593e-8,263.13129 H 33.866665 v 33.86666 c 0,0 -25.7079536,-10.33088 -16.933332,-10.33088 C 25.758426,286.66707 6.719959e-8,296.99795 6.719959e-8,296.99795 Z"
|
||||
id="background-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccscc" />
|
||||
<path
|
||||
style="display:inline;fill:url(#linearGradient821-8-2);fill-opacity:1;stroke-width:0.06800982"
|
||||
d="M 33.866664,263.13129 H 67.73333 v 33.86666 c 0,0 -25.707954,-10.33088 -16.933333,-10.33088 8.825093,0 -16.933333,10.33088 -16.933333,10.33088 z"
|
||||
id="background-2-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccscc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 299 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 387 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 353 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 357 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 362 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 305 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 131 B |
272
static/nryg.less
|
@ -18,10 +18,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
color: @accent-color;
|
||||
}
|
||||
|
||||
h1 .whatsthis {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @link-color;
|
||||
text-decoration: none;
|
||||
|
@ -75,7 +71,7 @@ code {
|
|||
font-family: "Consolas", "Source Code Pro", monospace;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="password"] {
|
||||
input[type="text"], input[type="password"], input[type="email"] {
|
||||
background-color: rgba(red(@text-color), green(@text-color), blue(@text-color), 0.1);
|
||||
color: @text-color;
|
||||
border: none;
|
||||
|
@ -213,21 +209,60 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
|
||||
&.multicolumn {
|
||||
column-width: 192px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
li {
|
||||
&::before {
|
||||
content: "•";
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
margin-left: -1em;
|
||||
}
|
||||
|
||||
&.list-admin {
|
||||
&::before {
|
||||
color: #ffff00;
|
||||
}
|
||||
}
|
||||
|
||||
&.list-locked {
|
||||
&::before {
|
||||
color: #555555;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
|
||||
@media (max-width:792px) {
|
||||
max-width: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.gravatar {
|
||||
border-radius: 16px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.whatsthis {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.omnicontainer {
|
||||
width: 380px;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
@media (min-width: 792px)
|
||||
{
|
||||
width: 776px;
|
||||
}
|
||||
|
||||
@media (min-width: 1180px)
|
||||
{
|
||||
width: 1164px;
|
||||
}
|
||||
|
||||
@media (min-width: 1568px) {
|
||||
width: 1552px;
|
||||
}
|
||||
|
@ -270,18 +305,6 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
@media (min-width:601px) {
|
||||
.mobile-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:600px) {
|
||||
.desktop-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.game-panel {
|
||||
display: inline-block;
|
||||
margin: 4px;
|
||||
|
@ -511,6 +534,10 @@ table {
|
|||
|
||||
img.medal {
|
||||
height: 60px;
|
||||
|
||||
&.locked {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -696,30 +723,78 @@ table {
|
|||
.ryg {
|
||||
background-color: rgba(red(@text-color), green(@text-color), blue(@text-color), 0.1);
|
||||
padding: 18px;
|
||||
grid-template-columns: 80% 20%;
|
||||
grid-template-rows: 32px 16px 16px 36px;
|
||||
grid-template-columns: 33.3% 33.3% 33.3%;
|
||||
|
||||
.player {
|
||||
.username {
|
||||
grid-row: 1;
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 3;
|
||||
font-weight: bold;
|
||||
grid-column: 1 / 3;
|
||||
font-size: x-large;
|
||||
align-self: center;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.member-status {
|
||||
.special-title {
|
||||
grid-row: 1;
|
||||
grid-column: 3;
|
||||
font-size: small;
|
||||
align-self: center;
|
||||
justify-self: flex-end;
|
||||
font-style: italic;
|
||||
color: @accent-color;
|
||||
}
|
||||
|
||||
.join-date-title {
|
||||
grid-row: 3;
|
||||
grid-column: 1;
|
||||
grid-row-start: 2;
|
||||
grid-row-end: 4;
|
||||
font-size: x-large;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
font-size: xx-small;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.join-date {
|
||||
grid-row: 4;
|
||||
grid-column: 1;
|
||||
font-size: large;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
|
||||
}
|
||||
|
||||
.wiki-edits-title {
|
||||
grid-row: 3;
|
||||
grid-column: 2;
|
||||
font-size: xx-small;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.wiki-edits {
|
||||
grid-row: 4;
|
||||
grid-column: 2;
|
||||
font-size: large;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.fiorygi-title {
|
||||
grid-row: 3;
|
||||
grid-column: 3;
|
||||
font-size: xx-small;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.fiorygi {
|
||||
grid-column: 2;
|
||||
grid-row: 4;
|
||||
grid-column: 3;
|
||||
font-size: large;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.fiorygi.game-score {
|
||||
font-size: x-large;
|
||||
.unknown {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -809,13 +884,50 @@ table {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.terraria13 {
|
||||
border: 3px solid black;
|
||||
padding: 15px;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), url("/static/stoneslab.png");
|
||||
font-family: "Andy", sans-serif;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
grid-row-gap: 5px;
|
||||
|
||||
.character {
|
||||
grid-row: 1;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
.contribution-status {
|
||||
grid-row: 2;
|
||||
|
||||
.contribution {
|
||||
font-size: xx-large;
|
||||
|
||||
&.blue {
|
||||
color: #8686e5;
|
||||
}
|
||||
|
||||
&.green {
|
||||
color: #92f892;
|
||||
}
|
||||
|
||||
&.orange {
|
||||
color: #e9b688;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wiki {
|
||||
|
||||
.wiki-log {
|
||||
.wiki-log, .wiki-locked {
|
||||
font-family: "Consolas", "Source Code Pro", monospace;
|
||||
font-size: small;
|
||||
margin-bottom: 12px;
|
||||
opacity: 0.4;
|
||||
|
||||
.last-reason {
|
||||
font-style: italic;
|
||||
|
@ -837,7 +949,7 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
.diario {
|
||||
display: grid;
|
||||
|
||||
.left {
|
||||
|
@ -854,15 +966,15 @@ table {
|
|||
font-size: smaller;
|
||||
}
|
||||
|
||||
.entry-id {
|
||||
.diario-id {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.main-page {
|
||||
.two-columns {
|
||||
display: grid;
|
||||
|
||||
@media (min-width:601px) {
|
||||
@media (min-width:791px) {
|
||||
//Desktop
|
||||
|
||||
grid-template-columns: 50% 50%;
|
||||
|
@ -876,7 +988,7 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
@media (max-width:600px) {
|
||||
@media (max-width:792px) {
|
||||
//Mobile
|
||||
|
||||
grid-template-columns: 100%;
|
||||
|
@ -894,11 +1006,6 @@ table {
|
|||
grid-row-end: 3;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
column-width: 200px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
.event {
|
||||
|
@ -942,6 +1049,65 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.quest {
|
||||
padding: 8px;
|
||||
color: @accent-color;
|
||||
font-family: "Verdana", sans-serif;
|
||||
background-image: url("/static/plank.jpg");
|
||||
display: grid;
|
||||
grid-template-columns: auto 64px;
|
||||
grid-row-gap: 2px;
|
||||
margin-bottom: 1px;
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
|
||||
.title {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.description {
|
||||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.reward {
|
||||
grid-row-start: 1;
|
||||
grid-row-end: 3;
|
||||
grid-column: 2;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.number {
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
.subtext {
|
||||
font-size: smaller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#royal-games {
|
||||
font-size: 64px;
|
||||
text-align: center;
|
||||
|
||||
@media (max-width:792px) {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 128px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
#debug-mode {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
|
|
3
static/plank.jpg
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ec59480cf8db818b449242d83ec720ae23154eff9f8cdf33ac6c2a53bfb4f3aa
|
||||
size 1459923
|
3
static/rank_icon_locked.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ebabd07ca06e02e43486019112ffaa65cb068aa15340797d5c46980c32a6116f
|
||||
size 37273
|
3
static/stoneslab.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1ddb8b02a67b7890df9530ffe7ccc1c1b2fc700045b2ffd483694bbdffd561f0
|
||||
size 12108
|
3
static/terrariafont.ttf
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7697ec2286230bcfbb4c668968193d0da1621e7b97bd15137e51811b482eaf2d
|
||||
size 83083
|
|
@ -11,8 +11,8 @@ import telegram
|
|||
import sys
|
||||
import coloredlogs
|
||||
import requests
|
||||
from dirty import Dirty
|
||||
from sentry_sdk import configure_scope
|
||||
import strings
|
||||
from utils import Dirty, DirtyDelta, reply_msg
|
||||
|
||||
logging.getLogger().disabled = True
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -30,21 +30,16 @@ sentry = raven.Client(config["Sentry"]["token"],
|
|||
hook_libraries=[])
|
||||
|
||||
telegram_bot = telegram.Bot(config["Telegram"]["bot_token"])
|
||||
main_chat_id = config["Telegram"]["main_group"]
|
||||
|
||||
|
||||
def update_block(session: db.Session, block: list, delay: float=0, change_callback: typing.Callable=None):
|
||||
def update_block(session: db.Session, block: list, delay: float = 0, change_callback: typing.Callable = None):
|
||||
for item in block:
|
||||
logger.debug(f"Updating {repr(item)}.")
|
||||
t = time.clock()
|
||||
try:
|
||||
change = item.update(session=session)
|
||||
except requests.exceptions.HTTPError as e:
|
||||
with configure_scope() as scope:
|
||||
if str(e.response.status_code).startswith("5"):
|
||||
scope.level = "warning"
|
||||
logger.warning(f"Server error {sys.exc_info()} while updating {repr(item)}.")
|
||||
else:
|
||||
scope.level = "error"
|
||||
logger.error(f"Error {sys.exc_info()} while updating {repr(item)}.")
|
||||
sentry.extra_context({
|
||||
"item": repr(item),
|
||||
|
@ -76,12 +71,11 @@ def new_dota_rank(item: db.Dota, change):
|
|||
f" {item.get_rank_name()} {item.get_rank_number()} su Dota 2!")
|
||||
except Exception:
|
||||
logger.warning(f"Couldn't notify on Telegram: {item}")
|
||||
sentry.captureException()
|
||||
|
||||
|
||||
def new_lol_rank(item, change: typing.Tuple[Dirty]):
|
||||
def new_lol_rank(item, change: typing.Tuple[Dirty, Dirty, Dirty]):
|
||||
# It always gets called, even when there is no change
|
||||
# Assignment inspection is wrong
|
||||
# noinspection PyTupleAssignmentBalance
|
||||
solo, flex, twtr = change
|
||||
try:
|
||||
if solo:
|
||||
|
@ -107,11 +101,65 @@ def new_lol_rank(item, change: typing.Tuple[Dirty]):
|
|||
parse_mode="Markdown")
|
||||
except Exception:
|
||||
logger.warning(f"Couldn't notify on Telegram: {item}")
|
||||
sentry.captureException()
|
||||
|
||||
|
||||
def osu_pp_change(item, change: typing.Tuple[DirtyDelta, DirtyDelta, DirtyDelta, DirtyDelta]):
|
||||
std, taiko, catch, mania = change
|
||||
try:
|
||||
if std.delta >= 1:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
f"✳️ {item.royal.username} ha ora <b>{int(std.value)}pp</b> (+{int(std.delta)}) su osu!",
|
||||
parse_mode="HTML")
|
||||
if taiko.delta >= 1:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
f"✳️ {item.royal.username} ha ora <b>{int(taiko.value)}pp</b> (+{int(taiko.delta)}) su osu!taiko!",
|
||||
parse_mode="HTML")
|
||||
if catch.delta >= 1:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
f"✳️ {item.royal.username} ha ora <b>{int(catch.value)}pp</b> (+{int(catch.delta)}) su osu!catch!",
|
||||
parse_mode="HTML")
|
||||
if mania.delta >= 1:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
f"✳️ {item.royal.username} ha ora <b>{int(mania.value)}pp</b> (+{int(mania.delta)}) su osu!mania!",
|
||||
parse_mode="HTML")
|
||||
except Exception:
|
||||
logger.warning(f"Couldn't notify on Telegram: {item}")
|
||||
sentry.captureException()
|
||||
|
||||
|
||||
def brawlhalla_rank_change(item, change: typing.Tuple[DirtyDelta, Dirty]):
|
||||
solo, team = change
|
||||
try:
|
||||
if solo.delta >= 10:
|
||||
reply_msg(telegram_bot, main_chat_id, strings.STATSUPDATE.BRAWLHALLA.SOLO,
|
||||
username=item.steam.royal.telegram.mention(),
|
||||
rating=solo.value,
|
||||
delta=solo.difference_string())
|
||||
if team.is_dirty():
|
||||
partner = item.best_team_partner
|
||||
if partner is None:
|
||||
other = "qualcun altro"
|
||||
else:
|
||||
other = partner.steam.royal.telegram.mention()
|
||||
reply_msg(telegram_bot, main_chat_id, strings.STATSUPDATE.BRAWLHALLA.TEAM,
|
||||
username=item.steam.royal.telegram.mention(),
|
||||
rating=team.value[1],
|
||||
other=other)
|
||||
except Exception:
|
||||
logger.warning(f"Couldn't notify on Telegram: {item}")
|
||||
sentry.captureException()
|
||||
|
||||
|
||||
def process():
|
||||
while True:
|
||||
session = db.Session()
|
||||
logger.info("Now updating League of Legends data.")
|
||||
update_block(session, session.query(db.Brawlhalla).all(), delay=5, change_callback=brawlhalla_rank_change)
|
||||
session.commit()
|
||||
logger.info("Now updating osu! data.")
|
||||
update_block(session, session.query(db.Osu).all(), delay=5, change_callback=osu_pp_change)
|
||||
session.commit()
|
||||
logger.info("Now updating Steam data.")
|
||||
update_block(session, session.query(db.Steam).all())
|
||||
session.commit()
|
||||
|
@ -121,12 +169,6 @@ def process():
|
|||
logger.info("Now updating League of Legends data.")
|
||||
update_block(session, session.query(db.LeagueOfLegends).all(), delay=5, change_callback=new_lol_rank)
|
||||
session.commit()
|
||||
logger.info("Now updating osu! data.")
|
||||
update_block(session, session.query(db.Osu).all(), delay=5)
|
||||
session.commit()
|
||||
logger.info("Now updating Overwatch data.")
|
||||
update_block(session, session.query(db.Overwatch).all(), delay=5)
|
||||
session.commit()
|
||||
logger.info("Pausing for 30 minutes.")
|
||||
time.sleep(1800)
|
||||
|
||||
|
|
268
strings.py
Normal file
|
@ -0,0 +1,268 @@
|
|||
import utils
|
||||
import dice
|
||||
import typing
|
||||
|
||||
|
||||
class SafeDict(dict):
|
||||
def __missing__(self, key):
|
||||
return "{" + key + "}"
|
||||
|
||||
|
||||
def safely_format_string(string: str, words: typing.Dict[str, str] = None, ignore_escaping=False) -> str:
|
||||
if words is None:
|
||||
words = {}
|
||||
if ignore_escaping:
|
||||
escaped = words
|
||||
else:
|
||||
escaped = {}
|
||||
for key in words:
|
||||
escaped[key] = str(words[key]).replace("<", "<").replace(">", ">")
|
||||
return string.format_map(SafeDict(**escaped))
|
||||
|
||||
|
||||
# Generic telegram errors
|
||||
class TELEGRAM:
|
||||
BOT_STARTED = "✅ Hai autorizzato il bot ad inviarti messaggi privati."
|
||||
FIORYGI_AWARDED = "⭐️ {mention} è stato premiato con <b>{number} {fiorygi}</b> per <i>{reason}</i>!"
|
||||
|
||||
class ERRORS:
|
||||
CRITICAL_ERROR = "☢ <b>ERRORE CRITICO!</b>\nIl bot ha ignorato il comando.\nUna segnalazione di errore è stata automaticamente mandata a @Steffo.\n\nDettagli dell'errore:\n<pre>{exc_info}</pre>"
|
||||
CRITICAL_ERROR_QUERY = "☢ ERRORE CRITICO!"
|
||||
UNAUTHORIZED_USER = "⚠ Non sono autorizzato a inviare messaggi a {mention}.\nPer piacere, {mention}, inviami un messaggio in privata!"
|
||||
UNAUTHORIZED_GROUP = "⚠ Non sono autorizzato a inviare messaggi in <i>{group}</i>.\n@Steffo, aggiungimi al gruppo o concedimi i permessi!"
|
||||
|
||||
|
||||
PONG = "🏓 Pong!"
|
||||
ESCAPE = "{text}"
|
||||
|
||||
|
||||
# Ah, non lo so io.
|
||||
class AHNONLOSOIO:
|
||||
ONCE = "😐 Ah, non lo so io!"
|
||||
AGAIN = "😐 Ah, non lo so nemmeno io..."
|
||||
|
||||
|
||||
# Bridge commands between Discord and Telegram
|
||||
class BRIDGE:
|
||||
SUCCESS = "✅ Comando inoltrato a Discord."
|
||||
FAILURE = "❎ Errore nell'esecuzione del comando su Discord."
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato un comando!\nSintassi: <code>/bridge (comando)</code>"
|
||||
INACTIVE_BRIDGE = "⚠ Il collegamento tra Telegram e Discord non è attivo al momento."
|
||||
|
||||
|
||||
# Random spellslinging
|
||||
class CAST:
|
||||
class ERRORS:
|
||||
NOT_YET_AVAILABLE = "⚠ Il nuovo cast non è ancora disponibile! Per un'anteprima sulle nuove funzioni, usa <code>/spell</code>."
|
||||
|
||||
|
||||
# Ciao Ruozi!
|
||||
class CIAORUOZI:
|
||||
THE_LEGEND_HIMSELF = "👋 Ciao me!"
|
||||
SOMEBODY_ELSE = "👋 Ciao Ruozi!"
|
||||
|
||||
|
||||
# The /color meme, from Octeon
|
||||
COLOR = "<i>I am sorry, unknown error occured during working with your request, Admin were notified</i>"
|
||||
|
||||
|
||||
# Diario
|
||||
class DIARIO:
|
||||
SUCCESS = "✅ Riga aggiunta al diario:\n{diario}"
|
||||
ANONYMOUS = "Anonimo"
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Sintassi del comando errata.\nSintassi: <code>/diario (frase)</code>, oppure rispondi a un messaggio con <code>/diario</code>."
|
||||
NO_TEXT = "⚠ Il messaggio a cui hai risposto non contiene testo."
|
||||
|
||||
|
||||
# Diario search
|
||||
class DIARIOSEARCH:
|
||||
HEADER = "ℹ️ Risultati della ricerca di {term}:\n"
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato un termine da cercare!\nSintassi: <code>/{command} (termine)</code>"
|
||||
RESULTS_TOO_LONG = "⚠ Sono presenti troppi risultati da visualizzare! Prova a restringere la ricerca."
|
||||
|
||||
|
||||
# Eat!
|
||||
class EAT:
|
||||
FOODS = {
|
||||
"_default": "🍗 Hai mangiato {food}!\n<i>Ma non succede nulla.</i>",
|
||||
"tonnuooooooro": "👻 Il {food} che hai mangiato era posseduto.\n<i>Spooky!</i>",
|
||||
"uranio": "☢️ L'{food} che hai mangiato era radioattivo.\n<i>Stai brillando di verde!</i>",
|
||||
"pollo": '🍗 Il {food} che hai appena mangiato proveniva <a href="https://store.steampowered.com/app/353090/Chicken_Invaders_5/">dallo spazio</a>.\n<i>Coccodè?</i>',
|
||||
"ragno": "🕸 Hai mangiato un {food}.\n<i>Ewww!</i>",
|
||||
"curry": "🔥 BRUCIAAAAAAAAAA! Il {food} era piccantissimo!\n<i>Stai sputando fiamme!</i>",
|
||||
"torta": "⬜️ Non hai mangiato niente.\n<i>La {food} è una menzogna!</i>",
|
||||
"cake": "⬜️ Non hai mangiato niente.\n<i>The {food} is a lie!</i>",
|
||||
"biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n<i>L'Inquisizione non lo saprà mai!</i>",
|
||||
"biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n<i>Attento! L'Inquisizione è sulle tue tracce!</i>",
|
||||
"tango": "🌳 Hai mangiato un {food}, e un albero insieme ad esso.\n<i>Senti il tuo corpo curare le tue ferite.</i>",
|
||||
"sasso": "🥌 Il {food} che hai mangiato era duro come un {food}\n<i>Stai soffrendo di indigestione!</i>",
|
||||
"gnocchetti": "🥘 Ullà, sono duri 'sti {food}!\n<i>Fai fatica a digerirli.</i>",
|
||||
"tide pods": "☣️ I {food} che hai mangiato erano buonissimi.\n<i>Stai sbiancando!</i>"
|
||||
}
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato cosa mangiare!\nSintassi: <code>/eat (cibo)</code>"
|
||||
|
||||
|
||||
# Emojify a string
|
||||
class EMOJIFY:
|
||||
RESPONSE = "{emojified}"
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato una frase!\nSintassi: <code>/emojify (testo)</code>"
|
||||
|
||||
|
||||
# Royalnet linking
|
||||
class LINK:
|
||||
SUCCESS = "✅ Collegamento riuscito!"
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato un username!\nSintassi: <code>/link (username)</code>"
|
||||
NOT_FOUND = "⚠ Non esiste nessun account Royalnet con quel nome.\nNota: gli username sono case-sensitive, e iniziano sempre con una maiuscola!"
|
||||
ALREADY_EXISTING = "⚠ Questo account è già collegato a un account Royalnet."
|
||||
ROYALNET_NOT_LINKED = "⚠ Il tuo account Telegram non è connesso a Royalnet! Connettilo con <code>/link (username)</code>."
|
||||
|
||||
|
||||
# Markov strings
|
||||
class MARKOV:
|
||||
class ERRORS:
|
||||
NO_MODEL = "⚠ La catena di Markov non è disponibile."
|
||||
GENERATION_FAILED = "⚠ <code>markovify</code> non è riuscito a generare una frase. Prova di nuovo?\n E' un'avvenimento sorprendentemente raro..."
|
||||
SPECIFIC_WORD_FAILED = "⚠ <code>markovify</code> non è riuscito a generare una frase partendo da questa parola. Provane una diversa..."
|
||||
MISSING_WORD = "⚠ La parola specificata non è presente nella catena di Markov. Provane una diversa..."
|
||||
|
||||
|
||||
# Matchmaking service strings
|
||||
class MATCHMAKING:
|
||||
EMOJIS = {
|
||||
"ready": "🔵",
|
||||
"wait_for_me": "🕒",
|
||||
"maybe": "❓",
|
||||
"ignore": "❌",
|
||||
"close": "🚩",
|
||||
"cancel": "🗑"
|
||||
}
|
||||
|
||||
ENUM_TO_EMOJIS = {
|
||||
utils.MatchmakingStatus.READY: EMOJIS["ready"],
|
||||
utils.MatchmakingStatus.WAIT_FOR_ME: EMOJIS["wait_for_me"],
|
||||
utils.MatchmakingStatus.MAYBE: EMOJIS["maybe"],
|
||||
utils.MatchmakingStatus.IGNORED: EMOJIS["ignore"],
|
||||
}
|
||||
|
||||
BUTTONS = {
|
||||
"match_ready": f"{EMOJIS['ready']} Sono pronto per iniziare!",
|
||||
"match_wait_for_me": f"{EMOJIS['wait_for_me']} Ci sarò, aspettatemi!",
|
||||
"match_maybe": f"{EMOJIS['maybe']} Forse vengo, se non ci sono fate senza di me.",
|
||||
"match_ignore": f"{EMOJIS['ignore']} Non ci sarò.",
|
||||
"match_close": f"{EMOJIS['close']} ADMIN: Avvia la partita",
|
||||
"match_cancel": f"{EMOJIS['cancel']} ADMIN: Annulla la partita"
|
||||
}
|
||||
|
||||
TICKER_TEXT = {
|
||||
"match_ready": f"{EMOJIS['ready']} Hai detto che sei pronto per giocare!",
|
||||
"match_wait_for_me": f"{EMOJIS['wait_for_me']} Hai chiesto agli altri di aspettarti.",
|
||||
"match_maybe": f"{EMOJIS['maybe']} Hai detto che forse ci sarai.",
|
||||
"match_ignore": f"{EMOJIS['ignore']} Non hai intenzione di partecipare.",
|
||||
"match_close": f"{EMOJIS['close']} Hai notificato tutti che la partita sta iniziando.",
|
||||
"match_cancel": f"{EMOJIS['cancel']} Hai annullato la partita."
|
||||
}
|
||||
|
||||
GAME_START = {
|
||||
int(utils.MatchmakingStatus.READY): "🔵 Che <b>{match_title}</b> abbia inizio!",
|
||||
int(utils.MatchmakingStatus.WAIT_FOR_ME): "🕒 Sbrigati! <b>{match_title}</b> sta per iniziare!",
|
||||
int(utils.MatchmakingStatus.MAYBE): "❓ <b>{match_title}</b> sta iniziando. Se vuoi partecipare, fai in fretta!",
|
||||
}
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Sintassi del comando errata.\nSintassi: <pre>/mm [minplayers-][maxplayers] ['per'] (gamename) \\n[descrizione]</pre>"
|
||||
NOT_ADMIN = "⚠ Non sei il creatore di questo match!"
|
||||
MATCH_CLOSED = "⚠ Il matchmaking per questa partita è terminato."
|
||||
|
||||
|
||||
# Pug sender
|
||||
class PUG:
|
||||
HERE_HAVE_A_PUG = '🐶 Ecco, tieni un <a href="{image_url}">carlino</a>.'
|
||||
|
||||
class ERRORS:
|
||||
PRIVATE_CHAT_ONLY = "⚠ Foto di carlini possono essere inviate esclusivamente in chat privata, in seguito al Disegno di Legge Intergalattico n. 5116."
|
||||
|
||||
|
||||
# Dice roller
|
||||
class ROLL:
|
||||
SUCCESS = "🎲 {result}"
|
||||
|
||||
SYMBOLS = {
|
||||
dice.elements.Div: "/",
|
||||
dice.elements.Mul: "*",
|
||||
dice.elements.Sub: "-",
|
||||
dice.elements.Add: "+",
|
||||
dice.elements.Modulo: "%",
|
||||
dice.elements.AddEvenSubOdd: "+-",
|
||||
dice.elements.Highest: "h",
|
||||
dice.elements.Lowest: "l",
|
||||
dice.elements.Middle: "m",
|
||||
dice.elements.Again: "a",
|
||||
dice.elements.Successes: "e",
|
||||
dice.elements.SuccessFail: "f",
|
||||
dice.elements.ArrayAdd: ".+",
|
||||
dice.elements.ArraySub: ".-",
|
||||
dice.elements.Array: ",",
|
||||
dice.elements.Extend: "|",
|
||||
dice.elements.Reroll: "r",
|
||||
dice.elements.Explode: "x",
|
||||
dice.elements.ForceReroll: "rr"
|
||||
}
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Sintassi del tiro di dadi non valida."
|
||||
DICE_ERROR = "⚠ Il tiro di dadi è fallito."
|
||||
|
||||
|
||||
# Ship creator
|
||||
class SHIP:
|
||||
RESULT = "💕 {one} + {two} = <b>{result}</b>"
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato correttamente i due nomi!\nSintassi: <code>/ship (nome) (nome)</code>"
|
||||
INVALID_NAMES = "⚠ I nomi specificati non sono validi.\nRiprova con dei nomi diversi!"
|
||||
|
||||
|
||||
# Get information about a spell
|
||||
class SPELL:
|
||||
HEADER = "🔍 La magia <b>{name}</b> ha le seguenti proprietà (v{version}):\n"
|
||||
ACCURACY = "Precisione - <b>{accuracy}%</b>\n"
|
||||
DAMAGE = "Danni - <b>{number}d{type}{constant}</b> <i>(in media {avg})</i>\n"
|
||||
TYPE = "Tipo - <b>{type}</b>\n"
|
||||
REPEAT = "Multiattacco - <b>×{repeat}</b>\n"
|
||||
HEALING = "Cura - <b>{number}d{type}{constant}</b> <i>(in media {avg})</i>\n"
|
||||
STAT = "Attrib. - <b>{name}{change}</b>\n"
|
||||
STATUS_EFFECT = "Infligge - <b>{effect}</b> (<b>{chance}%</b> di probabilità)"
|
||||
NOTHING = "<i>Chi la usa sguazza nell'acqua, senza ottenere alcun effetto.</i>"
|
||||
|
||||
class ERRORS:
|
||||
INVALID_SYNTAX = "⚠ Non hai specificato la magia di cui vuoi conoscere i dettagli!\nSintassi: <code>/spell (nome)</code>"
|
||||
|
||||
|
||||
# Game stats updates
|
||||
class STATSUPDATE:
|
||||
class BRAWLHALLA:
|
||||
SOLO = "✳️ {username} ha ora <b>{rating}</b> ({delta}) Elo 1v1 su Brawlhalla!"
|
||||
TEAM = "✳️ {username}+{other} hanno ora <b>{rating}</b> Elo 2v2 su Brawlhalla!"
|
||||
|
||||
|
||||
# Secondo me, è colpa delle stringhe.
|
||||
SMECDS = "🤔 Secondo me, è colpa {ds}."
|
||||
|
||||
|
||||
# Wiki notifications
|
||||
class WIKI:
|
||||
PAGE_LOCKED = '🔒 La pagina wiki <a href="https://ryg.steffo.eu/wiki/{key}">{key}</a> è stata bloccata da <b>{user}</b>.'
|
||||
PAGE_UNLOCKED = '🔓 La pagina wiki <a href="https://ryg.steffo.eu/wiki/{key}">{key}</a> è stata sbloccata da <b>{user}</b>.'
|
||||
PAGE_UPDATED = '📖 La pagina wiki <a href="https://ryg.steffo.eu/wiki/{key}">{key}</a> è stata modificata da <b>{user}</b>.\n{reason} [{change}]'
|
718
telegrambot.py
|
@ -2,30 +2,40 @@ import datetime
|
|||
import random
|
||||
import typing
|
||||
import db
|
||||
import errors
|
||||
import stagismo
|
||||
from utils import smecds, cast, errors, emojify, reply_msg
|
||||
# python-telegram-bot has a different name
|
||||
# noinspection PyPackageRequirements
|
||||
from telegram import Bot, Update, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
import telegram
|
||||
# noinspection PyPackageRequirements
|
||||
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler
|
||||
# noinspection PyPackageRequirements
|
||||
from telegram.error import TimedOut, Unauthorized, BadRequest, TelegramError
|
||||
import dice
|
||||
import sys
|
||||
import os
|
||||
import cast
|
||||
import re
|
||||
import logging
|
||||
import configparser
|
||||
import markovify
|
||||
import raven
|
||||
import coloredlogs
|
||||
import strings
|
||||
import time
|
||||
import requests
|
||||
IKMarkup = telegram.InlineKeyboardMarkup
|
||||
IKButton = telegram.InlineKeyboardButton
|
||||
|
||||
# Markov model
|
||||
# Markov models
|
||||
try:
|
||||
with open("markovmodel.json") as file:
|
||||
model = markovify.Text.from_json(file.read())
|
||||
with open("markovmodels/default.json") as file:
|
||||
default_model = markovify.Text.from_json(file.read())
|
||||
except Exception:
|
||||
model = None
|
||||
default_model = None
|
||||
try:
|
||||
with open("markovmodels/dnd4.json") as file:
|
||||
dnd4_model = markovify.Text.from_json(file.read())
|
||||
except Exception:
|
||||
dnd4_model = None
|
||||
|
||||
logging.getLogger().disabled = True
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -35,6 +45,7 @@ coloredlogs.install(level="DEBUG", logger=logger)
|
|||
# Init the config reader
|
||||
config = configparser.ConfigParser()
|
||||
config.read("config.ini")
|
||||
main_group_id = int(config["Telegram"]["main_group"])
|
||||
|
||||
discord_connection = None
|
||||
|
||||
|
@ -45,26 +56,39 @@ sentry = raven.Client(config["Sentry"]["token"],
|
|||
hook_libraries=[])
|
||||
|
||||
|
||||
def catch_and_report(func: "function"):
|
||||
def new_func(bot: Bot, update: Update):
|
||||
def reply(bot: telegram.Bot, update: telegram.Update, string: str, ignore_escaping=False, disable_web_page_preview=True, **kwargs) -> telegram.Message:
|
||||
while True:
|
||||
try:
|
||||
return reply_msg(bot, update.message.chat.id, string, ignore_escaping=ignore_escaping, disable_web_page_preview=disable_web_page_preview, **kwargs)
|
||||
except Unauthorized:
|
||||
if update.message.chat.type == telegram.Chat.PRIVATE:
|
||||
return reply_msg(bot, main_group_id, strings.TELEGRAM.ERRORS.UNAUTHORIZED_USER,
|
||||
mention=update.message.from_user.mention_html())
|
||||
else:
|
||||
return reply_msg(bot, main_group_id, strings.TELEGRAM.ERRORS.UNAUTHORIZED_GROUP,
|
||||
group=(update.message.chat.title or update.message.chat.id))
|
||||
except TimedOut:
|
||||
time.sleep(1)
|
||||
pass
|
||||
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def command(func: "function"):
|
||||
def new_func(bot: telegram.Bot, update: telegram.Update):
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
bot.send_chat_action(update.message.chat.id, telegram.ChatAction.TYPING)
|
||||
return func(bot, update)
|
||||
except TimedOut:
|
||||
logger.warning(f"Telegram timed out in {update}")
|
||||
except Exception:
|
||||
logger.error(f"Critical error: {sys.exc_info()}")
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
bot.send_message(int(config["Telegram"]["main_group"]),
|
||||
"☢ **ERRORE CRITICO!** \n"
|
||||
f"Il bot ha ignorato il comando.\n"
|
||||
f"Una segnalazione di errore è stata automaticamente mandata a @Steffo.\n\n"
|
||||
f"Dettagli dell'errore:\n"
|
||||
f"```\n"
|
||||
f"{sys.exc_info()}\n"
|
||||
f"```", parse_mode="Markdown")
|
||||
reply_msg(bot, main_group_id, strings.TELEGRAM.ERRORS.CRITICAL_ERROR,
|
||||
exc_info=repr(sys.exc_info()))
|
||||
except Exception:
|
||||
logger.error(f"Double critical error: {sys.exc_info()}")
|
||||
if not __debug__:
|
||||
sentry.user_context({
|
||||
"id": update.effective_user.id,
|
||||
"telegram": {
|
||||
|
@ -80,40 +104,58 @@ def catch_and_report(func: "function"):
|
|||
return new_func
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_ping(bot: Bot, update: Update):
|
||||
bot.send_message(update.message.chat.id, "🏓 Pong!")
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_register(bot: Bot, update: Update):
|
||||
# noinspection PyUnresolvedReferences
|
||||
def database_access(func: "function"):
|
||||
def new_func(bot: telegram.Bot, update: telegram.Update):
|
||||
try:
|
||||
session = db.Session()
|
||||
return func(bot, update, session)
|
||||
except Exception:
|
||||
logger.error(f"Database error: {sys.exc_info()}")
|
||||
sentry.captureException()
|
||||
finally:
|
||||
try:
|
||||
session.close()
|
||||
except Exception:
|
||||
pass
|
||||
return new_func
|
||||
|
||||
|
||||
@command
|
||||
def cmd_ping(bot: telegram.Bot, update: telegram.Update):
|
||||
reply(bot, update, strings.PONG)
|
||||
|
||||
|
||||
@command
|
||||
@database_access
|
||||
def cmd_link(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
try:
|
||||
username = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
bot.send_message(update.message.chat.id, "⚠️ Non hai specificato un username!")
|
||||
reply(bot, update, strings.LINK.ERRORS.INVALID_SYNTAX)
|
||||
session.close()
|
||||
return
|
||||
try:
|
||||
t = db.Telegram.create(session,
|
||||
royal_username=username,
|
||||
telegram_user=update.message.from_user)
|
||||
except errors.NotFoundError:
|
||||
reply(bot, update, strings.LINK.ERRORS.NOT_FOUND)
|
||||
session.close()
|
||||
return
|
||||
except errors.AlreadyExistingError:
|
||||
bot.send_message(update.message.chat.id, "⚠ Il tuo account Telegram è già collegato a un account RYG o"
|
||||
" l'account RYG che hai specificato è già collegato a un account"
|
||||
" Telegram.")
|
||||
reply(bot, update, strings.LINK.ERRORS.ALREADY_EXISTING)
|
||||
session.close()
|
||||
return
|
||||
session.add(t)
|
||||
session.commit()
|
||||
bot.send_message(update.message.chat.id, "✅ Sincronizzazione completata!")
|
||||
session.close()
|
||||
reply(bot, update, strings.LINK.SUCCESS)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_discord(bot: Bot, update: Update):
|
||||
@command
|
||||
def cmd_cv(bot: telegram.Bot, update: telegram.Update):
|
||||
if discord_connection is None:
|
||||
bot.send_message(update.message.chat.id, "⚠ Il bot non è collegato a Discord al momento.")
|
||||
reply(bot, update, strings.BRIDGE.ERRORS.INACTIVE_BRIDGE)
|
||||
return
|
||||
# dirty hack as usual
|
||||
if update.message.text.endswith("full"):
|
||||
|
@ -121,70 +163,49 @@ def cmd_discord(bot: Bot, update: Update):
|
|||
else:
|
||||
discord_connection.send("get cv")
|
||||
message = discord_connection.recv()
|
||||
bot.send_message(update.message.chat.id, message, disable_web_page_preview=True, parse_mode="HTML")
|
||||
reply(bot, update, message)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_cast(bot: Bot, update: Update):
|
||||
try:
|
||||
spell: str = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
bot.send_message(update.message.chat.id, "⚠️ Non hai specificato nessun incantesimo!\n"
|
||||
"Sintassi corretta: `/cast <nome_incantesimo>`", parse_mode="Markdown")
|
||||
return
|
||||
# Open a new db session
|
||||
session = db.Session()
|
||||
# Find a target for the spell
|
||||
target = random.sample(session.query(db.Telegram).all(), 1)[0]
|
||||
# Close the session
|
||||
session.close()
|
||||
# END
|
||||
bot.send_message(update.message.chat.id, cast.cast(spell_name=spell,
|
||||
target_name=target.username if target.username is not None
|
||||
else target.first_name, platform="telegram"),
|
||||
parse_mode="HTML")
|
||||
@command
|
||||
def cmd_cast(bot: telegram.Bot, update: telegram.Update):
|
||||
reply(bot, update, strings.CAST.ERRORS.NOT_YET_AVAILABLE)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_color(bot: Bot, update: Update):
|
||||
bot.send_message(update.message.chat.id, "I am sorry, unknown error occured during working with your request,"
|
||||
" Admin were notified")
|
||||
@command
|
||||
def cmd_color(bot: telegram.Bot, update: telegram.Update):
|
||||
reply(bot, update, strings.COLOR)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_smecds(bot: Bot, update: Update):
|
||||
ds = random.sample(stagismo.listona, 1)[0]
|
||||
bot.send_message(update.message.chat.id, f"Secondo me, è colpa {ds}.")
|
||||
@command
|
||||
def cmd_smecds(bot: telegram.Bot, update: telegram.Update):
|
||||
ds = random.sample(smecds, 1)[0]
|
||||
reply(bot, update, strings.SMECDS, ds=ds)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_ciaoruozi(bot: Bot, update: Update):
|
||||
@command
|
||||
def cmd_ciaoruozi(bot: telegram.Bot, update: telegram.Update):
|
||||
if update.message.from_user.username.lstrip("@") == "MeStakes":
|
||||
bot.send_message(update.message.chat.id, "Ciao me!")
|
||||
reply(bot, update, strings.CIAORUOZI.THE_LEGEND_HIMSELF)
|
||||
else:
|
||||
bot.send_message(update.message.chat.id, "Ciao Ruozi!")
|
||||
reply(bot, update, strings.CIAORUOZI.SOMEBODY_ELSE)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_ahnonlosoio(bot: Bot, update: Update):
|
||||
@command
|
||||
def cmd_ahnonlosoio(bot: telegram.Bot, update: telegram.Update):
|
||||
if update.message.reply_to_message is not None and update.message.reply_to_message.text in [
|
||||
"/ahnonlosoio", "/ahnonlosoio@royalgamesbot", "Ah, non lo so io!", "Ah, non lo so neppure io!"
|
||||
"/ahnonlosoio", "/ahnonlosoio@royalgamesbot", strings.AHNONLOSOIO.ONCE, strings.AHNONLOSOIO.AGAIN
|
||||
]:
|
||||
bot.send_message(update.message.chat.id, "Ah, non lo so neppure io!")
|
||||
reply(bot, update, strings.AHNONLOSOIO.AGAIN)
|
||||
else:
|
||||
bot.send_message(update.message.chat.id, "Ah, non lo so io!")
|
||||
reply(bot, update, strings.AHNONLOSOIO.ONCE)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_balurage(bot: Bot, update: Update):
|
||||
session = db.Session()
|
||||
try:
|
||||
@command
|
||||
@database_access
|
||||
def cmd_balurage(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
if user is None:
|
||||
bot.send_message(update.message.chat.id,
|
||||
"⚠ Il tuo account Telegram non è registrato al RYGdb!\n\n"
|
||||
"Registrati con `/register@royalgamesbot <nomeutenteryg>`.",
|
||||
parse_mode="Markdown")
|
||||
reply(bot, update, strings.LINK.ERRORS.ROYALNET_NOT_LINKED)
|
||||
return
|
||||
try:
|
||||
reason = update.message.text.split(" ", 1)[1]
|
||||
|
@ -194,62 +215,64 @@ def cmd_balurage(bot: Bot, update: Update):
|
|||
session.add(br)
|
||||
session.commit()
|
||||
bot.send_message(update.message.chat.id, f"😡 Stai sfogando la tua ira sul bot!")
|
||||
except Exception:
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_diario(bot: Bot, update: Update):
|
||||
session = db.Session()
|
||||
try:
|
||||
def parse_diario(session: db.Session, text: str):
|
||||
match = re.match(r'"?([^"]+)"? (?:—|-{1,2}) ?@?([A-Za-z0-9_]+)$', text)
|
||||
if match is None:
|
||||
return None, text
|
||||
text_string = match.group(1)
|
||||
author_string = match.group(2).lower()
|
||||
royal = session.query(db.Royal).filter(db.func.lower(db.Royal.username) == author_string).first()
|
||||
if royal is not None:
|
||||
author = royal.telegram[0]
|
||||
return author, text_string
|
||||
author = session.query(db.Telegram).filter(db.func.lower(db.Telegram.username) == author_string).first()
|
||||
if author is not None:
|
||||
return author, text_string
|
||||
return None, text_string
|
||||
|
||||
|
||||
@command
|
||||
@database_access
|
||||
def cmd_diario(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
if user is None:
|
||||
bot.send_message(update.message.chat.id, "⚠ Il tuo account Telegram non è registrato al RYGdb!"
|
||||
" Registrati con `/register@royalgamesbot <nomeutenteryg>`.",
|
||||
parse_mode="Markdown")
|
||||
reply(bot, update, strings.LINK.ERRORS.ROYALNET_NOT_LINKED)
|
||||
return
|
||||
try:
|
||||
text = update.message.text.split(" ", 1)[1]
|
||||
author = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
saver = author
|
||||
saver = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
author, actual_text = parse_diario(session, text)
|
||||
except IndexError:
|
||||
if update.message.reply_to_message is None:
|
||||
bot.send_message(update.message.chat.id,
|
||||
f"⚠ Non hai specificato cosa aggiungere al diario!\n\n"
|
||||
f"Puoi rispondere `/diario@royalgamesbot` al messaggio che vuoi salvare nel diario"
|
||||
f" oppure scrivere `/diario@royalgamesbot <messaggio>`"
|
||||
f" per aggiungere quel messaggio nel diario.",
|
||||
parse_mode="Markdown")
|
||||
reply(bot, update, strings.DIARIO.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
text = update.message.reply_to_message.text
|
||||
if update.message.forward_from:
|
||||
author = session.query(db.Telegram) \
|
||||
.filter_by(telegram_id=update.message.forward_from.id) \
|
||||
.one_or_none()
|
||||
else:
|
||||
author = session.query(db.Telegram)\
|
||||
.filter_by(telegram_id=update.message.reply_to_message.from_user.id)\
|
||||
.one_or_none()
|
||||
saver = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
if text is None:
|
||||
bot.send_message(update.message.chat.id, f"⚠ Il messaggio a cui hai risposto non contiene testo.")
|
||||
reply(bot, update, strings.DIARIO.ERRORS.NO_TEXT)
|
||||
return
|
||||
diario = db.Diario(timestamp=datetime.datetime.now(),
|
||||
saver=saver,
|
||||
author=author,
|
||||
text=text)
|
||||
text=actual_text)
|
||||
session.add(diario)
|
||||
session.commit()
|
||||
bot.send_message(update.message.chat.id,
|
||||
f"✅ Riga [#{diario.id}](https://ryg.steffo.eu/diario#entry-{diario.id}) aggiunta al diario!",
|
||||
parse_mode="Markdown", disable_web_page_preview=True)
|
||||
except Exception:
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
reply(bot, update, strings.DIARIO.SUCCESS, ignore_escaping=True, diario=diario.to_telegram())
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_vote(bot: Bot, update: Update):
|
||||
session = db.Session()
|
||||
try:
|
||||
@command
|
||||
@database_access
|
||||
def cmd_vote(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
if user is None:
|
||||
bot.send_message(update.message.chat.id,
|
||||
|
@ -274,41 +297,115 @@ def cmd_vote(bot: Bot, update: Update):
|
|||
return
|
||||
session.add(vote)
|
||||
session.flush()
|
||||
inline_keyboard = InlineKeyboardMarkup([[InlineKeyboardButton("🔵 Sì", callback_data="vote_yes")],
|
||||
[InlineKeyboardButton("🔴 No", callback_data="vote_no")],
|
||||
[InlineKeyboardButton("⚫️ Astieniti", callback_data="vote_abstain")]])
|
||||
inline_keyboard = IKMarkup([[IKButton("🔵 Sì", callback_data="vote_yes")],
|
||||
[IKButton("🔴 No", callback_data="vote_no")],
|
||||
[IKButton("⚫️ Astieniti", callback_data="vote_abstain")]])
|
||||
message = bot.send_message(update.message.chat.id, vote.generate_text(session=session),
|
||||
reply_markup=inline_keyboard,
|
||||
parse_mode="HTML")
|
||||
vote.message_id = message.message_id
|
||||
session.commit()
|
||||
except Exception:
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def on_callback_query(bot: Bot, update: Update):
|
||||
def generate_search_message(term, entries):
|
||||
msg = strings.DIARIOSEARCH.HEADER.format(term=term)
|
||||
if len(entries) < 100:
|
||||
for entry in entries[:5]:
|
||||
msg += f'<a href="https://ryg.steffo.eu/diario#entry-{entry.id}">#{entry.id}</a> di <i>{entry.author or "Anonimo"}</i>\n{entry.text}\n\n'
|
||||
if len(entries) > 5:
|
||||
msg += "I termini comapiono anche nelle righe:\n"
|
||||
for entry in entries[5:]:
|
||||
msg += f'<a href="https://ryg.steffo.eu/diario#entry-{entry.id}">#{entry.id}</a> '
|
||||
else:
|
||||
for entry in entries[:100]:
|
||||
msg += f'<a href="https://ryg.steffo.eu/diario#entry-{entry.id}">#{entry.id}</a> '
|
||||
for entry in entries[100:]:
|
||||
msg += f"#{entry.id} "
|
||||
return msg
|
||||
|
||||
|
||||
@command
|
||||
@database_access
|
||||
def cmd_search(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
try:
|
||||
query = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
reply(bot, update, strings.DIARIOSEARCH.ERRORS.INVALID_SYNTAX, command="search")
|
||||
return
|
||||
query = query.replace('%', '\\%').replace('_', '\\_')
|
||||
entries = session.query(db.Diario)\
|
||||
.filter(db.Diario.text.op("~*")(r"(?:[\s\.,:;!?\"'<{([]+|^)"
|
||||
+ query +
|
||||
r"(?:[\s\.,:;!?\"'>\})\]]+|$)"))\
|
||||
.order_by(db.Diario.id.desc())\
|
||||
.all()
|
||||
bot.send_message(update.message.chat.id, generate_search_message(f"<b>{query}</b>", entries), parse_mode="HTML")
|
||||
|
||||
|
||||
@command
|
||||
@database_access
|
||||
def cmd_regex(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
try:
|
||||
query = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
reply(bot, update, strings.DIARIOSEARCH.ERRORS.INVALID_SYNTAX, command="regex")
|
||||
return
|
||||
query = query.replace('%', '\\%').replace('_', '\\_')
|
||||
entries = session.query(db.Diario).filter(db.Diario.text.op("~*")(query)).order_by(db.Diario.id.desc()).all()
|
||||
try:
|
||||
bot.send_message(update.message.chat.id, generate_search_message(f"<code>{query}</code>", entries), parse_mode="HTML")
|
||||
except (BadRequest, TelegramError):
|
||||
reply(bot, update, strings.DIARIOSEARCH.ERRORS.RESULTS_TOO_LONG)
|
||||
|
||||
|
||||
@command
|
||||
@database_access
|
||||
def cmd_mm(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).one_or_none()
|
||||
if user is None:
|
||||
reply(bot, update, strings.LINK.ERRORS.ROYALNET_NOT_LINKED)
|
||||
return
|
||||
match = re.match(r"/(?:mm|matchmaking)(?:@royalgamesbot)?(?: (?:([0-9]+)-)?([0-9]+))? (?:per )?([A-Za-z0-9!\-_. ]+)(?:.*\n(.+))?",
|
||||
update.message.text)
|
||||
if match is None:
|
||||
reply(bot, update, strings.MATCHMAKING.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
min_players, max_players, match_name, match_desc = match.group(1, 2, 3, 4)
|
||||
db_match = db.Match(timestamp=datetime.datetime.now(),
|
||||
match_title=match_name,
|
||||
match_desc=match_desc,
|
||||
min_players=min_players,
|
||||
max_players=max_players,
|
||||
creator=user)
|
||||
session.add(db_match)
|
||||
session.flush()
|
||||
inline_keyboard = IKMarkup([([IKButton(strings.MATCHMAKING.BUTTONS[key], callback_data=key)]) for key in strings.MATCHMAKING.BUTTONS])
|
||||
message = bot.send_message(config["Telegram"]["announcement_group"], db_match.generate_text(session=session),
|
||||
parse_mode="HTML",
|
||||
reply_markup=inline_keyboard)
|
||||
db_match.message_id = message.message_id
|
||||
session.commit()
|
||||
|
||||
|
||||
def on_callback_query(bot: telegram.Bot, update: telegram.Update):
|
||||
try:
|
||||
session = db.Session()
|
||||
if update.callback_query.data.startswith("vote_"):
|
||||
if update.callback_query.data == "vote_yes":
|
||||
choice = db.VoteChoices.YES
|
||||
status = db.VoteChoices.YES
|
||||
emoji = "🔵"
|
||||
elif update.callback_query.data == "vote_no":
|
||||
choice = db.VoteChoices.NO
|
||||
status = db.VoteChoices.NO
|
||||
emoji = "🔴"
|
||||
elif update.callback_query.data == "vote_abstain":
|
||||
choice = db.VoteChoices.ABSTAIN
|
||||
status = db.VoteChoices.ABSTAIN
|
||||
emoji = "⚫️"
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
if update.callback_query.data.startswith("vote_"):
|
||||
session = db.Session()
|
||||
try:
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.callback_query.from_user.id).one_or_none()
|
||||
if user is None:
|
||||
bot.answer_callback_query(update.callback_query.id, show_alert=True,
|
||||
text="⚠ Il tuo account Telegram non è registrato al RYGdb!"
|
||||
" Registrati con `/register@royalgamesbot <nomeutenteryg>`.",
|
||||
text=strings.LINK.ERRORS.ROYALNET_NOT_LINKED,
|
||||
parse_mode="Markdown")
|
||||
return
|
||||
question = session.query(db.VoteQuestion)\
|
||||
|
@ -316,106 +413,177 @@ def on_callback_query(bot: Bot, update: Update):
|
|||
.one()
|
||||
answer = session.query(db.VoteAnswer).filter_by(question=question, user=user).one_or_none()
|
||||
if answer is None:
|
||||
answer = db.VoteAnswer(question=question, choice=choice, user=user)
|
||||
answer = db.VoteAnswer(question=question, choice=status, user=user)
|
||||
session.add(answer)
|
||||
bot.answer_callback_query(update.callback_query.id, text=f"Hai votato {emoji}.", cache_time=1)
|
||||
elif answer.choice == choice:
|
||||
elif answer.choice == status:
|
||||
session.delete(answer)
|
||||
bot.answer_callback_query(update.callback_query.id, text=f"Hai ritratto il tuo voto.", cache_time=1)
|
||||
else:
|
||||
answer.choice = choice
|
||||
answer.choice = status
|
||||
bot.answer_callback_query(update.callback_query.id, text=f"Hai cambiato il tuo voto in {emoji}.",
|
||||
cache_time=1)
|
||||
session.commit()
|
||||
inline_keyboard = InlineKeyboardMarkup([[InlineKeyboardButton("🔵 Sì",
|
||||
callback_data="vote_yes")],
|
||||
[InlineKeyboardButton("🔴 No",
|
||||
callback_data="vote_no")],
|
||||
[InlineKeyboardButton("⚫️ Astieniti",
|
||||
callback_data="vote_abstain")]])
|
||||
inline_keyboard = IKMarkup([[IKButton("🔵 Sì", callback_data="vote_yes")],
|
||||
[IKButton("🔴 No", callback_data="vote_no")],
|
||||
[IKButton("⚫️ Astieniti", callback_data="vote_abstain")]])
|
||||
bot.edit_message_text(message_id=update.callback_query.message.message_id,
|
||||
chat_id=update.callback_query.message.chat.id,
|
||||
text=question.generate_text(session),
|
||||
reply_markup=inline_keyboard,
|
||||
parse_mode="HTML")
|
||||
elif update.callback_query.data.startswith("match_"):
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.callback_query.from_user.id).one_or_none()
|
||||
if user is None:
|
||||
bot.answer_callback_query(update.callback_query.id,
|
||||
show_alert=True,
|
||||
text=strings.LINK.ERRORS.ROYALNET_NOT_LINKED,
|
||||
parse_mode="Markdown")
|
||||
return
|
||||
match = session.query(db.Match).filter_by(message_id=update.callback_query.message.message_id).one()
|
||||
if update.callback_query.data == "match_close":
|
||||
if not (match.creator == user or user.telegram_id == 25167391):
|
||||
bot.answer_callback_query(update.callback_query.id,
|
||||
show_alert=True,
|
||||
text=strings.MATCHMAKING.ERRORS.NOT_ADMIN)
|
||||
return
|
||||
match.closed = True
|
||||
for partecipation in match.players:
|
||||
if int(partecipation.status) >= 1:
|
||||
try:
|
||||
reply_msg(bot, partecipation.user.telegram_id, strings.MATCHMAKING.GAME_START[int(partecipation.status)], **match.format_dict())
|
||||
except Unauthorized:
|
||||
reply_msg(bot, main_group_id, strings.TELEGRAM.ERRORS.UNAUTHORIZED_USER,
|
||||
mention=partecipation.user.mention())
|
||||
elif update.callback_query.data == "match_cancel":
|
||||
if not (match.creator == user or user.telegram_id == 25167391):
|
||||
bot.answer_callback_query(update.callback_query.id,
|
||||
show_alert=True,
|
||||
text=strings.MATCHMAKING.ERRORS.NOT_ADMIN)
|
||||
return
|
||||
match.closed = True
|
||||
status = {
|
||||
"match_ready": db.MatchmakingStatus.READY,
|
||||
"match_wait_for_me": db.MatchmakingStatus.WAIT_FOR_ME,
|
||||
"match_maybe": db.MatchmakingStatus.MAYBE,
|
||||
"match_ignore": db.MatchmakingStatus.IGNORED,
|
||||
"match_close": None,
|
||||
"match_cancel": None,
|
||||
}.get(update.callback_query.data)
|
||||
if status:
|
||||
if match.closed:
|
||||
bot.answer_callback_query(update.callback_query.id,
|
||||
show_alert=True,
|
||||
text=strings.MATCHMAKING.ERRORS.MATCH_CLOSED)
|
||||
return
|
||||
partecipation = session.query(db.MatchPartecipation).filter_by(match=match, user=user).one_or_none()
|
||||
if partecipation is None:
|
||||
partecipation = db.MatchPartecipation(match=match, status=status.value, user=user)
|
||||
session.add(partecipation)
|
||||
else:
|
||||
partecipation.status = status.value
|
||||
session.commit()
|
||||
bot.answer_callback_query(update.callback_query.id,
|
||||
text=strings.MATCHMAKING.TICKER_TEXT[update.callback_query.data],
|
||||
cache_time=1)
|
||||
if not match.closed:
|
||||
inline_keyboard = IKMarkup([([IKButton(strings.MATCHMAKING.BUTTONS[key], callback_data=key)]) for key in strings.MATCHMAKING.BUTTONS])
|
||||
else:
|
||||
inline_keyboard = None
|
||||
while True:
|
||||
try:
|
||||
bot.edit_message_text(message_id=update.callback_query.message.message_id,
|
||||
chat_id=config["Telegram"]["announcement_group"],
|
||||
text=match.generate_text(session),
|
||||
reply_markup=inline_keyboard,
|
||||
parse_mode="HTML")
|
||||
break
|
||||
except BadRequest:
|
||||
break
|
||||
except TimedOut:
|
||||
time.sleep(1)
|
||||
except Exception:
|
||||
raise
|
||||
try:
|
||||
bot.answer_callback_query(update.callback_query.id,
|
||||
show_alert=True,
|
||||
text=strings.TELEGRAM.ERRORS.CRITICAL_ERROR_QUERY)
|
||||
except Exception:
|
||||
pass
|
||||
logger.error(f"Critical error: {sys.exc_info()}")
|
||||
sentry.user_context({
|
||||
"id": update.effective_user.id,
|
||||
"telegram": {
|
||||
"username": update.effective_user.username,
|
||||
"first_name": update.effective_user.first_name,
|
||||
"last_name": update.effective_user.last_name
|
||||
}
|
||||
})
|
||||
sentry.extra_context({
|
||||
"update": update.to_dict()
|
||||
})
|
||||
sentry.captureException()
|
||||
finally:
|
||||
try:
|
||||
# noinspection PyUnboundLocalVariable
|
||||
session.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_eat(bot: Bot, update: Update):
|
||||
@command
|
||||
def cmd_eat(bot: telegram.Bot, update: telegram.Update):
|
||||
try:
|
||||
food: str = update.message.text.split(" ", 1)[1].capitalize()
|
||||
except IndexError:
|
||||
bot.send_message(update.message.chat.id, "⚠️ Non hai specificato cosa mangiare!\n"
|
||||
"Sintassi corretta: `/eat <cibo>`", parse_mode="Markdown")
|
||||
reply(bot, update, strings.EAT.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
if "tonnuooooooro" in food.lower():
|
||||
bot.send_message(update.message.chat.id, "👻 Il pesce che hai mangiato era posseduto.\n"
|
||||
"Spooky!")
|
||||
return
|
||||
bot.send_message(update.message.chat.id, f"🍗 Hai mangiato {food}!")
|
||||
reply(bot, update, strings.EAT.FOODS.get(food.lower(), strings.EAT.FOODS["_default"]), food=food)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_ship(bot: Bot, update: Update):
|
||||
@command
|
||||
def cmd_ship(bot: telegram.Bot, update: telegram.Update):
|
||||
try:
|
||||
_, name_one, name_two = update.message.text.split(" ", 2)
|
||||
names = update.message.text.split(" ")
|
||||
name_one = names[1]
|
||||
name_two = names[2]
|
||||
except ValueError:
|
||||
bot.send_message(update.message.chat.id, "⚠️ Non hai specificato correttamente i due nomi!\n"
|
||||
"Sintassi corretta: `/ship <nome> <nome>`", parse_mode="Markdown")
|
||||
reply(bot, update, strings.SHIP.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
name_one = name_one.lower()
|
||||
name_two = name_two.lower()
|
||||
part_one = re.search(r"^[A-Za-z][^aeiouAEIOU]*[aeiouAEIOU]?", name_one)
|
||||
part_two = re.search(r"[^aeiouAEIOU]*[aeiouAEIOU]?[A-Za-z]$", name_two)
|
||||
try:
|
||||
mixed = part_one.group(0) + part_two.group(0)
|
||||
except Exception:
|
||||
bot.send_message(update.message.chat.id, "⚠ I nomi specificati non sono validi.\n"
|
||||
"Riprova con dei nomi diversi!")
|
||||
match_one = re.search(r"^[A-Za-z][^aeiouAEIOU]*[aeiouAEIOU]?", name_one)
|
||||
if match_one is None:
|
||||
part_one = name_one[:int(len(name_one) / 2)]
|
||||
else:
|
||||
part_one = match_one.group(0)
|
||||
match_two = re.search(r"[^aeiouAEIOU]*[aeiouAEIOU]?[A-Za-z]$", name_two)
|
||||
if match_two is None:
|
||||
part_two = name_two[int(len(name_two) / 2):]
|
||||
else:
|
||||
part_two = match_two.group(0)
|
||||
mixed = part_one + part_two # TODO: find out what exceptions this could possibly raise
|
||||
reply(bot, update, strings.SHIP.RESULT,
|
||||
one=name_one.capitalize(),
|
||||
two=name_two.capitalize(),
|
||||
result=mixed.capitalize())
|
||||
|
||||
|
||||
@command
|
||||
def cmd_bridge(bot: telegram.Bot, update: telegram.Update):
|
||||
if discord_connection is None:
|
||||
reply(bot, update, strings.BRIDGE.ERRORS.INACTIVE_BRIDGE)
|
||||
return
|
||||
if part_one is None or part_two is None:
|
||||
bot.send_message(update.message.chat.id, "⚠ I nomi specificati non sono validi.\n"
|
||||
"Riprova con dei nomi diversi!")
|
||||
return
|
||||
bot.send_message(update.message.chat.id, f"💕 {name_one.capitalize()} + {name_two.capitalize()} ="
|
||||
f" {mixed.capitalize()}")
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_profile(bot: Bot, update: Update):
|
||||
session = db.Session()
|
||||
user = session.query(db.Telegram).filter_by(telegram_id=update.message.from_user.id).join(db.Royal).one_or_none()
|
||||
session.close()
|
||||
if user is None:
|
||||
bot.send_message(update.message.chat.id, "⚠ Non sei connesso a Royalnet!\n"
|
||||
"Per registrarti, utilizza il comando /register.")
|
||||
return
|
||||
bot.send_message(update.message.chat.id, f"👤 [Profilo di {user.royal.username}]"
|
||||
f"(http://ryg.steffo.eu/profile/{user.royal.username})\n"
|
||||
f"Attualmente, hai **{user.royal.fiorygi}** fiorygi.",
|
||||
parse_mode="Markdown")
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_bridge(bot: Bot, update: Update):
|
||||
try:
|
||||
data = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
bot.send_message(update.message.chat.id,
|
||||
"⚠ Non hai specificato un comando!\n"
|
||||
"Sintassi corretta: `/bridge <comando> <argomenti>`",
|
||||
parse_mode="Markdown")
|
||||
reply(bot, update, strings.BRIDGE.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
discord_connection.send(f"!{data}")
|
||||
result = discord_connection.recv()
|
||||
if result == "error":
|
||||
bot.send_message(update.message.chat.id, "⚠ Il comando specificato non esiste.")
|
||||
reply(bot, update, strings.BRIDGE.FAILURE)
|
||||
if result == "success":
|
||||
bot.send_message(update.message.chat.id, "⏩ Comando eseguito su Discord.")
|
||||
reply(bot, update, strings.BRIDGE.SUCCESS)
|
||||
|
||||
|
||||
def parse_timestring(timestring: str) -> typing.Union[datetime.timedelta, datetime.datetime]:
|
||||
|
@ -466,8 +634,9 @@ def parse_timestring(timestring: str) -> typing.Union[datetime.timedelta, dateti
|
|||
raise ValueError("Nothing was found.")
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_newevent(bot: Bot, update: Update):
|
||||
@command
|
||||
@database_access
|
||||
def cmd_newevent(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
try:
|
||||
_, timestring, name_desc = update.message.text.split(" ", 2)
|
||||
except ValueError:
|
||||
|
@ -499,7 +668,6 @@ def cmd_newevent(bot: Bot, update: Update):
|
|||
"per favore inserisci una data futura.\n", parse_mode="Markdown")
|
||||
return
|
||||
# Create the event
|
||||
session = db.Session()
|
||||
telegram_user = session.query(db.Telegram)\
|
||||
.filter_by(telegram_id=update.message.from_user.id)\
|
||||
.join(db.Royal)\
|
||||
|
@ -516,15 +684,13 @@ def cmd_newevent(bot: Bot, update: Update):
|
|||
# Save the event
|
||||
session.add(event)
|
||||
session.commit()
|
||||
session.close()
|
||||
bot.send_message(update.message.chat.id, "✅ Evento aggiunto al Calendario Royal Games!")
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_calendar(bot: Bot, update: Update):
|
||||
session = db.Session()
|
||||
@command
|
||||
@database_access
|
||||
def cmd_calendar(bot: telegram.Bot, update: telegram.Update, session: db.Session):
|
||||
next_events = session.query(db.Event).filter(db.Event.time > datetime.datetime.now()).order_by(db.Event.time).all()
|
||||
session.close()
|
||||
msg = "📆 Prossimi eventi\n"
|
||||
for event in next_events:
|
||||
if event.time_left.days >= 1:
|
||||
|
@ -537,39 +703,128 @@ def cmd_calendar(bot: Bot, update: Update):
|
|||
bot.send_message(update.message.chat.id, msg, parse_mode="HTML", disable_web_page_preview=True)
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_markov(bot: Bot, update: Update):
|
||||
if model is None:
|
||||
bot.send_message(update.message.chat.id, "⚠️ Il modello Markov non è disponibile.")
|
||||
@command
|
||||
def cmd_markov(bot: telegram.Bot, update: telegram.Update):
|
||||
if default_model is None:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.NO_MODEL)
|
||||
return
|
||||
try:
|
||||
_, first_word = update.message.text.split(" ", 1)
|
||||
except ValueError:
|
||||
sentence = model.make_sentence(tries=1000)
|
||||
first_word = update.message.text.split(" ")[1]
|
||||
except IndexError:
|
||||
# Any word
|
||||
sentence = default_model.make_sentence(tries=1000)
|
||||
if sentence is None:
|
||||
bot.send_message(update.message.chat.id, "⚠ Complimenti! Hai vinto la lotteria di Markov!\n"
|
||||
"O forse l'hai persa.\n"
|
||||
"Non sono riuscito a generare una frase, riprova.")
|
||||
reply(bot, update, strings.MARKOV.ERRORS.GENERATION_FAILED)
|
||||
return
|
||||
bot.send_message(update.message.chat.id, sentence)
|
||||
reply(bot, update, sentence)
|
||||
return
|
||||
# Specific word
|
||||
try:
|
||||
sentence = default_model.make_sentence_with_start(first_word, tries=1000)
|
||||
except KeyError:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.MISSING_WORD)
|
||||
return
|
||||
if sentence is None:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.SPECIFIC_WORD_FAILED)
|
||||
return
|
||||
reply(bot, update, sentence)
|
||||
|
||||
|
||||
@command
|
||||
def cmd_dndmarkov(bot: telegram.Bot, update: telegram.Update):
|
||||
if dnd4_model is None:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.NO_MODEL)
|
||||
return
|
||||
try:
|
||||
first_word = update.message.text.split(" ")[1]
|
||||
except IndexError:
|
||||
# Any word
|
||||
sentence = dnd4_model.make_sentence(tries=1000)
|
||||
if sentence is None:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.GENERATION_FAILED)
|
||||
return
|
||||
reply(bot, update, sentence)
|
||||
return
|
||||
# Specific word
|
||||
try:
|
||||
sentence = dnd4_model.make_sentence_with_start(first_word, tries=1000)
|
||||
except KeyError:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.MISSING_WORD)
|
||||
return
|
||||
if sentence is None:
|
||||
reply(bot, update, strings.MARKOV.ERRORS.SPECIFIC_WORD_FAILED)
|
||||
return
|
||||
reply(bot, update, sentence)
|
||||
|
||||
|
||||
def exec_roll(roll) -> str:
|
||||
result = int(roll.evaluate())
|
||||
string = ""
|
||||
if isinstance(roll, dice.elements.Dice):
|
||||
string += f"<b>{result}</b>"
|
||||
else:
|
||||
sentence = model.make_sentence_with_start(first_word, tries=1000)
|
||||
if sentence is None:
|
||||
bot.send_message(update.message.chat.id, "⚠ Non è stato possibile generare frasi partendo da questa"
|
||||
" parola.")
|
||||
return
|
||||
bot.send_message(update.message.chat.id, sentence)
|
||||
for index, operand in enumerate(roll.original_operands):
|
||||
if operand != roll.operands[index]:
|
||||
string += f"<i>{roll.operands[index]}</i>"
|
||||
else:
|
||||
string += f"{operand}"
|
||||
if index + 1 != len(roll.original_operands):
|
||||
|
||||
string += strings.ROLL.SYMBOLS[roll.__class__]
|
||||
string += f"=<b>{result}</b>"
|
||||
return string
|
||||
|
||||
|
||||
@catch_and_report
|
||||
def cmd_roll(bot: Bot, update: Update):
|
||||
@command
|
||||
def cmd_roll(bot: telegram.Bot, update: telegram.Update):
|
||||
dice_string = update.message.text.split(" ", 1)[1]
|
||||
try:
|
||||
result = dice.roll(f"{dice_string}t")
|
||||
roll = dice.roll(f"{dice_string}", raw=True)
|
||||
except dice.DiceBaseException:
|
||||
bot.send_message(update.message.chat.id, "⚠ Il tiro dei dadi è fallito. Controlla la sintassi!")
|
||||
reply(bot, update, strings.ROLL.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
bot.send_message(update.message.chat.id, f"🎲 {result}")
|
||||
try:
|
||||
result = exec_roll(roll)
|
||||
except dice.DiceFatalException:
|
||||
reply(bot, update, strings.ROLL.ERRORS.DICE_ERROR)
|
||||
return
|
||||
reply(bot, update, strings.ROLL.SUCCESS, result=result, ignore_escaping=True)
|
||||
|
||||
|
||||
@command
|
||||
def cmd_start(bot: telegram.Bot, update: telegram.Update):
|
||||
reply(bot, update, strings.TELEGRAM.BOT_STARTED)
|
||||
|
||||
|
||||
@command
|
||||
def cmd_spell(bot: telegram.Bot, update: telegram.Update):
|
||||
try:
|
||||
spell_name: str = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
reply(bot, update, strings.SPELL.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
spell = cast.Spell(spell_name)
|
||||
reply(bot, update, spell.stringify())
|
||||
|
||||
|
||||
@command
|
||||
def cmd_emojify(bot: telegram.Bot, update: telegram.Update):
|
||||
try:
|
||||
string: str = update.message.text.split(" ", 1)[1]
|
||||
except IndexError:
|
||||
reply(bot, update, strings.EMOJIFY.ERRORS.INVALID_SYNTAX)
|
||||
return
|
||||
msg = emojify(string)
|
||||
reply(bot, update, strings.EMOJIFY.RESPONSE, emojified=msg)
|
||||
|
||||
|
||||
@command
|
||||
def cmd_pug(bot: telegram.Bot, update: telegram.Update):
|
||||
if update.effective_chat.type != telegram.Chat.PRIVATE:
|
||||
reply(bot, update, strings.PUG.ERRORS.PRIVATE_CHAT_ONLY)
|
||||
return
|
||||
j = requests.get("https://dog.ceo/api/breed/pug/images/random").json()
|
||||
reply(bot, update, strings.PUG.HERE_HAVE_A_PUG, disable_web_page_preview=False, image_url=j["message"])
|
||||
|
||||
|
||||
def process(arg_discord_connection):
|
||||
|
@ -580,27 +835,40 @@ def process(arg_discord_connection):
|
|||
u = Updater(config["Telegram"]["bot_token"])
|
||||
logger.info("Registering handlers...")
|
||||
u.dispatcher.add_handler(CommandHandler("ping", cmd_ping))
|
||||
u.dispatcher.add_handler(CommandHandler("register", cmd_register))
|
||||
u.dispatcher.add_handler(CommandHandler("discord", cmd_discord))
|
||||
u.dispatcher.add_handler(CommandHandler("cv", cmd_discord))
|
||||
u.dispatcher.add_handler(CommandHandler("pong", cmd_ping))
|
||||
u.dispatcher.add_handler(CommandHandler("link", cmd_link))
|
||||
u.dispatcher.add_handler(CommandHandler("discord", cmd_cv))
|
||||
u.dispatcher.add_handler(CommandHandler("cv", cmd_cv))
|
||||
u.dispatcher.add_handler(CommandHandler("cast", cmd_cast))
|
||||
u.dispatcher.add_handler(CommandHandler("color", cmd_color))
|
||||
u.dispatcher.add_handler(CommandHandler("error", cmd_color))
|
||||
u.dispatcher.add_handler(CommandHandler("smecds", cmd_smecds))
|
||||
u.dispatcher.add_handler(CommandHandler("ciaoruozi", cmd_ciaoruozi))
|
||||
u.dispatcher.add_handler(CommandHandler("ahnonlosoio", cmd_ahnonlosoio))
|
||||
u.dispatcher.add_handler(CommandHandler("balurage", cmd_balurage))
|
||||
u.dispatcher.add_handler(CommandHandler("diario", cmd_diario))
|
||||
u.dispatcher.add_handler(CommandHandler("spaggia", cmd_diario))
|
||||
u.dispatcher.add_handler(CommandHandler("spaggio", cmd_diario))
|
||||
u.dispatcher.add_handler(CommandHandler("vote", cmd_vote))
|
||||
u.dispatcher.add_handler(CommandHandler("eat", cmd_eat))
|
||||
u.dispatcher.add_handler(CommandHandler("ship", cmd_ship))
|
||||
u.dispatcher.add_handler(CommandHandler("profile", cmd_profile))
|
||||
u.dispatcher.add_handler(CommandHandler("bridge", cmd_bridge))
|
||||
u.dispatcher.add_handler(CommandHandler("newevent", cmd_newevent))
|
||||
u.dispatcher.add_handler(CommandHandler("calendar", cmd_calendar))
|
||||
u.dispatcher.add_handler(CommandHandler("markov", cmd_markov))
|
||||
u.dispatcher.add_handler(CommandHandler("dndmarkov", cmd_dndmarkov))
|
||||
u.dispatcher.add_handler(CommandHandler("roll", cmd_roll))
|
||||
u.dispatcher.add_handler(CommandHandler("r", cmd_roll))
|
||||
u.dispatcher.add_handler(CommandHandler("mm", cmd_mm))
|
||||
u.dispatcher.add_handler(CommandHandler("matchmaking", cmd_mm))
|
||||
u.dispatcher.add_handler(CommandHandler("search", cmd_search))
|
||||
u.dispatcher.add_handler(CommandHandler("regex", cmd_regex))
|
||||
u.dispatcher.add_handler(CommandHandler("start", cmd_start))
|
||||
u.dispatcher.add_handler(CommandHandler("spell", cmd_spell))
|
||||
u.dispatcher.add_handler(CommandHandler("emojify", cmd_emojify))
|
||||
u.dispatcher.add_handler(CommandHandler("pug", cmd_pug))
|
||||
u.dispatcher.add_handler(CommandHandler("carlino", cmd_pug))
|
||||
u.dispatcher.add_handler(CommandHandler("carlini", cmd_pug))
|
||||
u.dispatcher.add_handler(CallbackQueryHandler(on_callback_query))
|
||||
logger.info("Handlers registered.")
|
||||
u.start_polling()
|
||||
|
|
|
@ -11,4 +11,14 @@
|
|||
<p>
|
||||
Il tuo browser ha inviato una richiesta non valida. Magari non hai riempito qualche campo di un form?
|
||||
</p>
|
||||
<blockquote id="entry-966" class="entry ">
|
||||
<div class="left">
|
||||
<p>
|
||||
<span class="text">Villa di Von Shdfisjz</span>
|
||||
</p>
|
||||
<p>
|
||||
<cite>— <a class="author" href="{{ url_for("page_profile", name="Steffo") }}">Steffo</a>, <span class="timestamp">2017-07-26 18:46:43 </span> </cite>
|
||||
</p>
|
||||
</div>
|
||||
</blockquote>
|
||||
{% endblock %}
|
|
@ -9,6 +9,25 @@
|
|||
403 - Forbidden
|
||||
</h1>
|
||||
<p>
|
||||
Non puoi accedere a questa pagina. Magari hai sbagliato password?
|
||||
Non puoi accedere a questa pagina.
|
||||
</p>
|
||||
{% if g.logged_in %}
|
||||
<p>
|
||||
Forse dovresti provare a fare il <a href="{{ url_for("page_login") }}">login</a>...
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
Temo che questa pagina sia riservata agli amministratori...
|
||||
</p>
|
||||
{% endif %}
|
||||
<blockquote class="entry">
|
||||
<div class="left">
|
||||
<p>
|
||||
<span class="text">Io sono il padrone, questo è champagne, buon Natale!</span>
|
||||
</p>
|
||||
<p>
|
||||
<cite>— <span class="author anonymous">Anonimo</span>, <span class="timestamp">2017-02-10 09:11:00</span></cite>
|
||||
</p>
|
||||
</div>
|
||||
</blockquote>
|
||||
{% endblock %}
|
|
@ -11,14 +11,18 @@
|
|||
<p>
|
||||
Il server è crashato mentre cercava di generare questa pagina. Oops.
|
||||
</p>
|
||||
<blockquote>
|
||||
<blockquote class="entry">
|
||||
<div class="left">
|
||||
<p>
|
||||
I am sorry, unknown error occured during working with your request, Admin were notified
|
||||
<span class="text">I am sorry, unknown error occured during working with your request, Admin were notified</span>
|
||||
</p>
|
||||
<p>
|
||||
<cite>— <a class="author" href="https://github.com/ProtoxiDe22/Octeon">OcteonRygBot</a>, <span class="timestamp">2017-09-14 14:11:00</span></cite>
|
||||
</p>
|
||||
</div>
|
||||
</blockquote>
|
||||
<p>
|
||||
L'errore <i>dovrebbe</i> essere stato segnalato a Steffo.
|
||||
Se riesci e ne hai voglia, spiegagli anche cosa ha provocato l'errore.
|
||||
Se riesci e ne hai voglia, spiegagli cosa ha provocato l'errore.
|
||||
</p>
|
||||
<i>@OcteonRygBot, 2017</i>
|
||||
{% endblock %}
|
|
@ -18,7 +18,7 @@
|
|||
<h1>
|
||||
Attività su Discord negli ultimi 7 giorni
|
||||
</h1>
|
||||
<canvas class="graph members-graph-7d" id="discord-members-graph-7d" height="240px"></canvas>
|
||||
<canvas class="graph members-graph-7d" id="discord-members-graph-7d" height="60px"></canvas>
|
||||
<script>
|
||||
new Chart("discord-members-graph-7d",
|
||||
{
|
||||
|
@ -77,7 +77,7 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
<canvas class="graph cv-graph-7d" id="discord-cv-graph-7d" height="240px"></canvas>
|
||||
<canvas class="graph cv-graph-7d" id="discord-cv-graph-7d" height="60px"></canvas>
|
||||
<script>
|
||||
new Chart("discord-cv-graph-7d",
|
||||
{
|
||||
|
@ -122,7 +122,7 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
<canvas class="graph channels-graph-7d" id="discord-channels-graph-7d" height="240px"></canvas>
|
||||
<canvas class="graph channels-graph-7d" id="discord-channels-graph-7d" height="60px"></canvas>
|
||||
<script>
|
||||
new Chart("discord-channels-graph-7d",
|
||||
{
|
||||
|
@ -151,6 +151,129 @@
|
|||
},
|
||||
"options":{
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<h1>
|
||||
Attività per ogni ora nell'ultimo mese
|
||||
</h1>
|
||||
<canvas class="graph members-graph-hour-bucket" id="discord-members-hour-bucket" height="60px"></canvas>
|
||||
<script>
|
||||
new Chart("discord-members-hour-bucket",
|
||||
{
|
||||
"type": "line",
|
||||
"data": {
|
||||
"labels": [
|
||||
{% for point in hourly_avg %}
|
||||
"{{ point.h|int }}:00",
|
||||
{% endfor %}
|
||||
],
|
||||
"datasets": [
|
||||
{
|
||||
"label": "In cv",
|
||||
"borderColor": "#fe7f00",
|
||||
"backgroundColor": "#fe7f0022",
|
||||
"borderWidth": 4,
|
||||
"cubicInterpolationMode": "monotone",
|
||||
"fill": "origin",
|
||||
"data": [
|
||||
{% for point in hourly_avg %}
|
||||
{{ point.cv_members_avg }},
|
||||
{% endfor %}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "In game",
|
||||
"borderColor": "#9ae915",
|
||||
"backgroundColor": "#9ae91511",
|
||||
"borderWidth": 1,
|
||||
"borderDash": [2],
|
||||
"cubicInterpolationMode": "monotone",
|
||||
"fill": "disabled",
|
||||
"data": [
|
||||
{% for point in hourly_avg %}
|
||||
{{ point.ingame_members_avg }},
|
||||
{% endfor %}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Online",
|
||||
"borderColor": "#6dcff6",
|
||||
"backgroundColor": "#6dcff611",
|
||||
"borderWidth": 1,
|
||||
"cubicInterpolationMode": "monotone",
|
||||
"fill": 0,
|
||||
"data": [
|
||||
{% for point in hourly_avg %}
|
||||
{{ point.online_members_avg }},
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options":{
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<h1>
|
||||
Confronto cv con il mese scorso
|
||||
</h1>
|
||||
<canvas class="graph members-graph-hour-comp" id="discord-members-hour-comp" height="60px"></canvas>
|
||||
<script>
|
||||
new Chart("discord-members-hour-comp",
|
||||
{
|
||||
"type": "line",
|
||||
"data": {
|
||||
"labels": [
|
||||
{% for point in hourly_avg %}
|
||||
"{{ point.h|int }}:00",
|
||||
{% endfor %}
|
||||
],
|
||||
"datasets": [
|
||||
{
|
||||
"label": "Adesso",
|
||||
"borderColor": "#a0ccff",
|
||||
"backgroundColor": "#a0ccff22",
|
||||
"borderWidth": 4,
|
||||
"cubicInterpolationMode": "monotone",
|
||||
"fill": "origin",
|
||||
"data": [
|
||||
{% for point in hourly_avg %}
|
||||
{{ point.cv_members_avg }},
|
||||
{% endfor %}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Il mese scorso",
|
||||
"borderColor": "#d3a1ff",
|
||||
"backgroundColor": "#d3a1ff11",
|
||||
"borderWidth": 1,
|
||||
"cubicInterpolationMode": "monotone",
|
||||
"fill": "origin",
|
||||
"data": [
|
||||
{% for point in hourly_comp %}
|
||||
{{ point.cv_members_avg }},
|
||||
{% endfor %}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Il mese prima",
|
||||
"borderColor": "#ffa3d0",
|
||||
"backgroundColor": "#ffa3d011",
|
||||
"borderWidth": 1,
|
||||
"cubicInterpolationMode": "monotone",
|
||||
"fill": "origin",
|
||||
"data": [
|
||||
{% for point in hourly_before %}
|
||||
{{ point.cv_members_avg }},
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options":{
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<body>
|
||||
<nav>
|
||||
<div class="left">
|
||||
<img src="{{ url_for('static', filename='FixMeRYGLogo.jpg') }}" alt="" class="ryg-logo">
|
||||
<img src="{{ url_for('static', filename='LogoRoyalGames.svg') }}" alt="" title="👑⭐️ RYG" class="ryg-logo">
|
||||
<b>Royalnet</b>
|
||||
<a href="/">Home</a>
|
||||
</div>
|
||||
|
@ -23,8 +23,8 @@
|
|||
<span id="debug-mode">DEBUG MODE</span>
|
||||
{% endif %}
|
||||
<span class="login-status">
|
||||
{% if session.get('username') is not none %}
|
||||
<a href="{{ url_for('page_profile', name=session.get('username')) }}">{{ session.get('username') }}</a>
|
||||
{% if g.user %}
|
||||
<a href="{{ url_for('page_profile', name=g.user.username) }}">{{ g.user.username }}</a>
|
||||
<a class="btn" href="{{ url_for('page_logout') }}">Logout</a>
|
||||
{% else %}
|
||||
<a class="btn" href="{{ url_for('page_login') }}">Login</a>
|
||||
|
@ -32,6 +32,8 @@
|
|||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="omnicontainer">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,13 +1,23 @@
|
|||
<blockquote id="entry-{{ entry.id }}" class="entry {% if entry.spoiler %}spoiler{% endif %}">
|
||||
<blockquote id="diario-{{ entry.id }}" class="diario {% if entry.spoiler %}spoiler{% endif %}">
|
||||
<div class="left">
|
||||
<p>
|
||||
<span class="text">{{ entry.to_html() | safe }}</span>
|
||||
</p>
|
||||
<p>
|
||||
<cite>— {% if entry.author is not none %}<a class="author" href="{{ url_for("page_profile", name=entry.author.royal.username) }}">{{ entry.author.royal.username }}</a>{% else %}<span class="author anonymous">Anonimo</span>{% endif %}, <span class="timestamp">{{ entry.timestamp.strftime('%Y-%m-%d %H:%M:%S %Z') }}</span> {% if entry.saver is not none and entry.saver != entry.author %}<span class="saver">(salvato da <a href="/profile/{{ entry.saver.royal.username }}">{{ entry.saver.royal.username }}</a>)</span>{% endif %}</cite>
|
||||
<cite>—
|
||||
{% if entry.author is not none %}
|
||||
<a class="author known" href="{{ url_for("page_profile", name=entry.author.royal.username) }}">{{ entry.author.royal.username }}</a>
|
||||
{% else %}
|
||||
<span class="author anonymous">Anonimo</span>
|
||||
{% endif %},
|
||||
<span class="timestamp">{{ entry.timestamp.strftime('%Y-%m-%d %H:%M:%S %Z') }}</span>
|
||||
{% if entry.saver is not none and entry.saver != entry.author %}
|
||||
<span class="saver">(salvato da <a href="/profile/{{ entry.saver.royal.username }}">{{ entry.saver.royal.username }}</a>)</span>
|
||||
{% endif %}
|
||||
</cite>
|
||||
</p>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a class="entry-id" href="{{ url_for("page_diario") }}#entry-{{ entry.id }}">#{{ entry.id }}</a>
|
||||
<a class="diario-id" href="#diario-{{ entry.id }}">#{{ entry.id }}</a>
|
||||
</div>
|
||||
</blockquote>
|
9
templates/components/diariooftheday.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Citazione casuale dal diario
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
{% include "components/diarioentry.html" %}
|
||||
<a href="{{ url_for("page_diario") }}">Visualizza tutto il diario</a>
|
||||
</div>
|
||||
</div>
|
10
templates/components/eventlist.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Prossimi eventi
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
{% for event in events %}
|
||||
{% include "components/event.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
19
templates/components/gamestatsbox.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Noi in vari giochi
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul class="multicolumn">
|
||||
<li><a href="{{ url_for("page_game", name="ryg") }}">Royal Games</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="halloween2018") }}">Halloween 2018</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="tg") }}">Telegram</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="discord") }}">Discord</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="steam") }}">Steam</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="dota") }}">Dota 2</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="lol") }}">League of Legends</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="ow") }}">Overwatch</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="osu") }}">osu!</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="terraria13") }}">Terraria 13</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
26
templates/components/links.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Link riservati ai membri
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul>
|
||||
{% if g.rygconf['Telegram']['invite_link'] %}
|
||||
<li><a href="{{ g.rygconf['Telegram']['invite_link'] }}">Link di unione a Telegram</a></li>
|
||||
{% else %}
|
||||
<li><i>Link di unione a Telegram disattivato</i></li>
|
||||
{% endif %}
|
||||
{% if g.rygconf['Discord']['invite_link'] %}
|
||||
<li><a href="{{ g.rygconf['Discord']['invite_link'] }}">Link di invito a Discord</a></li>
|
||||
{% else %}
|
||||
<li><i>Link di invito a Discord disattivato</i></li>
|
||||
{% endif %}
|
||||
<li><a href="https://steamcommunity.com/groups/royalgamescastle">Gruppo Steam Community</a></li>
|
||||
<li><a href="https://new.reddit.com/r/RoyalGames/">/r/RoyalGames</a></li>
|
||||
<li><a href="{{ url_for("page_music") }}">Statistiche su Royal Music</a></li>
|
||||
<li><a href="http://amazon.steffo.eu/royal-music-cache/">File in cache di Royal Music</a></li>
|
||||
<li><a href="{{ url_for("page_activity") }}">Statistiche sull'attività</a></li>
|
||||
<li><a href="https://github.com/Steffo99/royalnet">Codice sorgente di Royalnet</a></li>
|
||||
<li><a href="https://ryg.challonge.com/">Pagina Challonge (Tornei)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
12
templates/components/memberbox.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="box" id="members-box">
|
||||
<div class="upper-box">
|
||||
Membri
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul class="multicolumn">
|
||||
{% for royal in royals %}
|
||||
<li class="{% if royal.role == "Admin" %}list-admin{% endif %}"><a href="/profile/{{ royal.username }}">{{ royal.username }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
14
templates/components/quest.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<div class="quest">
|
||||
<div class="title">
|
||||
{{ quest.title }}
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ quest.description | markdown }}
|
||||
</div>
|
||||
<div class="reward">
|
||||
{% if quest.reward %}
|
||||
<div class="number">{{ quest.reward }}</div>
|
||||
<div class="subtext">fioryg{% if quest.reward != 1 %}i{% endif %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
14
templates/components/questboard.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Tabellone delle quest
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
{% if quests %}
|
||||
{% for quest in quests %}
|
||||
{% include "components/quest.html" %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<i>Non ci sono quest al momento.</i>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
8
templates/components/welcome.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Benvenuti!
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
Benvenuti al sito della community Royal Games!
|
||||
</div>
|
||||
</div>
|
9
templates/components/whatarewe.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Cosa siamo?
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
La Royal Games è una community di gamer di tutti i tipi che sono capitati insieme più o meno per caso, e continuano a trovarsi spesso online per parlare e giocare insieme.<br>
|
||||
Essendo nata <a href="{{ url_for("page_wiki", key="Storia della Royal Games") }}">parecchi anni fa</a>, all'interno di essa si è sviluppata una particolare cultura che la rende unica in tutto l'Internet.
|
||||
</div>
|
||||
</div>
|
|
@ -9,11 +9,13 @@
|
|||
Pagine Wiki
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul>
|
||||
<ul class="multicolumn">
|
||||
{% for page in wiki_pages %}
|
||||
<li><a href="/wiki/{{ page.key }}">{{ page.key }}</a></li>
|
||||
<li class="{% if page.locked %}list-locked{% endif %}"><a href="/wiki/{{ page.key }}">{{ page.key }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if g.user %}
|
||||
oppure... <input id="input-key" name="key" type="text" placeholder="Nome pagina" class="half"><button onclick="createpage()">Crea</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
|
@ -12,11 +12,9 @@
|
|||
<h1>
|
||||
Diario <a href="{{ url_for("page_wiki", key="Diario") }}" class="whatsthis">Cos'è?</a>
|
||||
</h1>
|
||||
<div class="omnicontainer">
|
||||
<div class="diario">
|
||||
{% for entry in entries %}
|
||||
{% include "components/diarioentry.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -6,22 +6,23 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block pagetitle %}
|
||||
{{ game_name }}
|
||||
{{ mini_type._mini_full_name }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>
|
||||
Royal Games su {{ game_name }}
|
||||
Royal Games su {{ mini_type._mini_full_name }}
|
||||
</h1>
|
||||
<div class="omnicontainer">
|
||||
{% if mini_type._mini_name == "ow" %}
|
||||
<div>
|
||||
Overwatch updates are currently disabled.
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="game">
|
||||
<div class="game-panels">
|
||||
{% for mini in minis %}
|
||||
{% with record = mini %}
|
||||
{% include "minis/" + game_short_name + ".html" %}
|
||||
{% endwith %}
|
||||
{% for record in mini_data %}
|
||||
{% include "minis/" + mini_type._mini_name + ".html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -9,90 +9,36 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1 id="main-title">
|
||||
Royal Games
|
||||
<h1 id="royal-games">
|
||||
<img src="{{ url_for('static', filename='LogoRoyalGames.svg') }}" alt=""> Royal Games
|
||||
</h1>
|
||||
<div class="main-page">
|
||||
<div class="two-columns">
|
||||
<div class="left">
|
||||
<div class="box">
|
||||
{% if next_events %}
|
||||
<div class="upper-box">
|
||||
Prossimi eventi
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
{% for event in next_events %}
|
||||
{% include "components/event.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if not g.user %}
|
||||
{% include "components/welcome.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Citazione casuale dal diario
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
{% include "components/diarioentry.html" %}
|
||||
<a href="{{ url_for("page_diario") }}">Visualizza tutto</a>
|
||||
</div>
|
||||
</div>
|
||||
{% if g.user %}
|
||||
{% if events %}
|
||||
{% include "components/eventlist.html" %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include "components/memberbox.html" %}
|
||||
{% if g.user %}
|
||||
{% include "components/wikibox.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Link utili
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul>
|
||||
{% if g.rygconf['Telegram']['invite_link'] %}
|
||||
<li><a href="{{ g.rygconf['Telegram']['invite_link'] }}">Link di unione a Telegram</a></li>
|
||||
{% else %}
|
||||
<li><i>Link di unione a Telegram disattivato</i></li>
|
||||
{% if not g.user %}
|
||||
{% include "components/whatarewe.html" %}
|
||||
{% endif %}
|
||||
{% if g.rygconf['Discord']['invite_link'] %}
|
||||
<li><a href="{{ g.rygconf['Discord']['invite_link'] }}">Link di invito a Discord</a></li>
|
||||
{% else %}
|
||||
<li><i>Link di invito a Discord disattivato</i></li>
|
||||
{% if g.user %}
|
||||
{% include "components/questboard.html" %}
|
||||
{% endif %}
|
||||
{% include "components/gamestatsbox.html" %}
|
||||
{% if g.user %}
|
||||
{% include "components/links.html" %}
|
||||
{% include "components/diariooftheday.html" %}
|
||||
{% endif %}
|
||||
<li><a href="https://steamcommunity.com/groups/royalgamescastle">Gruppo Steam Community</a></li>
|
||||
<li><a href="https://new.reddit.com/r/RoyalGames/">/r/RoyalGames</a></li>
|
||||
<li><a href="{{ url_for("page_music") }}">Statistiche su Royal Music</a></li>
|
||||
<li><a href="http://amazon.steffo.eu/royal-music-cache/">File in cache di Royal Music</a></li>
|
||||
<li><a href="{{ url_for("page_activity") }}">Statistiche sull'attività</a></li>
|
||||
<li><a href="https://github.com/Steffo99/royalnet">Codice sorgente di Royalnet</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Membri
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul>
|
||||
{% for royal in royals %}
|
||||
<li><a href="/profile/{{ royal.username }}">{{ royal.username }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="upper-box">
|
||||
Resoconti
|
||||
</div>
|
||||
<div class="lower-box">
|
||||
<ul>
|
||||
<li><a href="{{ url_for("page_game", name="ryg") }}">Royal Games</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="halloween2018") }}">Halloween 2018</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="tg") }}">Telegram</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="discord") }}">Discord</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="steam") }}">Steam</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="dota") }}">Dota 2</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="lol") }}">League of Legends</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="ow") }}">Overwatch</a></li>
|
||||
<li><a href="{{ url_for("page_game", name="osu") }}">osu!</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -21,11 +21,14 @@
|
|||
<span>{{ record.wins }}</span>
|
||||
</div>
|
||||
<div class="rank">
|
||||
{% if record.rank_tier is none %}
|
||||
<img class="medal" src="https://www.opendota.com/assets/images/dota2/rank_icons/rank_icon_0.png" alt="">
|
||||
{% if (record.wins + record.losses) < 100 %}
|
||||
<img class="medal locked" src="{{ url_for("static", filename="rank_icon_locked.png") }}" alt="">
|
||||
<span class="text">{{ 100 - record.wins - record.losses }} partite rimaste</span>
|
||||
{% elif record.rank_tier is none %}
|
||||
<img class="medal unranked" src="https://www.opendota.com/assets/images/dota2/rank_icons/rank_icon_0.png" alt="">
|
||||
<span class="text">Non classificato</span>
|
||||
{% elif record.rank_tier < 10 %}
|
||||
<img class="medal" src="https://www.opendota.com/assets/images/dota2/rank_icons/rank_icon_0.png" alt="">
|
||||
<img class="medal unranked" src="https://www.opendota.com/assets/images/dota2/rank_icons/rank_icon_0.png" alt="">
|
||||
<span class="text">{{ record.rank_tier }} piazzamenti completati</span>
|
||||
{% else %}
|
||||
<img class="medal" src="{{ record.get_rank_icon_url() }}" alt="">{% if record.get_rank_stars_url() %}<img class="stars" src="{{ record.get_rank_stars_url() }}" alt="">{% endif %}
|
||||
|
|
|
@ -1,16 +1,64 @@
|
|||
<div class="game-panel">
|
||||
<div class="game-grid ryg">
|
||||
<div class="player">
|
||||
<span class="player-name"><a href="https://ryg.steffo.eu/profile/{{ record.username }}">{{ record.username }}</a></span>
|
||||
<div class="game-grid ryg role-{{ record.role }}">
|
||||
<div class="username">
|
||||
<a href="{{ url_for("page_profile", name=record.username) }}">{{ record.username }}</a>
|
||||
</div>
|
||||
<div class="member-status">
|
||||
<span class="role">{{ record.role }}</span> dal <span class="member-since">{% if record.member_since %}{{ record.member_since }}{% else %}????-??-??{% endif %}</span>
|
||||
{% if record.special_title %}
|
||||
<div class="special-title">
|
||||
{{ record.special_title }}
|
||||
</div>
|
||||
<div class="game-title fiorygi">
|
||||
{% endif %}
|
||||
{% if record.username == "Steffo" %}
|
||||
<div class="join-date-title steffo">
|
||||
Admin dall'
|
||||
</div>
|
||||
<div class="join-date steffo">
|
||||
inizio!
|
||||
</div>
|
||||
{% elif record.member_since %}
|
||||
<div class="join-date-title member">
|
||||
{{ record.role }} dal
|
||||
</div>
|
||||
<div class="join-date member">
|
||||
{{ record.member_since.isoformat() }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="join-date-title unknown">
|
||||
{{ record.role }} dal
|
||||
</div>
|
||||
<div class="join-date unknown" title="Data di unione sconosciuta">
|
||||
?
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if record.wiki_edits|length > 0 %}
|
||||
<div class="wiki-edits-title">
|
||||
Contributi wiki
|
||||
</div>
|
||||
<div class="wiki-edits">
|
||||
{{ record.wiki_edits|length }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="wiki-edits-title unknown">
|
||||
Contributi wiki
|
||||
</div>
|
||||
<div class="wiki-edits unknown">
|
||||
---
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if record.fiorygi > 0 %}
|
||||
<div class="fiorygi-title">
|
||||
Fiorygi
|
||||
</div>
|
||||
<div class="game-score fiorygi">
|
||||
<div class="fiorygi">
|
||||
{{ record.fiorygi }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="fiorygi-title unknown">
|
||||
Fiorygi
|
||||
</div>
|
||||
<div class="fiorygi unknown">
|
||||
---
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
21
templates/minis/terraria13.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<style>
|
||||
@font-face {
|
||||
font-family: "Andy";
|
||||
src: url("{{ url_for('static', filename='terrariafont.ttf') }}");
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<div class="game-panel">
|
||||
<div class="game-grid terraria13">
|
||||
<div class="character">
|
||||
{{ record.character_name }}
|
||||
</div>
|
||||
<div class="contribution-status">
|
||||
<span class="contribution {% if record.contribution >= 8 %}orange{% elif record.contribution >= 5 %}green{% elif record.contribution >= 3 %}blue{% endif %}">
|
||||
{{ record.contribution }}
|
||||
</span>
|
||||
fioryg{% if record.contribution != 1 %}i{% endif %} ottenut{% if record.contribution != 1 %}i{% else %}o{% endif %} per la partecipazione a Terraria 13!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -23,7 +23,6 @@
|
|||
<h1>
|
||||
Profilo di {{ ryg.username }} {% if session.get('user_id', '') == ryg.id %}<a href="{{ url_for('page_editprofile') }}" id="edit-css">Modifica</a>{% endif %}
|
||||
</h1>
|
||||
<div class="omnicontainer">
|
||||
<div class="profile">
|
||||
{% if css.bio %}
|
||||
<div class="box bio">
|
||||
|
@ -36,50 +35,11 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
<div class="game-panels">
|
||||
{% with record = ryg %}
|
||||
{% include "minis/ryg.html" %}
|
||||
{% for mini in mini_data %}
|
||||
{% with record = mini["data"] %}
|
||||
{% include "minis/" + mini["name"] + ".html" %}
|
||||
{% endwith %}
|
||||
{% if halloween %}
|
||||
{% with record = halloween %}
|
||||
{% include "minis/halloween2018.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if tg %}
|
||||
{% with record = tg %}
|
||||
{% include "minis/tg.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if discord %}
|
||||
{% with record = discord %}
|
||||
{% include "minis/discord.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if steam %}
|
||||
{% with record = steam %}
|
||||
{% include "minis/steam.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if dota %}
|
||||
{% with record = dota %}
|
||||
{% include "minis/dota.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if osu %}
|
||||
{% with record = osu %}
|
||||
{% include "minis/osu.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if lol %}
|
||||
{% with record = lol %}
|
||||
{% include "minis/lol.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if ow %}
|
||||
{% with record = ow %}
|
||||
{% include "minis/ow.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -9,6 +9,7 @@
|
|||
Modifica profilo
|
||||
</h1>
|
||||
<form action="{{ url_for('page_editprofile') }}" method="POST">
|
||||
<input type="email" name="email" placeholder="La tua e-mail (Gravatar)" value="{{ royal.email }}"><br>
|
||||
Puoi usare il <a href="{{ url_for('page_wiki', key='Meta') }}">Markdown</a> nella tua bio.
|
||||
<textarea name="bio" placeholder="Scrivi la tua bio qui... (Markdown supportato)">{{ data.bio }}</textarea>
|
||||
Se vuoi, puoi personalizzare il tuo profilo con un tuo <a href="https://www.w3schools.com/css/css_howto.asp">foglio di stile!</a>
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block pagetitle %}
|
||||
Elenco delle Wiki
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>
|
||||
Royal Wiki
|
||||
</h1>
|
||||
<div class="wiki-home">
|
||||
{% include "components/wikibox.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -43,15 +43,37 @@
|
|||
Ultima modifica di <span class="last-author"><a href="/profile/{{ wiki_log.editor.username }}">{{ wiki_log.editor.username }}</a></span> alle <span class="last-timestamp">{{ wiki_log.timestamp.strftime('%Y-%m-%d %H:%M:%S %Z') }}</span>{% if wiki_log.reason %}, motivo: <span class="last-reason">{{ wiki_log.reason }}</span>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if session.get('user_id', '') %}
|
||||
{% if wiki_page is none %}
|
||||
<div class="wiki-edit">
|
||||
<h4>Crea</h4>
|
||||
<form action="{{ url_for('page_wiki_edit', key=key) }}" method="POST">
|
||||
<textarea oninput="newEdit()" class="content" name="content" placeholder="Inserisci il Markdown per la pagina qui.">{% if wiki_page %}{{ wiki_page.content }}{% endif %}</textarea><br>
|
||||
<input class="reason" name="reason" type="text" placeholder="Motivo per la creazione (facoltativo)"><br>
|
||||
<input class="submit" type="submit" onmouseenter="onEnter()" onmouseleave="onExit()" value="Crea">
|
||||
</form>
|
||||
</div>
|
||||
{% elif wiki_page.locked %}
|
||||
<div class="wiki-locked">
|
||||
<span>🔒 Pagina bloccata: non possono essere effettuate ulteriori modifiche.</span>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if g.user %}
|
||||
<div class="wiki-edit">
|
||||
<h4>Modifica</h4>
|
||||
<form action="{{ url_for('page_wiki', key=key) }}" method="POST">
|
||||
<textarea oninput="newEdit()" class="content" name="content" placeholder="Inserisci il Markdown per la pagina qui.">{% if wiki_page %}{{ wiki_page.content }}{% endif %}</textarea><br>
|
||||
<input class="reason" name="reason" type="text" placeholder="Motivo per la modifica"><br>
|
||||
<input class="submit" type="submit" onmouseenter="onEnter()" onmouseleave="onExit()" value="Invia">
|
||||
<form action="{{ url_for('page_wiki_edit', key=key) }}" method="POST">
|
||||
<textarea oninput="newEdit()" class="content" name="content" placeholder="Non eliminare pagine altrui. Steffo non la prenderà bene.">{% if wiki_page %}{{ wiki_page.content }}{% endif %}</textarea><br>
|
||||
<input class="reason" name="reason" type="text" placeholder="Motivo per la modifica (facoltativo)"><br>
|
||||
<input class="submit" type="submit" onmouseenter="onEnter()" onmouseleave="onExit()" value="Salva">
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if wiki_page is not none %}
|
||||
{% if g.user.role == "Admin" %}
|
||||
<form action="{{ url_for('page_wiki_lock', key=key) }}" method="POST">
|
||||
<input class="submit" type="submit" value="Blocca/Sblocca pagina">
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -2,13 +2,15 @@
|
|||
# Requires SENTRY_AUTH_TOKEN and SENTRY_ORG set in .sentryclirc
|
||||
|
||||
old=$(git rev-list HEAD -n 1)
|
||||
git stash
|
||||
git pull
|
||||
git lfs pull
|
||||
new=$(git rev-list HEAD -n 1)
|
||||
if [ ${old} = ${new} ]; then
|
||||
if [[ ${old} = ${new} ]]; then
|
||||
version=$(sentry-cli releases propose-version)
|
||||
sentry-cli releases new -p royalnet ${version}
|
||||
sentry-cli releases set-commits --auto ${version}
|
||||
fi
|
||||
sudo python3.6 -m pip install -r requirements.txt
|
||||
sudo python3.6 -m pip install -r requirements.txt --upgrade
|
||||
sudo service apache2 restart
|
||||
python3.6 -OO bots.py
|
||||
|
|
8
utils/__init__.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
from .dirty import Dirty, DirtyDelta
|
||||
from .mmstatus import MatchmakingStatus
|
||||
from .cast import Spell
|
||||
from .stagismo import smecds
|
||||
from .emojify import emojify
|
||||
from .telegramstuff import reply_msg
|
||||
|
||||
__all__ = ["Dirty", "DirtyDelta", "MatchmakingStatus", "Spell", "smecds", "emojify", "reply_msg"]
|
230
utils/cast.py
Normal file
|
@ -0,0 +1,230 @@
|
|||
import random
|
||||
import math
|
||||
import typing
|
||||
import strings
|
||||
import enum
|
||||
s = strings.safely_format_string
|
||||
|
||||
|
||||
class SpellType(enum.Flag):
|
||||
DAMAGING = enum.auto()
|
||||
HEALING = enum.auto()
|
||||
STATS = enum.auto()
|
||||
STATUS_EFFECT = enum.auto()
|
||||
|
||||
|
||||
class DamageComponent:
|
||||
dice_type_distribution = ([4] * 7) +\
|
||||
([6] * 12) +\
|
||||
([8] * 32) +\
|
||||
([10] * 30) +\
|
||||
([12] * 12) +\
|
||||
([20] * 6) +\
|
||||
([100] * 1)
|
||||
|
||||
all_damage_types = ["da fuoco", "da freddo", "elettrici", "sonici", "necrotici", "magici",
|
||||
"da acido", "divini", "nucleari", "psichici", "fisici", "puri", "da taglio",
|
||||
"da perforazione", "da impatto", "da caduta", "gelato", "onnipotenti", "oscuri",
|
||||
"di luce", "da velocità", "da cactus", "dannosi", "da radiazione",
|
||||
"tuamammici", "da maledizione", "pesanti", "leggeri", "immaginari", "da laser",
|
||||
"da neutrini", "galattici", "cerebrali", "ritardati", "ritardanti", "morali", "materiali",
|
||||
"energetici", "esplosivi", "energetici", "finanziari", "radianti", "sonori", "spaggiaritici",
|
||||
"interiori", "endocrini", "invisibili", "inesistenti", "eccellenti", "bosonici",
|
||||
"gellificanti", "terminali"]
|
||||
|
||||
repeat_distribution = ([1] * 8) +\
|
||||
([2] * 1) +\
|
||||
([3] * 1)
|
||||
|
||||
damage_types_distribution = ([1] * 6) + \
|
||||
([2] * 3) + \
|
||||
([3] * 1)
|
||||
|
||||
def __init__(self):
|
||||
# ENSURE THE SEED IS ALREADY SET WHEN CREATING THIS COMPONENT!!!
|
||||
self.dice_number = random.randrange(1, 21)
|
||||
self.dice_type = random.sample(self.dice_type_distribution, 1)[0]
|
||||
self.constant = random.randrange(math.floor(-self.dice_type / 4), math.ceil(self.dice_type / 4) + 1)
|
||||
self.miss_chance = random.randrange(50, 101)
|
||||
self.repeat = random.sample(self.repeat_distribution, 1)[0]
|
||||
self.damage_types_qty = random.sample(self.damage_types_distribution, 1)[0]
|
||||
self.damage_types = random.sample(self.all_damage_types, self.damage_types_qty)
|
||||
|
||||
@property
|
||||
def avg(self):
|
||||
return (self.dice_number * (self.dice_type + 1) / 2) + self.constant
|
||||
|
||||
def stringify(self) -> str:
|
||||
string = ""
|
||||
if self.constant > 0:
|
||||
constant = "+" + str(self.constant)
|
||||
elif self.constant == 0:
|
||||
constant = ""
|
||||
else:
|
||||
constant = str(self.constant)
|
||||
string += s(strings.SPELL.DAMAGE,
|
||||
words={"number": str(self.dice_number),
|
||||
"type": str(self.dice_type),
|
||||
"constant": constant,
|
||||
"avg": str(int(self.avg))})
|
||||
for dmg_type in self.damage_types:
|
||||
string += s(strings.SPELL.TYPE, words={"type": dmg_type})
|
||||
string += s(strings.SPELL.ACCURACY, words={"accuracy": str(self.miss_chance)})
|
||||
if self.repeat > 1:
|
||||
string += s(strings.SPELL.REPEAT, words={"repeat": str(self.repeat)})
|
||||
return string
|
||||
|
||||
|
||||
class HealingComponent:
|
||||
dice_type_distribution = ([4] * 12) +\
|
||||
([6] * 38) +\
|
||||
([8] * 30) +\
|
||||
([10] * 12) +\
|
||||
([12] * 6) +\
|
||||
([20] * 1) +\
|
||||
([100] * 1)
|
||||
|
||||
def __init__(self):
|
||||
# ENSURE THE SEED IS ALREADY SET WHEN CREATING THIS COMPONENT!!!
|
||||
self.dice_number = random.randrange(1, 11)
|
||||
self.dice_type = random.sample(self.dice_type_distribution, 1)[0]
|
||||
self.constant = random.randrange(math.floor(-self.dice_type / 4), math.ceil(self.dice_type / 4) + 1)
|
||||
|
||||
@property
|
||||
def avg(self):
|
||||
return (self.dice_number * (self.dice_type + 1) / 2) + self.constant
|
||||
|
||||
def stringify(self) -> str:
|
||||
string = ""
|
||||
if self.constant > 0:
|
||||
constant = "+" + str(self.constant)
|
||||
elif self.constant == 0:
|
||||
constant = ""
|
||||
else:
|
||||
constant = str(self.constant)
|
||||
string += s(strings.SPELL.HEALING,
|
||||
words={"number": str(self.dice_number),
|
||||
"type": str(self.dice_type),
|
||||
"constant": constant,
|
||||
"avg": str(int(self.avg))})
|
||||
return string
|
||||
|
||||
|
||||
class StatsComponent:
|
||||
all_stats = ["Attacco", "Difesa", "Velocità", "Elusione", "Tenacia", "Rubavita",
|
||||
"Vampirismo", "Forza", "Destrezza", "Costituzione", "Intelligenza",
|
||||
"Saggezza", "Carisma", "Attacco Speciale", "Difesa Speciale",
|
||||
"Eccellenza", "Immaginazione", "Cromosomi", "Timidezza", "Sonno",
|
||||
"Elasticità", "Peso", "Sanità", "Appetito", "Fortuna", "Percezione",
|
||||
"Determinazione"]
|
||||
|
||||
change_distribution = (["--"] * 1) +\
|
||||
(["-"] * 2) +\
|
||||
(["+"] * 2) +\
|
||||
(["++"] * 1)
|
||||
|
||||
multistat_distribution = ([1] * 16) +\
|
||||
([2] * 8) +\
|
||||
([3] * 4) +\
|
||||
([5] * 2) +\
|
||||
([8] * 1)
|
||||
|
||||
def __init__(self):
|
||||
# ENSURE THE SEED IS ALREADY SET WHEN CREATING THIS COMPONENT!!!
|
||||
self.stat_changes = {}
|
||||
self.stat_number = random.sample(self.multistat_distribution, 1)[0]
|
||||
available_stats = self.all_stats.copy()
|
||||
for _ in range(self.stat_number):
|
||||
stat = random.sample(available_stats, 1)[0]
|
||||
available_stats.remove(stat)
|
||||
change = random.sample(self.change_distribution, 1)[0]
|
||||
self.stat_changes[stat] = change
|
||||
|
||||
def stringify(self) -> str:
|
||||
string = ""
|
||||
for name in self.stat_changes:
|
||||
string += s(strings.SPELL.STAT, words={
|
||||
"name": name,
|
||||
"change": self.stat_changes[name]
|
||||
})
|
||||
return string
|
||||
|
||||
|
||||
class StatusEffectComponent:
|
||||
all_status_effects = ["Bruciatura", "Sanguinamento", "Paralisi", "Veleno",
|
||||
"Congelamento", "Iperveleno", "Sonno", "Stordimento",
|
||||
"Rallentamento", "Radicamento", "Rigenerazione", "Morte",
|
||||
"Affaticamento", "Glitch", "Accecamento", "Silenzio",
|
||||
"Esilio", "Invisibilità", "Rapidità", "Splendore"]
|
||||
|
||||
def __init__(self):
|
||||
# ENSURE THE SEED IS ALREADY SET WHEN CREATING THIS COMPONENT!!!
|
||||
self.chance = random.randrange(1, 101)
|
||||
self.effect = random.sample(self.all_status_effects, 1)[0]
|
||||
|
||||
def stringify(self) -> str:
|
||||
return s(strings.SPELL.STATUS_EFFECT, words={
|
||||
"chance": str(self.chance),
|
||||
"effect": self.effect
|
||||
})
|
||||
|
||||
|
||||
|
||||
class Spell:
|
||||
version = "3.2"
|
||||
|
||||
damaging_spell_chance = 0.9
|
||||
healing_spell_chance = 0.9 # If not a damaging spell
|
||||
additional_stats_chance = 0.1 # In addition to the damage/healing
|
||||
additional_status_effect_chance = 0.1 # In addition to the rest
|
||||
|
||||
def __init__(self, name: str):
|
||||
seed = name.capitalize()
|
||||
random.seed(seed)
|
||||
# Spell name
|
||||
self.name = seed
|
||||
# Find the spell type
|
||||
self.spell_type = SpellType(0)
|
||||
if random.random() < self.damaging_spell_chance:
|
||||
self.spell_type |= SpellType.DAMAGING
|
||||
elif random.random() < self.healing_spell_chance:
|
||||
self.spell_type |= SpellType.HEALING
|
||||
if random.random() < self.additional_stats_chance:
|
||||
self.spell_type |= SpellType.STATS
|
||||
if random.random() < self.additional_status_effect_chance:
|
||||
self.spell_type |= SpellType.STATUS_EFFECT
|
||||
# Damaging spells
|
||||
if self.spell_type & SpellType.DAMAGING:
|
||||
self.damage_component = DamageComponent()
|
||||
else:
|
||||
self.damage_component = None
|
||||
# Healing spells
|
||||
if self.spell_type & SpellType.HEALING:
|
||||
self.healing_component = HealingComponent()
|
||||
else:
|
||||
self.healing_component = None
|
||||
# Stats spells
|
||||
if self.spell_type & SpellType.STATS:
|
||||
self.stats_component = StatsComponent()
|
||||
else:
|
||||
self.stats_component = None
|
||||
# Status effect spells
|
||||
if self.spell_type & SpellType.STATUS_EFFECT:
|
||||
self.status_effect_component = StatusEffectComponent()
|
||||
else:
|
||||
self.status_effect_component = None
|
||||
|
||||
|
||||
def stringify(self) -> str:
|
||||
string = s(strings.SPELL.HEADER, words={"name": self.name, "version": self.version})
|
||||
if self.spell_type & SpellType.DAMAGING:
|
||||
string += self.damage_component.stringify()
|
||||
if self.spell_type & SpellType.HEALING:
|
||||
string += self.healing_component.stringify()
|
||||
if self.spell_type & SpellType.STATS:
|
||||
string += self.stats_component.stringify()
|
||||
if self.spell_type & SpellType.STATUS_EFFECT:
|
||||
string += self.status_effect_component.stringify()
|
||||
if self.spell_type == SpellType(0):
|
||||
string += s(strings.SPELL.NOTHING)
|
||||
return string
|
37
utils/dirty.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
class Dirty:
|
||||
def __init__(self, initial_value):
|
||||
self.initial_value = initial_value
|
||||
self.value = initial_value
|
||||
|
||||
def is_clean(self):
|
||||
return self.initial_value == self.value
|
||||
|
||||
def is_dirty(self):
|
||||
return not self.is_clean()
|
||||
|
||||
def __bool__(self):
|
||||
return self.is_dirty()
|
||||
|
||||
|
||||
class DirtyDelta(Dirty):
|
||||
|
||||
@property
|
||||
def difference(self):
|
||||
if self.initial_value is None:
|
||||
initial_value = 0
|
||||
else:
|
||||
initial_value = self.initial_value
|
||||
if self.value is None:
|
||||
value = 0
|
||||
else:
|
||||
value = self.value
|
||||
return value - initial_value
|
||||
|
||||
@property
|
||||
def delta(self):
|
||||
return abs(self.difference)
|
||||
|
||||
def difference_string(self):
|
||||
if self.difference > 0:
|
||||
return f"+{self.difference}"
|
||||
return self.difference
|
59
utils/emojify.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
import random
|
||||
|
||||
emojis = {
|
||||
"abcd": ["🔡", "🔠"],
|
||||
"back": ["🔙"],
|
||||
"cool": ["🆒"],
|
||||
"free": ["🆓"],
|
||||
"abc": ["🔤"],
|
||||
"atm": ["🏧"],
|
||||
"new": ["🆕"],
|
||||
"sos": ["🆘"],
|
||||
"top": ["🔝"],
|
||||
"zzz": ["💤"],
|
||||
"end": ["🔚"],
|
||||
"ab": ["🆎"],
|
||||
"cl": ["🆑"],
|
||||
"id": ["🆔"],
|
||||
"ng": ["🆖"],
|
||||
"no": ["♑️"],
|
||||
"ok": ["🆗"],
|
||||
"on": ["🔛"],
|
||||
"sy": ["💱"],
|
||||
"tm": ["™️"],
|
||||
"wc": ["🚾"],
|
||||
"up": ["🆙"],
|
||||
"a": ["🅰️"],
|
||||
"b": ["🅱️"],
|
||||
"c": ["☪️", "©", "🥐"],
|
||||
"d": ["🇩"],
|
||||
"e": ["📧", "💶"],
|
||||
"f": ["🎏"],
|
||||
"g": ["🇬"],
|
||||
"h": ["🏨", "🏩", "🏋♀", "🏋♂"],
|
||||
"i": ["ℹ️", "♊️", "🕕"],
|
||||
"j": ["⤴️"],
|
||||
"k": ["🎋", "🦅", "💃"],
|
||||
"l": ["🛴", "🕒"],
|
||||
"m": ["♏️", "Ⓜ️", "〽️"],
|
||||
"n": ["📈"],
|
||||
"o": ["⭕️", "🅾️", "📯", "🌝", "🌚", "🌕", "🥯", "🙆♀", "🙆♂"],
|
||||
"p": ["🅿️"],
|
||||
"q": ["🔍", "🍀"],
|
||||
"r": ["®"],
|
||||
"s": ["💰", "💵", "💸", "💲"],
|
||||
"t": ["✝️", "⬆️", "☦️"],
|
||||
"u": ["⛎", "⚓️", "🍉", "🌙", "🐋"],
|
||||
"v": ["✅", "🔽", "☑️", "✔️"],
|
||||
"w": ["🤷♀","🤷♂", "🤾♀", "🤾♂", "🤽♀", "🤽♂"],
|
||||
"x": ["🙅♀", "🙅♂", "❌", "❎"],
|
||||
"y": ["💴"],
|
||||
"z": ["⚡️"]
|
||||
}
|
||||
|
||||
def emojify(string: str):
|
||||
new_string = string.lower()
|
||||
for key in emojis:
|
||||
selected_emoji = random.sample(emojis[key], 1)[0]
|
||||
new_string = new_string.replace(key, selected_emoji)
|
||||
return new_string
|
9
utils/mmstatus.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
import enum
|
||||
|
||||
|
||||
class MatchmakingStatus(enum.IntEnum):
|
||||
WAIT_FOR_ME = 1
|
||||
READY = 2
|
||||
MAYBE = 3
|
||||
SOMEONE_ELSE = 4
|
||||
IGNORED = -1
|
46
utils/stagismo.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
smecds = ["della secca", "del seccatore", "del secchiello", "del secchio", "del secchione", "del secondino",
|
||||
"del sedano", "del sedativo", "della sedia", "del sedicente", "del sedile", "della sega", "del segale",
|
||||
"della segatura", "della seggiola", "del seggiolino", "della seggiovia", "della segheria", "del seghetto",
|
||||
"del segnalibro", "del segnaposto", "del segno", "del segretario", "della segreteria", "del seguace",
|
||||
"del segugio", "della selce", "della sella", "della selz", "della selva", "della selvaggina", "del semaforo",
|
||||
"del seme", "del semifreddo", "del seminario", "della seminarista", "della semola", "del semolino",
|
||||
"del semplicione", "della senape", "del senatore", "del seno", "del sensore", "della sentenza",
|
||||
"della sentinella", "del sentore", "della seppia", "del sequestratore", "della serenata", "del sergente",
|
||||
"del sermone", "della serpe", "del serpente", "della serpentina", "della serra", "del serraglio",
|
||||
"del serramanico", "della serranda", "della serratura", "del servitore", "della servitù", "del servizievole",
|
||||
"del servo", "del set", "della seta", "della setola", "del sidecar", "del siderurgico", "del sidro",
|
||||
"della siepe", "del sifone", "della sigaretta", "del sigaro", "del sigillo", "della signora",
|
||||
"della signorina", "del silenziatore", "della silhouette", "del silicio", "del silicone", "del siluro",
|
||||
"della sinagoga", "della sindacalista", "del sindacato", "del sindaco", "della sindrome", "della sinfonia",
|
||||
"del sipario", "del sire", "della sirena", "della siringa", "del sismografo", "del sobborgo",
|
||||
"del sobillatore", "del sobrio", "del soccorritore", "del socio", "del sociologo", "della soda", "del sofà",
|
||||
"della soffitta", "del software", "dello sogghignare", "del soggiorno", "della sogliola", "del sognatore",
|
||||
"della soia", "del solaio", "del solco", "del soldato", "del soldo", "del sole", "della soletta",
|
||||
"della solista", "del solitario", "del sollazzare", "del sollazzo", "del sollecito", "del solleone",
|
||||
"del solletico", "del sollevare", "del sollievo", "del solstizio", "del solubile", "del solvente",
|
||||
"della soluzione", "del somaro", "del sombrero", "del sommergibile", "del sommo", "della sommossa",
|
||||
"del sommozzatore", "del sonar", "della sonda", "del sondaggio", "del sondare", "del sonnacchioso",
|
||||
"del sonnambulo", "del sonnellino", "del sonnifero", "del sonno", "della sonnolenza", "del sontuoso",
|
||||
"del soppalco", "del soprabito", "del sopracciglio", "del sopraffare", "del sopraffino", "del sopraluogo",
|
||||
"del sopramobile", "del soprannome", "del soprano", "del soprappensiero", "del soprassalto",
|
||||
"del soprassedere", "del sopravvento", "del sopravvivere", "del soqquadro", "del sorbetto", "del sordido",
|
||||
"della sordina", "del sordo", "della sorella", "della sorgente", "del sornione", "del sorpasso",
|
||||
"della sorpresa", "del sorreggere", "del sorridere", "della sorsata", "del sorteggio", "del sortilegio",
|
||||
"del sorvegliante", "del sorvolare", "del sosia", "del sospettoso", "del sospirare", "della sosta",
|
||||
"della sostanza", "del sostegno", "del sostenitore", "del sostituto", "del sottaceto", "della sottana",
|
||||
"del sotterfugio", "del sotterraneo", "del sottile", "del sottilizzare", "del sottintendere",
|
||||
"del sottobanco", "del sottobosco", "del sottomarino", "del sottopassaggio", "del sottoposto",
|
||||
"del sottoscala", "della sottoscrizione", "del sottostare", "del sottosuolo", "del sottotetto",
|
||||
"del sottotitolo", "del sottovalutare", "del sottovaso", "della sottoveste", "del sottovuoto",
|
||||
"del sottufficiale", "della soubrette", "del souvenir", "del soverchiare", "del sovrano", "del sovrapprezzo",
|
||||
"della sovvenzione", "del sovversivo", "del sozzo", "dello suadente", "del sub", "del subalterno",
|
||||
"del subbuglio", "del subdolo", "del sublime", "del suburbano", "del successore", "del succo",
|
||||
"della succube", "del succulento", "della succursale", "del sudario", "della sudditanza", "del suddito",
|
||||
"del sudicio", "del suffisso", "del suffragio", "del suffumigio", "del suggeritore", "del sughero",
|
||||
"del sugo", "del suino", "della suite", "del sulfureo", "del sultano", "di Steffo", "di Spaggia",
|
||||
"di Sabrina", "del sas", "del ses", "del sis", "del sos", "del sus", "della supremazia", "del Santissimo",
|
||||
"della scatola", "del supercalifragilistichespiralidoso", "del sale", "del salame", "di (Town of) Salem",
|
||||
"di Stronghold", "di SOMA", "dei Saints", "di S.T.A.L.K.E.R.", "di Sanctum", "dei Sims", "di Sid",
|
||||
"delle Skullgirls", "di Sonic", "di Spiral (Knights)", "di Spore", "di Starbound", "di SimCity", "di Sensei",
|
||||
"di Ssssssssssssss... Boom! E' esploso il dizionario", "della scala", "di Sakura", "di Suzie", "di Shinji",
|
||||
"del senpai", "del support", "di Superman"]
|
9
utils/telegramstuff.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
import telegram
|
||||
import strings
|
||||
|
||||
|
||||
def reply_msg(bot: telegram.Bot, chat_id: int, string: str, ignore_escaping=False, disable_web_page_preview=True, **kwargs) -> telegram.Message:
|
||||
string = strings.safely_format_string(string, ignore_escaping=ignore_escaping, words=kwargs)
|
||||
return bot.send_message(chat_id, string,
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=disable_web_page_preview)
|
423
webserver.py
|
@ -1,4 +1,3 @@
|
|||
import secrets
|
||||
from flask import Flask, render_template, request, abort, redirect, url_for, Markup, escape, jsonify
|
||||
from flask import session as fl_session
|
||||
from flask import g as fl_g
|
||||
|
@ -9,10 +8,13 @@ import markdown2
|
|||
import datetime
|
||||
# noinspection PyPackageRequirements
|
||||
import telegram
|
||||
import query_discord_music
|
||||
import random
|
||||
import sql_queries
|
||||
import re
|
||||
import functools
|
||||
import strings
|
||||
from sqlalchemy.orm.collections import InstrumentedList
|
||||
from raven.contrib.flask import Sentry
|
||||
from utils import reply_msg
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
@ -29,9 +31,42 @@ telegram_bot = telegram.Bot(config["Telegram"]["bot_token"])
|
|||
sentry = Sentry(app, dsn=config["Sentry"]["token"])
|
||||
|
||||
|
||||
@app.template_filter()
|
||||
def markdown(text):
|
||||
"""Convert a string to markdown."""
|
||||
converted_md = markdown2.markdown(text.replace("<", "<"),
|
||||
extras=["spoiler", "tables", "smarty-pants", "fenced-code-blocks"])
|
||||
converted_md = re.sub(r"{https?://(?:www\.)?(?:youtube\.com/watch\?.*?&?v=|youtu.be/)([0-9A-Za-z-]+).*?}",
|
||||
r'<div class="youtube-embed">'
|
||||
r' <iframe src="https://www.youtube-nocookie.com/embed/\1?rel=0&showinfo=0"'
|
||||
r' frameborder="0"'
|
||||
r' allow="autoplay; encrypted-media"'
|
||||
r' allowfullscreen'
|
||||
r' width="640px"'
|
||||
r' height="320px">'
|
||||
r' </iframe>'
|
||||
r'</div>', converted_md)
|
||||
converted_md = re.sub(r"{https?://clyp.it/([a-z0-9]+)}",
|
||||
r'<div class="clyp-embed">'
|
||||
r' <iframe width="100%" height="160" src="https://clyp.it/\1/widget" frameborder="0">'
|
||||
r' </iframe>'
|
||||
r'</div>', converted_md)
|
||||
return Markup(converted_md)
|
||||
|
||||
|
||||
def require_login(f):
|
||||
@functools.wraps(f)
|
||||
def func(*args, **kwargs):
|
||||
if not fl_g.user:
|
||||
abort(403)
|
||||
return
|
||||
return f(*args, **kwargs)
|
||||
return func
|
||||
|
||||
|
||||
@app.errorhandler(400)
|
||||
def error_400(_=None):
|
||||
return render_template("400.html", g=fl_g)
|
||||
return render_template("400.html"), 400
|
||||
|
||||
|
||||
@app.route("/400")
|
||||
|
@ -41,7 +76,7 @@ def page_400():
|
|||
|
||||
@app.errorhandler(403)
|
||||
def error_403(_=None):
|
||||
return render_template("403.html", g=fl_g)
|
||||
return render_template("403.html"), 403
|
||||
|
||||
|
||||
@app.route("/403")
|
||||
|
@ -51,7 +86,7 @@ def page_403():
|
|||
|
||||
@app.errorhandler(500)
|
||||
def error_500(_=None):
|
||||
return render_template("500.html", g=fl_g)
|
||||
return render_template("500.html"), 500
|
||||
|
||||
|
||||
@app.route("/500")
|
||||
|
@ -61,64 +96,65 @@ def page_500():
|
|||
|
||||
@app.route("/")
|
||||
def page_main():
|
||||
if not fl_session.get("user_id"):
|
||||
return redirect(url_for("page_login"))
|
||||
db_session = db.Session()
|
||||
royals = db_session.query(db.Royal).order_by(db.Royal.username).all()
|
||||
wiki_pages = db_session.query(db.WikiEntry).order_by(db.WikiEntry.key).all()
|
||||
random_diario = db_session.query(db.Diario).order_by(db.func.random()).first()
|
||||
next_events = db_session.query(db.Event).filter(db.Event.time > datetime.datetime.now()).order_by(
|
||||
royals = fl_g.session.query(db.Royal).order_by(db.Royal.fiorygi.desc()).all()
|
||||
wiki_pages = fl_g.session.query(db.WikiEntry).order_by(db.WikiEntry.key).all()
|
||||
random_diario = fl_g.session.query(db.Diario).order_by(db.func.random()).first()
|
||||
next_events = fl_g.session.query(db.Event).filter(db.Event.time > datetime.datetime.now()).order_by(
|
||||
db.Event.time).all()
|
||||
halloween = db.Halloween.puzzle_status()[1]
|
||||
db_session.close()
|
||||
quests = fl_g.session.query(db.Quest).all()
|
||||
return render_template("main.html", royals=royals, wiki_pages=wiki_pages, entry=random_diario,
|
||||
next_events=next_events, g=fl_g, escape=escape, halloween=enumerate(halloween))
|
||||
events=next_events, escape=escape, quests=quests)
|
||||
|
||||
|
||||
@app.route("/profile/<name>")
|
||||
def page_profile(name: str):
|
||||
db_session = db.Session()
|
||||
user = db_session.query(db.Royal).filter_by(username=name).one_or_none()
|
||||
user = fl_g.session.query(db.Royal).filter_by(username=name).one_or_none()
|
||||
if user is None:
|
||||
db_session.close()
|
||||
abort(404)
|
||||
return
|
||||
css = db_session.query(db.ProfileData).filter_by(royal=user).one_or_none()
|
||||
steam = db_session.query(db.Steam).filter_by(royal=user).one_or_none()
|
||||
osu = db_session.query(db.Osu).filter_by(royal=user).one_or_none()
|
||||
dota = db_session.query(db.Dota).join(db.Steam).filter_by(royal=user).one_or_none()
|
||||
lol = db_session.query(db.LeagueOfLegends).filter_by(royal=user).one_or_none()
|
||||
ow = db_session.query(db.Overwatch).filter_by(royal=user).one_or_none()
|
||||
tg = db_session.query(db.Telegram).filter_by(royal=user).one_or_none()
|
||||
discord = db_session.execute(query_discord_music.one_query, {"royal": user.id}).fetchone()
|
||||
gamelog = db_session.query(db.GameLog).filter_by(royal=user).one_or_none()
|
||||
halloween = db_session.query(db.Halloween).filter_by(royal=user).one_or_none()
|
||||
db_session.close()
|
||||
css = fl_g.session.query(db.ProfileData).filter_by(royal=user).one_or_none()
|
||||
mini_data = []
|
||||
for game in db.mini_list:
|
||||
# TODO: investigate on why instrumentedlists are returned, or minis are not found
|
||||
try:
|
||||
data = game.mini_get_single_from_royal(fl_g.session, user)
|
||||
except Exception:
|
||||
data = None
|
||||
if data is None:
|
||||
continue
|
||||
elif isinstance(data, InstrumentedList):
|
||||
if len(data) == 0:
|
||||
continue
|
||||
mini_data.append({
|
||||
"name": game._mini_name,
|
||||
"data": data[0]
|
||||
})
|
||||
continue
|
||||
mini_data.append({
|
||||
"name": game._mini_name,
|
||||
"data": data
|
||||
})
|
||||
if css is not None:
|
||||
converted_bio = Markup(markdown2.markdown(css.bio.replace("<", "<"),
|
||||
extras=["spoiler", "tables", "smarty-pants", "fenced-code-blocks"]))
|
||||
else:
|
||||
converted_bio = ""
|
||||
return render_template("profile.html", ryg=user, css=css, osu=osu, dota=dota, lol=lol, steam=steam, ow=ow,
|
||||
tg=tg, discord=discord, g=fl_g, bio=converted_bio, gamelog=gamelog,
|
||||
halloween=halloween)
|
||||
return render_template("profile.html", ryg=user, css=css, bio=converted_bio, mini_data=mini_data)
|
||||
|
||||
|
||||
@app.route("/login")
|
||||
def page_login():
|
||||
return render_template("login.html", g=fl_g)
|
||||
return render_template("login.html")
|
||||
|
||||
|
||||
@app.route("/loggedin", methods=["POST"])
|
||||
def page_loggedin():
|
||||
username = request.form.get("username", "")
|
||||
password = request.form.get("password", "")
|
||||
db_session = db.Session()
|
||||
user = db_session.query(db.Royal).filter_by(username=username).one_or_none()
|
||||
db_session.close()
|
||||
user = fl_g.session.query(db.Royal).filter_by(username=username).one_or_none()
|
||||
fl_session.permanent = True
|
||||
if user is None:
|
||||
abort(403)
|
||||
abort(400)
|
||||
return
|
||||
if user.password is None:
|
||||
fl_session["user_id"] = user.id
|
||||
|
@ -128,9 +164,7 @@ def page_loggedin():
|
|||
fl_session["user_id"] = user.id
|
||||
fl_session["username"] = username
|
||||
return redirect(url_for("page_main"))
|
||||
else:
|
||||
abort(403)
|
||||
return
|
||||
return redirect(url_for("page_login"))
|
||||
|
||||
|
||||
@app.route("/logout")
|
||||
|
@ -142,39 +176,27 @@ def page_logout():
|
|||
|
||||
|
||||
@app.route("/password", methods=["GET", "POST"])
|
||||
@require_login
|
||||
def page_password():
|
||||
if not fl_session.get("user_id"):
|
||||
return redirect(url_for("page_login"))
|
||||
user_id = fl_session.get("user_id")
|
||||
if request.method == "GET":
|
||||
if user_id is None:
|
||||
return redirect(url_for("page_login"))
|
||||
return render_template("password.html", g=fl_g)
|
||||
return render_template("password.html")
|
||||
elif request.method == "POST":
|
||||
new_password = request.form.get("new", "")
|
||||
db_session = db.Session()
|
||||
user = db_session.query(db.Royal).filter_by(id=user_id).one()
|
||||
user = fl_g.session.query(db.Royal).filter_by(id=fl_g.user.id).one()
|
||||
if user.password is None:
|
||||
user.password = bcrypt.hashpw(bytes(new_password, encoding="utf8"), bcrypt.gensalt())
|
||||
user.fiorygi += 1
|
||||
db_session.commit()
|
||||
db_session.close()
|
||||
user.password = bcrypt.hashpw(bytes(new_password, encoding="utf8"), bcrypt.gensalt())
|
||||
fl_g.session.commit()
|
||||
return redirect(url_for("page_main"))
|
||||
else:
|
||||
db_session.close()
|
||||
return redirect(url_for("page_login"))
|
||||
|
||||
|
||||
@app.route("/editprofile", methods=["GET", "POST"])
|
||||
@require_login
|
||||
def page_editprofile():
|
||||
user_id = fl_session.get("user_id")
|
||||
if not user_id:
|
||||
return redirect(url_for("page_login"))
|
||||
db_session = db.Session()
|
||||
profile_data = db_session.query(db.ProfileData).filter_by(royal_id=user_id).join(db.Royal).one_or_none()
|
||||
royal = fl_g.session.query(db.Royal).filter_by(id=fl_g.user.id).one()
|
||||
profile_data = fl_g.session.query(db.ProfileData).filter_by(royal=royal).one_or_none()
|
||||
if request.method == "GET":
|
||||
db_session.close()
|
||||
return render_template("profileedit.html", data=profile_data, g=fl_g)
|
||||
return render_template("profileedit.html", royal=royal, data=profile_data)
|
||||
elif request.method == "POST":
|
||||
css = request.form.get("css", "")
|
||||
bio = request.form.get("bio", "")
|
||||
|
@ -182,91 +204,35 @@ def page_editprofile():
|
|||
abort(400)
|
||||
return
|
||||
if profile_data is None:
|
||||
profile_data = db.ProfileData(royal_id=user_id, css=css, bio=bio)
|
||||
db_session.add(profile_data)
|
||||
db_session.flush()
|
||||
profile_data.royal.fiorygi += 1
|
||||
try:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
f'⭐️ {profile_data.royal.username} ha'
|
||||
f' <a href="http://ryg.steffo.eu/editprofile">configurato la sua bio</a>'
|
||||
f' su Royalnet e ha ottenuto un fioryg!',
|
||||
parse_mode="HTML", disable_web_page_preview=True, disable_notification=True)
|
||||
except Exception:
|
||||
pass
|
||||
profile_data = db.ProfileData(royal=royal, css=css, bio=bio)
|
||||
fl_g.session.add(profile_data)
|
||||
fl_g.session.flush()
|
||||
else:
|
||||
profile_data.css = css
|
||||
profile_data.bio = bio
|
||||
db_session.commit()
|
||||
royal = db_session.query(db.Royal).filter_by(id=user_id).one()
|
||||
db_session.close()
|
||||
fl_g.session.commit()
|
||||
return redirect(url_for("page_profile", name=royal.username))
|
||||
|
||||
|
||||
@app.route("/game/<name>")
|
||||
def page_game(name: str):
|
||||
db_session = db.Session()
|
||||
if name == "rl":
|
||||
game_name = "Rocket League"
|
||||
query = db_session.query(db.RocketLeague).join(db.Steam).order_by(db.RocketLeague.solo_std_rank).all()
|
||||
elif name == "dota":
|
||||
game_name = "Dota 2"
|
||||
query = db_session.query(db.Dota).join(db.Steam).order_by(db.Dota.rank_tier.desc().nullslast()).all()
|
||||
elif name == "lol":
|
||||
game_name = "League of Legends"
|
||||
query = db_session.query(db.LeagueOfLegends).order_by(db.LeagueOfLegends.solo_division.desc().nullslast(),
|
||||
db.LeagueOfLegends.solo_rank,
|
||||
db.LeagueOfLegends.flex_division.desc().nullslast(),
|
||||
db.LeagueOfLegends.flex_rank,
|
||||
db.LeagueOfLegends.twtr_division.desc().nullslast(),
|
||||
db.LeagueOfLegends.twtr_rank,
|
||||
db.LeagueOfLegends.level).all()
|
||||
elif name == "osu":
|
||||
game_name = "osu!"
|
||||
query = db_session.query(db.Osu).order_by(db.Osu.mania_pp.desc().nullslast()).all()
|
||||
elif name == "ow":
|
||||
game_name = "Overwatch"
|
||||
query = db_session.query(db.Overwatch).order_by(db.Overwatch.rank.desc().nullslast()).all()
|
||||
elif name == "steam":
|
||||
game_name = "Steam"
|
||||
query = db_session.query(db.Steam).order_by(db.Steam.persona_name).all()
|
||||
elif name == "ryg":
|
||||
game_name = "Royalnet"
|
||||
query = db_session.query(db.Royal).order_by(db.Royal.username).all()
|
||||
elif name == "tg":
|
||||
game_name = "Telegram"
|
||||
query = db_session.query(db.Telegram).order_by(db.Telegram.telegram_id).all()
|
||||
elif name == "discord":
|
||||
game_name = "Discord"
|
||||
query = [dict(row) for row in db_session.execute(query_discord_music.all_query)]
|
||||
elif name == "halloween2018":
|
||||
game_name = "Rituale di Halloween"
|
||||
query = db_session.query(db.Halloween).all()
|
||||
for game in db.mini_list:
|
||||
if game._mini_name == name:
|
||||
query = game.mini_get_all(fl_g.session)
|
||||
break
|
||||
else:
|
||||
abort(404)
|
||||
return
|
||||
db_session.close()
|
||||
return render_template("game.html", minis=query, game_name=game_name, game_short_name=name, g=fl_g)
|
||||
return render_template("game.html", mini_type=game, mini_data=query)
|
||||
|
||||
|
||||
@app.route("/wiki")
|
||||
def page_wikihome():
|
||||
db_session = db.Session()
|
||||
wiki_pages = db_session.query(db.WikiEntry).order_by(db.WikiEntry.key).all()
|
||||
db_session.close()
|
||||
return render_template("wikilist.html", wiki_pages=wiki_pages, g=fl_g)
|
||||
|
||||
|
||||
@app.route("/wiki/<key>", methods=["GET", "POST"])
|
||||
@app.route("/wiki/<key>")
|
||||
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) \
|
||||
wiki_page = fl_g.session.query(db.WikiEntry).filter_by(key=key).one_or_none()
|
||||
wiki_latest_edit = fl_g.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("wikipage.html", key=key, g=fl_g)
|
||||
return render_template("wikipage.html", key=key, wiki_page=None)
|
||||
# Embed YouTube videos
|
||||
converted_md = markdown2.markdown(wiki_page.content.replace("<", "<"),
|
||||
extras=["spoiler", "tables", "smarty-pants", "fenced-code-blocks"])
|
||||
|
@ -286,129 +252,133 @@ def page_wiki(key: str):
|
|||
r' </iframe>'
|
||||
r'</div>', converted_md)
|
||||
return render_template("wikipage.html", key=key, wiki_page=wiki_page, converted_md=Markup(converted_md),
|
||||
wiki_log=wiki_latest_edit, g=fl_g)
|
||||
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()
|
||||
return redirect(url_for("page_login"))
|
||||
wiki_log=wiki_latest_edit)
|
||||
|
||||
|
||||
@app.route("/wiki/<key>/edit", methods=["POST"])
|
||||
@require_login
|
||||
def page_wiki_edit(key: str):
|
||||
wiki_page = fl_g.session.query(db.WikiEntry).filter_by(key=key).one_or_none()
|
||||
if wiki_page is not None and wiki_page.locked:
|
||||
abort(403)
|
||||
return
|
||||
new_content = request.form.get("content")
|
||||
# Create new page
|
||||
if wiki_page is None:
|
||||
difference = len(new_content)
|
||||
wiki_page = db.WikiEntry(key=key, content=new_content)
|
||||
db_session.add(wiki_page)
|
||||
db_session.flush()
|
||||
fl_g.session.add(wiki_page)
|
||||
fl_g.session.flush()
|
||||
# Edit existing page
|
||||
else:
|
||||
difference = len(new_content) - len(wiki_page.content)
|
||||
wiki_page.content = new_content
|
||||
# Award fiorygi
|
||||
if difference > 50:
|
||||
fioryg_chance = -(5000/difference) + 100
|
||||
fioryg_roll = random.randrange(0, 100)
|
||||
if fioryg_roll > fioryg_chance:
|
||||
user.fiorygi += 1
|
||||
if difference > 500:
|
||||
fiorygi = difference // 500
|
||||
fiorygi_word = "fioryg" + ("i" if fiorygi != 1 else "")
|
||||
fl_g.user.fiorygi += fiorygi
|
||||
else:
|
||||
fioryg_chance = -1
|
||||
fioryg_roll = -2
|
||||
fiorygi = 0
|
||||
fiorygi_word = ""
|
||||
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()
|
||||
message = f'ℹ️ La pagina wiki <a href="https://ryg.steffo.eu/wiki/{key}">{key}</a> è stata' \
|
||||
f' modificata da' \
|
||||
f' <a href="https://ryg.steffo.eu/profile/{user.username}">{user.username}</a>' \
|
||||
f' {"(" + edit_reason + ")" if edit_reason else ""}' \
|
||||
f' [{"+" if difference > 0 else ""}{difference}]\n'
|
||||
if fioryg_roll > fioryg_chance:
|
||||
message += f"⭐️ {user.username} è stato premiato con 1 fioryg per la modifica!"
|
||||
new_log = db.WikiLog(editor=fl_g.user, edited_key=key, timestamp=datetime.datetime.now(), reason=edit_reason)
|
||||
fl_g.session.add(new_log)
|
||||
fl_g.session.commit()
|
||||
try:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"], message,
|
||||
parse_mode="HTML", disable_web_page_preview=True, disable_notification=True)
|
||||
reply_msg(telegram_bot, config["Telegram"]["main_group"], strings.WIKI.PAGE_UPDATED,
|
||||
key=key,
|
||||
user=fl_g.user.telegram.mention(),
|
||||
reason=edit_reason,
|
||||
change=f"+{str(difference)}" if difference > 0 else str(difference))
|
||||
if fiorygi > 0:
|
||||
reply_msg(telegram_bot, config["Telegram"]["main_group"], strings.TELEGRAM.FIORYGI_AWARDED,
|
||||
mention=fl_g.user.telegram.mention(),
|
||||
number=fiorygi,
|
||||
fiorygi=fiorygi_word,
|
||||
reason="aver contribuito alla wiki Royal Games")
|
||||
except Exception:
|
||||
pass
|
||||
return redirect(url_for("page_wiki", key=key))
|
||||
|
||||
|
||||
@app.route("/wiki/<key>/lock", methods=["POST"])
|
||||
@require_login
|
||||
def page_wiki_lock(key: str):
|
||||
wiki_page = fl_g.session.query(db.WikiEntry).filter_by(key=key).one_or_none()
|
||||
if wiki_page is None:
|
||||
abort(404)
|
||||
return
|
||||
if fl_g.user.role != "Admin":
|
||||
abort(403)
|
||||
return
|
||||
wiki_page.locked = not wiki_page.locked
|
||||
try:
|
||||
if wiki_page.locked:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
strings.safely_format_string(strings.WIKI.PAGE_LOCKED,
|
||||
words={
|
||||
"key": key,
|
||||
"user": fl_g.user.username
|
||||
}),
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
disable_notification=True)
|
||||
else:
|
||||
telegram_bot.send_message(config["Telegram"]["main_group"],
|
||||
strings.safely_format_string(strings.WIKI.PAGE_UNLOCKED,
|
||||
words={
|
||||
"key": key,
|
||||
"user": fl_g.user.username
|
||||
}),
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
disable_notification=True)
|
||||
except Exception:
|
||||
pass
|
||||
fl_g.session.commit()
|
||||
return redirect(url_for("page_wiki", key=key))
|
||||
|
||||
|
||||
@app.route("/diario")
|
||||
@require_login
|
||||
def page_diario():
|
||||
user_id = fl_session.get("user_id")
|
||||
if not user_id:
|
||||
return redirect(url_for("page_login"))
|
||||
db_session = db.Session()
|
||||
diario_entries = db_session.query(db.Diario).order_by(db.Diario.timestamp.desc()).all()
|
||||
db_session.close()
|
||||
return render_template("diario.html", g=fl_g, entries=diario_entries)
|
||||
diario_entries = fl_g.session.query(db.Diario).order_by(db.Diario.timestamp.desc()).all()
|
||||
return render_template("diario.html", entries=diario_entries)
|
||||
|
||||
|
||||
@app.route("/music")
|
||||
def page_music():
|
||||
db_session = db.Session()
|
||||
songs = db_session.execute(query_discord_music.top_songs)
|
||||
db_session.close()
|
||||
songs = fl_g.session.execute(sql_queries.top_songs)
|
||||
return render_template("topsongs.html", songs=songs)
|
||||
|
||||
|
||||
@app.route("/music/<discord_id>")
|
||||
def page_music_individual(discord_id: str):
|
||||
db_session = db.Session()
|
||||
discord = db_session.query(db.Discord).filter_by(discord_id=discord_id).one_or_none()
|
||||
discord = fl_g.session.query(db.Discord).filter_by(discord_id=discord_id).one_or_none()
|
||||
if discord is None:
|
||||
db_session.close()
|
||||
abort(404)
|
||||
return
|
||||
songs = db_session.execute(query_discord_music.single_top_songs, {"discordid": discord.discord_id})
|
||||
db_session.close()
|
||||
songs = fl_g.session.execute(sql_queries.single_top_songs, {"discordid": discord.discord_id})
|
||||
return render_template("topsongs.html", songs=songs, discord=discord)
|
||||
|
||||
|
||||
@app.route("/activity")
|
||||
def page_activity():
|
||||
db_session = db.Session()
|
||||
reports = list(db_session.query(db.ActivityReport).order_by(db.ActivityReport.timestamp.desc()).limit(192).all())
|
||||
db_session.close()
|
||||
return render_template("activity.html", activityreports=list(reversed(reports)))
|
||||
|
||||
|
||||
@app.route("/api/token")
|
||||
def api_token():
|
||||
username = request.form.get("username", "")
|
||||
password = request.form.get("password", "")
|
||||
db_session = db.Session()
|
||||
user = db_session.query(db.Royal).filter_by(username=username).one_or_none()
|
||||
if user is None:
|
||||
db_session.close()
|
||||
abort(403)
|
||||
return
|
||||
if user.password is None:
|
||||
db_session.close()
|
||||
abort(403)
|
||||
if bcrypt.checkpw(bytes(password, encoding="utf8"), user.password):
|
||||
new_token = db.LoginToken(royal=user, token=secrets.token_urlsafe())
|
||||
db_session.add(new_token)
|
||||
db_session.commit()
|
||||
db_session.close()
|
||||
return jsonify({
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"token": new_token.token
|
||||
})
|
||||
else:
|
||||
abort(403)
|
||||
return
|
||||
|
||||
|
||||
@app.route("/ses/identify")
|
||||
def ses_identify():
|
||||
response = jsonify({
|
||||
"username": fl_session.get("username"),
|
||||
"id": fl_session.get("user_id")
|
||||
})
|
||||
response.headers["Access-Control-Allow-Origin"] = "https://steffo.eu"
|
||||
response.headers["Access-Control-Allow-Credentials"] = "true"
|
||||
return response
|
||||
reports = list(fl_g.session.query(db.ActivityReport).order_by(db.ActivityReport.timestamp.desc()).limit(192).all())
|
||||
hourly_avg = list(fl_g.session.execute(sql_queries.activity_by_hour, {"current_month": datetime.datetime.now().month}))
|
||||
previous_month = datetime.datetime.now().month - 1
|
||||
if previous_month == 0:
|
||||
previous_month = 12
|
||||
hourly_comp = list(fl_g.session.execute(sql_queries.activity_by_hour, {"current_month": previous_month}))
|
||||
even_before_month = previous_month - 1
|
||||
if even_before_month == 0:
|
||||
even_before_month = 12
|
||||
hourly_before = list(fl_g.session.execute(sql_queries.activity_by_hour, {"current_month": even_before_month}))
|
||||
return render_template("activity.html", activityreports=list(reversed(reports)),
|
||||
hourly_avg=hourly_avg,
|
||||
hourly_comp=hourly_comp,
|
||||
hourly_before=hourly_before)
|
||||
|
||||
|
||||
@app.route("/hooks/github", methods=["POST"])
|
||||
|
@ -422,7 +392,13 @@ def hooks_github():
|
|||
abort(400)
|
||||
return
|
||||
# TODO: add secret check
|
||||
message = f"🐙 Nuovi aggiornamenti a Royalnet:\n"
|
||||
if j["ref"] == "refs/heads/master":
|
||||
message = f"🐙 Nuovi aggiornamenti a Royalnet <code>master</code>:\n"
|
||||
elif j["ref"] == "refs/heads/unity":
|
||||
message = f"🐙 Progresso di Royalnet <code>unity</code>:\n"
|
||||
else:
|
||||
return "Ignored."
|
||||
if message:
|
||||
for commit in j.get("commits", []):
|
||||
if commit["distinct"]:
|
||||
message += f'<a href="{commit["url"]}">{commit["message"]}</a>' \
|
||||
|
@ -436,6 +412,17 @@ def hooks_github():
|
|||
def pre_request():
|
||||
fl_g.css = "nryg.less"
|
||||
fl_g.rygconf = config
|
||||
fl_g.session = db.Session()
|
||||
try:
|
||||
fl_g.user = fl_g.session.query(db.Royal).filter_by(id=fl_session["user_id"]).one_or_none()
|
||||
except KeyError:
|
||||
fl_g.user = None
|
||||
|
||||
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
fl_g.session.close()
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|