Skip to content
This repository has been archived by the owner on Sep 30, 2023. It is now read-only.

OK, im so bad at this #3

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8d7aff4
Remove submodules
r33int Nov 27, 2019
5e2c39c
Include submodule common
r33int Nov 27, 2019
c8cf2f1
Add submodule secret
r33int Nov 27, 2019
e1a5507
Nuke discord
r33int Nov 27, 2019
f2be352
Nuke 2FA
r33int Nov 27, 2019
a00caf0
Nuke Buttercake
r33int Nov 27, 2019
397faf6
Rebrand to kawata
r33int Nov 27, 2019
b8f8f05
Remove anticheat features
r33int Nov 27, 2019
dff7c5f
Switch to wifipiano2
r33int Nov 27, 2019
98acea8
Fix derp
r33int Nov 27, 2019
511e24c
Revert "Handle SIGINT and SIGTERM"
r33int Nov 27, 2019
08a6dac
Use old announce method
r33int Nov 27, 2019
acb5fc2
Drop failed replays
r33int Nov 27, 2019
8f9bb24
Limit sql attempts
r33int Nov 27, 2019
05714c5
Ranked relax (◕‿◕)
r33int Nov 29, 2019
9eef201
pp>score for vanilla
Jan 11, 2019
15aed8c
Revert "pp>score for vanilla"
r33int Dec 2, 2019
17ecdcc
Revert "Ranked relax (◕‿◕)"
r33int Dec 2, 2019
9379d35
akatsukis pp over score
KotRikD Sep 6, 2019
9c31972
Revert "akatsukis pp over score"
r33int Dec 2, 2019
38ce3fb
Ranked Relax, again.
Dec 5, 2019
58cf356
PP overwrite
Dec 5, 2019
56c52cb
Oops! There. Fixed them.
Dec 5, 2019
0a5aa31
Merge pull request #1 from Hazuki-san/patch-1
r33int Dec 5, 2019
c56e5bb
Calculate pp
r33int Dec 5, 2019
b7a961e
OOF
Hazuki-san Dec 6, 2019
d23c2f4
Merge pull request #2 from Hazuki-san/patch-2
r33int Dec 6, 2019
e3fa623
Remove autoban on negative score
r33int Dec 9, 2019
3a80bbd
Merge branch 'master' of github.com:kawatapw/lets
r33int Dec 9, 2019
7cce633
test
r33int Dec 9, 2019
8be91a7
Revert "test"
r33int Dec 9, 2019
fd998e0
[TEST] pp leaderboards
r33int Dec 11, 2019
ae95493
pp leaderboards
r33int Dec 11, 2019
c5057f5
Merge branch 'master' of github.com:kawatapw/lets
r33int Jan 1, 2020
6fe74ac
Revert "Ranked Relax, again."
r33int Jan 1, 2020
eeaf80b
Revert "Revert "Ranked Relax, again.""
r33int Jan 12, 2020
9f47485
This is a very bad idea
Hazuki-san Jan 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
[submodule "common"]
path = common
url = https://zxq.co/ripple/ripple-python-common.git
[submodule "secret"]
path = secret
url = [email protected]:ripple/lets-secret.git
[submodule "pp/oppai-ng"]
path = pp/oppai-ng
url = https://github.com/Francesco149/oppai-ng.git
[submodule "pp/maniapp-osu-tools"]
path = pp/maniapp-osu-tools
url = [email protected]:ripple/maniapp-osu-tools.git
branch = calc-no-replay
[submodule "pp/catch_the_pp"]
path = pp/catch_the_pp
url = https://zxq.co/ripple/catch-the-pp.git
[submodule "secret"]
path = secret
url = https://github.com/kawatapw/secret
1 change: 0 additions & 1 deletion common
Submodule common deleted from 3b58af
5 changes: 5 additions & 0 deletions common/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**/build
**/__pycache__
.idea
*.c
*.so
661 changes: 661 additions & 0 deletions common/LICENSE

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## ripple-python-common
Common Python code for Ripple

- Origin: https://zxq.co/ripple/ripple-python-common
- Mirror: https://github.com/osuripple/ripple-python-common

## License
All code in this repository is licensed under the GNU AGPL 3 License.
See the "LICENSE" file for more information
Empty file added common/__init__.py
Empty file.
70 changes: 70 additions & 0 deletions common/agpl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import os
from pathlib import Path

PAGES = (
"""This is a friendly reminder that the GNU AGPL adds an additional clause to
the standard GNU GPL, which is that you MUST distribute the source code for the
software once you publish it on the web.
This is not to be considered professional legal advice. For further
information, refer to the LICENSE file which contains the whole license, or ask
your lawyer. If you did not receive a copy of the LICENSE file with this
software, you can refer to the online version:
https://www.gnu.org/licenses/agpl-3.0.html""",
"""In order to comply with the license, should you have made any modification
to the original copy of the software, which should contain a link to the
source code, however minor it is, you are under the legal obligation to provide
the source code once you publish the software on the Web.
Another obligation is that of stating your changes. This is usually done by
cloning the original git repository of the project and stating your changes
through the creation of commits, which allow us to determine when a specific
change was done.""",
"""Furthermore, all the original clauses of the GNU General Public License
are kept intact, which means you have the obligation to
* Keep the AGPL License, without possibility of sublicensing the software
or making it available under any other more liberal license.
* Keep the copyright notice of the original authors
Failure to do so will result in a request to follow the License, and
repeated violation of the license could result in a legal fight.""",
"""For more information on the FSF and software freedom, refer to:
* What is free software? https://www.gnu.org/philosophy/free-sw.html
* Free Software Is Even More Important Now
https://www.gnu.org/philosophy/free-software-even-more-important.html
* The GNU operating system https://www.gnu.org
* The Free Software Foundation https://www.fsf.org
Thank you for reading this and following our license terms.""",
)


class LicenseError(Exception):
pass


def check_license(namespace, project_name):
license_folder_path = "{}/.config/".format(Path.home())
if not os.path.isdir(license_folder_path):
try:
os.mkdir(license_folder_path, mode=0o755)
except OSError as e:
raise LicenseError("Cannot create .config dir: {}".format(e))
agreed_file_name = "{}/{}_license_agreed".format(license_folder_path, namespace)
if os.path.isfile(agreed_file_name):
return

print(
" {}, and most/all software related to {},\n"
"is licensed under the GNU Affero General Public License.\n".format(project_name, namespace)
)
for page in PAGES:
print(" " * 4 + "\n" + page)
try:
input("\nPress Enter to continue")
except KeyboardInterrupt:
raise LicenseError("License not read. Quitting.")

if input("\nPlease write 'I agree' to accept the terms of the license.\n").lower().strip() != "i agree":
raise LicenseError("License not agreed. Quitting.")

try:
open(agreed_file_name, "a").close()
except IOError as e:
raise LicenseError("Couldn't save read status: {}".format(e))
Empty file added common/constants/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions common/constants/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Contains user actions"""
IDLE = 0
AFK = 1
PLAYING = 2
EDITING = 3
MODDING = 4
MULTIPLAYER = 5
WATCHING = 6
UNKNOWN = 7
TESTING = 8
SUBMITTING = 9
PAUSED = 10
LOBBY = 11
MULTIPLAYING= 12
OSU_DIRECT = 13
NONE = 14
9 changes: 9 additions & 0 deletions common/constants/bcolors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""Console colors"""
PINK = '\033[95m'
BLUE = '\033[94m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
67 changes: 67 additions & 0 deletions common/constants/gameModes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
STD = 0
TAIKO = 1
CTB = 2
MANIA = 3

_MODE_FROM_DB = {
"std": STD,
"taiko": TAIKO,
"ctb": CTB,
"mania": MANIA
}

def getGameModeForDB(gameMode):
"""
Convert a game mode number to string for database table/column

:param gameMode: game mode number
:return: game mode readable string for db
"""

if gameMode == STD:
return "std"
elif gameMode == TAIKO:
return "taiko"
elif gameMode == CTB:
return "ctb"
else:
return "mania"

def getGamemodeFull(gameMode):
"""
Get game mode name from game mode number

:param gameMode: game mode number
:return: game mode readable name
"""
if gameMode == STD:
return "osu!"
elif gameMode == TAIKO:
return "Taiko"
elif gameMode == CTB:
return "Catch The Beat"
else:
return "osu!mania"

def getGameModeForPrinting(gameMode):
"""
Convert a gamemode number to string for showing to a user (e.g. !last)

:param gameMode: gameMode int or variable (ex: gameMode.std)
:return: game mode readable string for a human
"""
if gameMode == STD:
return "osu!"
elif gameMode == TAIKO:
return "Taiko"
elif gameMode == CTB:
return "CatchTheBeat"
else:
return "osu!mania"


def getGameModeFromDB(s):
try:
return _MODE_FROM_DB[s]
except KeyError:
return None
31 changes: 31 additions & 0 deletions common/constants/mods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
NOMOD = 0
NOFAIL = 1
EASY = 2
TOUCHSCREEN = 4
HIDDEN = 8
HARDROCK = 16
SUDDENDEATH = 32
DOUBLETIME = 64
RELAX = 128
HALFTIME = 256
NIGHTCORE = 512
FLASHLIGHT = 1024
AUTOPLAY = 2048
SPUNOUT = 4096
RELAX2 = 8192
PERFECT = 16384
KEY4 = 32768
KEY5 = 65536
KEY6 = 131072
KEY7 = 262144
KEY8 = 524288
KEYMOD = 1015808
FADEIN = 1048576
RANDOM = 2097152
LASTMOD = 4194304
KEY9 = 16777216
KEY10 = 33554432
KEY1 = 67108864
KEY3 = 134217728
KEY2 = 268435456
SCOREV2 = 536870912
23 changes: 23 additions & 0 deletions common/constants/privileges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
USER_PUBLIC = 1
USER_NORMAL = 2 << 0
USER_DONOR = 2 << 1
ADMIN_ACCESS_RAP = 2 << 2
ADMIN_MANAGE_USERS = 2 << 3
ADMIN_BAN_USERS = 2 << 4
ADMIN_SILENCE_USERS = 2 << 5
ADMIN_WIPE_USERS = 2 << 6
ADMIN_MANAGE_BEATMAPS = 2 << 7
ADMIN_MANAGE_SERVERS = 2 << 8
ADMIN_MANAGE_SETTINGS = 2 << 9
ADMIN_MANAGE_BETAKEYS = 2 << 10
ADMIN_MANAGE_REPORTS = 2 << 11
ADMIN_MANAGE_DOCS = 2 << 12
ADMIN_MANAGE_BADGES = 2 << 13
ADMIN_VIEW_RAP_LOGS = 2 << 14
ADMIN_MANAGE_PRIVILEGES = 2 << 15
ADMIN_SEND_ALERTS = 2 << 16
ADMIN_CHAT_MOD = 2 << 17
ADMIN_KICK_USERS = 2 << 18
USER_PENDING_VERIFICATION = 2 << 19
USER_TOURNAMENT_STAFF = 2 << 20
ADMIN_CAKER = 20 << 21
Empty file added common/db/__init__.py
Empty file.
86 changes: 86 additions & 0 deletions common/db/dbConnector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import threading
import time

import pymysql
import pymysql.err

import objects.glob
import common.log.logUtils as log


class db:
def __init__(self, **kwargs):
self.connectionKwargs = kwargs
self.maxAttempts = 30

def connectionFactory(self):
return pymysql.connect(**self.connectionKwargs)

def _execute(self, query, params=None, cb=None):
if params is None:
params = ()
attempts = 0
result = None
lastExc = None
while attempts < self.maxAttempts:
# cur is needed in except (linter complains)
cur = None

# Calling objects.glob.threadScope.db may create a new connection
# and we need to except OperationalErorrs raised by it as well
try:
conn = objects.glob.threadScope.db
cur = conn.cursor(pymysql.cursors.DictCursor)

log.debug("{} ({})".format(query, params))
cur.execute(query, params)
if callable(cb):
result = cb(cur)

# Clear any exception we may have due to previously
# failed attempts to execute the query
lastExc = None
break
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
lastExc = e
log.error(
"MySQL operational/internal error on Thread {} ({}). Trying to recover".format(
threading.get_ident(),
e
)
)

# Close cursor now
try:
cur.close()
except:
pass

if attempts > 10:
break

# Sleep if necessary
if attempts > 0:
time.sleep(1)

# Reset connection (this closes the connection as well)
objects.glob.threadScope.dbClose()
attempts += 1
finally:
# Try to close the cursor (will except if there was a failure)
try:
cur.close()
except:
pass
if lastExc is not None:
raise lastExc
return result

def execute(self, query, params=None):
return self._execute(query=query, params=params, cb=lambda x: x.lastrowid)

def fetch(self, query, params=None):
return self._execute(query=query, params=params, cb=lambda x: x.fetchone())

def fetchAll(self, query, params=None):
return self._execute(query=query, params=params, cb=lambda x: x.fetchall())
Empty file added common/ddog/__init__.py
Empty file.
Loading