1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 18:03:12 +00:00

init - clone from personal Git

This commit is contained in:
wlinator 2023-06-19 10:20:17 -04:00
commit 5bc6e3dca4
25 changed files with 3039 additions and 0 deletions

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
venv/
.idea/
__pycache__/
*.db
.env

339
LICENSE Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

53
data/BlackJackStats.py Normal file
View file

@ -0,0 +1,53 @@
import json
from db import database
class BlackJackStats:
def __init__(self, user_id, is_won, bet, payout, hand_player, hand_dealer):
self.user_id = user_id
self.is_won = is_won
self.bet = bet
self.payout = payout
self.hand_player = json.dumps(hand_player)
self.hand_dealer = json.dumps(hand_dealer)
def push_one(self):
query = """
INSERT INTO stats_bj (user_id, is_won, bet, payout, hand_player, hand_dealer)
VALUES (?, ?, ?, ?, ?, ?)
"""
values = (self.user_id, self.is_won, self.bet, self.payout, self.hand_player, self.hand_dealer)
database.execute_query(query, values)
@staticmethod
def fetch_all():
query = "SELECT * FROM stats_bj"
rows = database.select_query(query)
stats_list = []
for row in rows:
# extract individual columns from the row
id, user_id, is_won, bet, payout, hand_player_json, hand_dealer_json = row
# convert hands from JSON strings to lists
hand_player = json.loads(hand_player_json)
hand_dealer = json.loads(hand_dealer_json)
# assign to dictionary
stats_data = {
'id': id,
'user_id': user_id,
'is_won': bool(is_won),
'bet': bet,
'payout': payout,
'hand_player': hand_player,
'hand_dealer': hand_dealer
}
# add the row to the list
stats_list.append(stats_data)
return stats_list

47
data/Currency.py Normal file
View file

@ -0,0 +1,47 @@
from db import database
class Currency:
@staticmethod
def get_cash_balance(user_id):
query = "SELECT cash_balance FROM currency WHERE user_id={}".format(user_id)
cash_balance = database.select_query(query)
if not cash_balance:
Currency.create_new_balance(user_id)
return 50
return cash_balance[0][0]
@staticmethod
def get_special_balance(user_id):
query = "SELECT special_balance FROM currency WHERE user_id={}".format(user_id)
special_balance = database.select_query(query)
if not special_balance:
Currency.create_new_balance(user_id)
return 3
return special_balance[0][0]
@staticmethod
def update_cash_balance(user_id, amount):
if amount < 0:
amount = 0
query = "UPDATE currency SET cash_balance = {} WHERE user_id = {}".format(round(amount, 2), user_id)
database.execute_query(query)
@staticmethod
def update_special_balance(user_id, amount):
if amount < 0:
amount = 0
query = "UPDATE currency SET special_balance = {} WHERE user_id = {}".format(amount, user_id)
database.execute_query(query)
@staticmethod
def create_new_balance(user_id):
query = "INSERT INTO currency(user_id, cash_balance, special_balance) VALUES ({}, 50, 3)".format(user_id)
database.execute_query(query)
print(f"BALANCE UPDATE --- USER with ID {user_id} created new balance")

46
data/Dailies.py Normal file
View file

@ -0,0 +1,46 @@
import json
import time
from db import database
with open("json/economy.json") as file:
json_data = json.load(file)
class Dailies:
def __init__(self, user_id, claimed_at, next_available):
self.user_id = user_id
self.amount = json_data["daily_reward"]
self.claimed_at = claimed_at
self.next_available = next_available
def push(self):
query = """
INSERT INTO dailies (user_id, amount, claimed_at, next_available)
VALUES (?, ?, ?, ?)
"""
values = (self.user_id, self.amount, self.claimed_at, self.next_available)
database.execute_query(query, values)
@staticmethod
def cooldown_check(user_id):
query = """
SELECT next_available
FROM dailies
WHERE id = (
SELECT MAX(id)
FROM dailies
WHERE user_id = ?
)
"""
values = (user_id,)
result = database.select_query_one(query, values)
current_time = time.time()
if result and current_time < result:
return False, result
return True, result

23
data/SlotsStats.py Normal file
View file

@ -0,0 +1,23 @@
import json
from db import database
class SlotsStats:
def __init__(self, user_id, is_won, bet, payout, spin_type, icons):
self.user_id = user_id
self.is_won = is_won
self.bet = bet
self.payout = payout
self.spin_type = spin_type
self.icons = json.dumps(icons)
def push_one(self):
query = """
INSERT INTO stats_slots (user_id, is_won, bet, payout, spin_type, icons)
VALUES (?, ?, ?, ?, ?, ?)
"""
values = (self.user_id, self.is_won, self.bet, self.payout, self.spin_type, self.icons)
database.execute_query(query, values)

125
data/Xp.py Normal file
View file

@ -0,0 +1,125 @@
import os
import random
import time
from dotenv import load_dotenv
from db import database
from sb_tools import xp_functions
load_dotenv('.env')
class Xp:
@staticmethod
def get_user_xp_data(user_id):
query = "SELECT user_xp, user_level, cooldown FROM xp WHERE user_id = {}".format(user_id)
data = database.select_query(query)
if data:
return data
else:
Xp.create_new_user_xp(user_id)
return [(3, 0, time.time())]
@staticmethod
def update_user_xp(user_id, new_xp, new_level, new_cooldown):
query = "UPDATE xp SET user_xp = {}, user_level = {}, cooldown = {} WHERE user_id = {}" \
.format(new_xp, new_level, new_cooldown, user_id)
database.execute_query(query)
@staticmethod
def create_new_user_xp(user_id):
query = "INSERT INTO xp(user_id, user_xp, user_level, cooldown) VALUES ({}, 3, 0, {})".format(user_id,
time.time())
database.execute_query(query)
print(f"XP UPDATE --- USER with ID {user_id} started leveling (db_lvl_null)")
@staticmethod
def calculate_rank(user_id):
query = "SELECT user_id, user_xp, user_level FROM xp ORDER BY user_level DESC, user_xp DESC"
data = database.select_query(query)
leaderboard = []
rank = 1
for row in data:
row_user_id = row[0]
user_xp = row[1]
user_level = row[2]
leaderboard.append((row_user_id, user_xp, user_level, rank))
rank += 1
user_rank = None
for entry in leaderboard:
if entry[0] == user_id:
user_rank = entry[3]
break
return user_rank
@staticmethod
async def assign_level_role(user, level):
level_roles = {
"level_5": 1118491431036792922,
"level_10": 1118491486259003403,
"level_15": 1118491512536301570,
"level_20": 1118491532111126578,
"level_25": 1118491554005393458,
"level_30": 1118491572770713710,
"level_35": 1118491596820840492,
"level_40": 1118491622045405287,
"level_45": 1118491650721853500,
"level_50": 1118491681004732466,
# Add more level roles as needed
}
guild = user.guild
current_level_role = None
new_level_role_id = level_roles.get(f"level_{level}")
for role in user.roles:
if role.id in level_roles.values() and role.id != new_level_role_id:
current_level_role = role
break
new_level_role = guild.get_role(new_level_role_id)
await user.add_roles(new_level_role)
if current_level_role:
await user.remove_roles(current_level_role)
return new_level_role_id
@staticmethod
def generate_progress_bar(current_value, target_value, bar_length=10):
progress = current_value / target_value
filled_length = int(bar_length * progress)
empty_length = bar_length - filled_length
bar = "" * filled_length + "" * empty_length
return f"`{bar}` {current_value}/{target_value}"
@staticmethod
def load_leaderboard():
query = "SELECT user_id, user_xp, user_level FROM xp ORDER BY user_level DESC, user_xp DESC"
data = database.select_query(query)
leaderboard = []
rank = 1
for row in data:
row_user_id = row[0]
user_xp = row[1]
user_level = row[2]
needed_xp_for_next_level = xp_functions.xp_needed_for_next_level(user_level)
leaderboard.append((row_user_id, user_xp, user_level, rank, needed_xp_for_next_level))
rank += 1
return leaderboard
@staticmethod
def load_gain_data():
xp_gain = list(map(int, os.getenv("XP_GAIN").split(",")))
cooldown = list(map(int, os.getenv("COOLDOWN").split(",")))
return random.choice(xp_gain), random.choice(cooldown)

61
db/database.py Normal file
View file

@ -0,0 +1,61 @@
import sqlite3
from sqlite3 import Error
def create_connection():
try:
conn = sqlite3.connect("db/rcu.db")
except Error as e:
print("'create_connection()' Error occurred: {}".format(e))
return
return conn
def execute_query(query, values=None):
conn = create_connection()
cursor = conn.cursor()
try:
if values:
cursor.execute(query, values)
else:
cursor.execute(query)
conn.commit()
except Error as e:
print("'execute_query()' Error occurred: {}".format(e))
return cursor
def select_query(query, values=None):
conn = create_connection()
cursor = conn.cursor()
try:
if values:
return cursor.execute(query, values).fetchall()
else:
return cursor.execute(query).fetchall()
except Error as e:
return f"ERROR: {e}"
def select_query_one(query, values=None):
conn = create_connection()
cursor = conn.cursor()
try:
if values:
output = cursor.execute(query, values).fetchone()
else:
output = cursor.execute(query).fetchone()
if output:
return output[0]
return None
except Error as e:
return f"ERROR: {e}"

72
db/tables.py Normal file
View file

@ -0,0 +1,72 @@
from db import database
xp_table = """
CREATE TABLE IF NOT EXISTS xp (
user_id INTEGER PRIMARY KEY NOT NULL,
user_xp INTEGER NOT NULL,
user_level INTEGER NOT NULL,
cooldown REAL
)
"""
currency_table = """
CREATE TABLE IF NOT EXISTS currency (
user_id INTEGER PRIMARY KEY NOT NULL,
cash_balance INTEGER NOT NULL,
special_balance INTEGER
)
"""
dailies_table = """
CREATE TABLE IF NOT EXISTS dailies (
id INTEGER PRIMARY KEY,
user_id INTEGER,
amount INTEGER,
claimed_at REAL,
next_available REAL
)
"""
stats_bj = """
CREATE TABLE IF NOT EXISTS stats_bj (
id INTEGER PRIMARY KEY,
user_id INTEGER,
is_won INTEGER,
bet INTEGER,
payout INTEGER,
hand_player TEXT,
hand_dealer TEXT
)
"""
stats_slots = """
CREATE TABLE IF NOT EXISTS stats_slots (
id INTEGER PRIMARY KEY,
user_id INTEGER,
is_won INTEGER,
bet INTEGER,
payout INTEGER,
spin_type TEXT,
icons TEXT
)
"""
stats_duel = """
CREATE TABLE IF NOT EXISTS stats_duel (
id INTEGER PRIMARY KEY,
user_id INTEGER,
is_won INTEGER,
bet INTEGER
)
"""
def sync_database():
database.execute_query(xp_table)
database.execute_query(currency_table)
database.execute_query(dailies_table)
database.execute_query(stats_bj)
database.execute_query(stats_slots)
database.execute_query(stats_duel)
print("On startup: database synced.")

213
json/economy.json Normal file
View file

@ -0,0 +1,213 @@
{
"emotes_guild_id": 1038051105642401812,
"rc_guild_id": 719227135151046699,
"daily_reward": 50,
"daily_cooldown": 86400,
"blackjack": {
"emotes": {
"hit_id": 1119262723285467156,
"stand_id": 1118923298298929154
},
"reward_multiplier": 1,
"deck_suits": [
"♠",
"♡",
"♢",
"♣"
],
"deck_ranks": [
"A",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J",
"Q",
"K"
]
},
"slots": {
"emotes": {
"slots_animated_id": 1119262805309259776,
"slots_0_id": 1119262803816095825,
"slots_1_id": 1119262801261760592,
"slots_2_id": 1119262800049614939,
"slots_3_id": 1119262796497039510,
"slots_4_id": 1119262794676715681,
"slots_5_id": 1119262792386621555,
"slots_6_id": 1119262791061229669,
"S_Wide": 1119286730302955651,
"L_Wide": 1119286763802857533,
"O_Wide": 1119286787169329203,
"T_Wide": 1119286804634406942,
"CBorderBLeft": 1119286973572595712,
"CBorderBRight": 1119286918459445408,
"CBorderTLeft": 1119287006464331806,
"CBorderTRight": 1119286865284051035,
"HBorderB": 1119286936155213835,
"HBorderT": 1119287027662344322,
"VBorder": 1119286889854279680,
"WSmall": 1119288536282173490,
"ISmall": 1119288552673517608,
"NSmall": 1119288579382857830,
"LCentered": 1119287296127156325,
"OCentered": 1119287563245584394,
"SCentered": 1119287327588634647,
"ECentered": 1119287343833165945,
"Blank": 1119287267001905283,
"lost": 1119288454212243607
},
"reward_multipliers": {
"pair": 1,
"three_of_a_kind": 3,
"three_diamonds": 4,
"jackpot": 5
}
},
"duel": {
"combat_messages": [
"{} unleashes a devastating tickle attack on {}, leaving them laughing uncontrollably and unable to fight back.",
"{} defeats {} with a cunning move called 'The Poultry Surprise,' involving a rubber chicken and a confetti cannon.",
"With a perfectly timed banana peel maneuver, {} sends {} slipping and sliding out of the arena, much to everyone's amusement.",
"{} pulls off an impressive dance-off against {}, leaving them stunned and distracted long enough to claim victory.",
"{} defeats {} by telling them an incredibly cheesy joke, causing them to burst into laughter and surrender.",
"In a bizarre turn of events, {} manages to defeat {} by challenging them to a thumb wrestling match, and coming out on top.",
"{} defeats {} using a comically oversized foam finger, dramatically poking them into submission.",
"{} wins the fight against {} by offering them a plate of freshly baked cookies, distracting them with deliciousness.",
"With a cunning strategy involving whoopee cushions and fake snakes, {} manages to startle {} into submission.",
"{} defeats {} by challenging them to a game of rock-paper-scissors and successfully predicting their every move.",
"In an unexpected twist, {} defeats {} by challenging them to a dance battle, showing off some surprisingly smooth moves.",
"{} emerges victorious by launching a barrage of rubber duckies at {}, overwhelming them with adorable and distracting quacks.",
"With a well-timed 'knock-knock' joke, {} manages to catch {} off guard, leaving them vulnerable and defeated.",
"{} defeats {} by using an inflatable sumo suit, bouncing them right out of the arena in a hilarious spectacle.",
"In a truly peculiar turn of events, {} defeats {} by engaging them in an intense thumb war and emerging as the undisputed champion.",
"{} wins the fight against {} by tickling them mercilessly, reducing them to a fit of giggles and surrender.",
"With a strategically placed whoopee cushion, {} manages to surprise and defeat {} in the most hilarious way possible.",
"{} defeats {} by unleashing a swarm of rubber chickens, causing chaos and uncontrollable laughter in the arena.",
"In a battle of wits, {} manages to outwit {} by challenging them to a game of 'Rock, Paper, Scissors, Lizard, Spock' and claiming victory.",
"{} emerges victorious against {} by skillfully executing the legendary 'Chicken Dance of Doom,' rendering their opponent speechless.",
"{} defeats {} by employing an unexpected strategy involving a squirting flower, leaving their opponent bewildered and soaked.",
"With a masterful display of slapstick comedy, {} manages to trip up {} and claim a hilarious victory.",
"{} wins the fight against {} by cunningly distracting them with an impromptu magic trick, leaving them spellbound and defeated.",
"In an epic showdown, {} defeats {} by challenging them to a contest of dad jokes, causing their opponent to surrender out of sheer comedic defeat.",
"{} emerges as the victor by engaging {} in a fierce battle of puns, leaving their opponent groaning and conceding defeat.",
"{} defeats {} with a perfectly timed 'banana peel slip' maneuver, turning the fight into a sidesplitting comedy act.",
"With an arsenal of whoopee cushions and squirting flowers, {} manages to defeat {} in a battle that can only be described as 'clownish'.",
"{} claims a comical victory against {} by using a rubber chicken as a formidable weapon, leaving their opponent in stitches.",
"In a hilarious turn of events, {} defeats {} by engaging them in a fierce tickle fight, reducing their opponent to fits of laughter and surrender.",
"{} emerges triumphant by employing an unexpected weapon—silly string—to disarm and defeat {} in a messy but amusing battle.",
"{} obliterates {} with a deadly barrage of pillow fluff, demonstrating the true power of softness.",
"{} achieves victory by strategically deploying an army of rubber ducks, overwhelming {} with cuteness.",
"In a stunning turn of events, {} wins the fight against {} by convincing them that the floor is lava.",
"{} emerges victorious after an intense dance-off, proving that their killer moves are not to be underestimated.",
"With a swift and devastating attack of dad jokes, {} renders {} defenseless with laughter and takes the win.",
"{} successfully hypnotizes {} with their mesmerizing disco dance moves, leaving their opponent dazed and confused.",
"In a battle of wits, {} defeats {} by challenging them to a game of 'Guess the Number' and revealing the meaning of life as the answer.",
"{} outsmarts {} by unleashing an army of mischievous squirrels, distracting their opponent and securing an unconventional victory.",
"With an expertly executed paper airplane assault, {} effortlessly subdues {} and claims the title of Paper Airplane Champion.",
"{} triumphs over {} by unleashing a barrage of terrible puns, effectively disarming their opponent's will to fight.",
"In a display of sheer absurdity, {} emerges victorious by defeating {} with an inflatable rubber chicken as their weapon of choice.",
"{} wins the fight against {} by summoning an army of invisible ninjas, leaving their opponent bewildered and defeated.",
"With a well-timed prank involving a whoopee cushion, {} takes the fight out of {} and secures an uproarious victory.",
"{} utilizes the power of bad breath to defeat {} in a battle of close-quarters combat, leaving their opponent gasping for fresh air.",
"{} emerges triumphant by utilizing the ancient technique of tickling, reducing {} to a giggling mess and claiming the win.",
"In an astonishing display of ridiculousness, {} defeats {} by transforming into a human burrito, effectively immobilizing their opponent.",
"{} takes the fight to a whole new level by challenging {} to a game of 'Rock, Paper, Scissors, Lizard, Spock, Dynamite,' and detonating their way to victory.",
"By harnessing the uncontrollable forces of chaos and mayhem, {} emerges as the reigning champion, leaving {} wondering what just happened.",
"{} obliterates {} with the fearsome weapon of 'Sarcasm Strike,' cutting their opponent down with devastatingly witty remarks.",
"In a battle that defies all logic, {} manages to defeat {} with a strategically timed 'facepalm' attack, leaving their opponent bewildered and defeated.",
"{} emerges victorious by channeling the power of sheer silliness, leaving {} wondering if they accidentally stepped into a clown convention.",
"With a triumphant mic drop and a sly grin, {} outshines {} in a battle of one-liners, proving that words can be as deadly as fists.",
"{} claims victory over {} by using an unexpected weapon—a rubber chicken armed with laser eyes—which proved too much for their opponent to handle.",
"In an act of pure audacity, {} defeats {} by unleashing an unstoppable barrage of dad jokes, leaving their opponent both defeated and embarrassed.",
"{} emerges triumphant by launching a relentless assault of puns, leaving {} defenseless against the power of linguistic wit.",
"{} achieves a comical victory over {} by outmaneuvering them with a surprising breakdance routine, leaving their opponent in awe and confusion.",
"By transforming the battlefield into a whimsical playground, {} manages to disarm and defeat {} with a joyful and mischievous spirit.",
"{} emerges as the victor by invoking the ancient art of slapstick comedy, reducing {} to uncontrollable fits of laughter and surrender.",
"{} triumphs over {} by launching a surprise attack with a barrage of rubber chickens.",
"{} defeats {} using the power of interpretive dance, leaving their opponent bewildered and slightly confused.",
"With a single eyebrow raise, {} disarms and defeats {} in a battle of snarky one-liners.",
"{} emerges victorious by unleashing an army of ferocious kittens armed with laser pointers against {}.",
"In an epic display of butter-fingered combat skills, {} accidentally defeats {} with an unexpected banana peel slip.",
"By engaging {} in a heated debate about the best flavor of ice cream, {} successfully distracts their opponent and secures the win.",
"{} claims victory over {} through the ingenious tactic of challenging them to a thumb war and emerging as the thumb wrestling champion.",
"With a well-timed 'YOLO' battle cry, {} surprises and defeats {} in the most unconventional manner possible.",
"{} outwits {} by reciting an endless stream of cheesy pickup lines, leaving their opponent both amused and defeated.",
"By executing a perfectly synchronized dance routine, {} dazzles and confuses {} into submission.",
"{} secures a hilarious win against {} by challenging them to a game of 'Rock, Paper, Scissors, Lizard, Spock' and emerging as the undisputed champion.",
"With a crafty move straight out of a Looney Tunes cartoon, {} outmaneuvers and outwits {} to claim victory.",
"By releasing a swarm of mischievous squirrels armed with water balloons, {} leaves {} soaked and defeated in the most hilarious way possible.",
"{} emerges triumphant by employing the ancient martial art of 'Tickle Fu,' rendering {} defenseless with uncontrollable laughter.",
"{} defeats {} using the power of bad breath and a strategically timed exhale, leaving their opponent breathless and defeated.",
"With a well-timed 'dad joke' assault, {} leaves {} rolling their eyes and unable to recover from the hilarity.",
"{} claims victory over {} by unleashing a pack of mischievous clowns armed with whoopee cushions and squirting flowers.",
"By strategically summoning a swarm of angry bees, {} overwhelms and defeats {} in a buzzing spectacle.",
"In an unexpected twist, {} defeats {} by challenging them to a game of 'Rock, Paper, Scissors' and emerging as the reigning champion.",
"With the power of their outrageous fashion sense, {} distracts and confuses {} into defeat.",
"{} emerges victorious by reciting an incredibly long and nonsensical tongue twister, leaving {} tongue-tied and defeated.",
"By engaging in a heated dance battle, {} grooves their way to victory, leaving {} in awe of their dance-floor prowess.",
"{} claims victory over {} by employing the ancient art of 'Sarcastic-Fu,' leaving their opponent at a loss for words.",
"With a perfectly timed 'facepalm' maneuver, {} disorients and defeats {} in the most hilarious fashion possible.",
"{} emerges triumphant by engaging {} in an intense game of 'Rock, Paper, Scissors, Lizard, Spock,' with the universe on the line.",
"By transforming into a human tornado of chaos and confusion, {} overwhelms and defeats {} in a whirlwind of hilarity.",
"{} secures a hilarious win over {} by challenging them to a game of 'Tic-Tac-Toe' and emerging as the ultimate champion.",
"With a cleverly executed 'boop' to the nose, {} renders {} momentarily stunned and unable to continue the fight.",
"{} claims victory over {} by unleashing their secret weapon: an unstoppable army of dancing flamingos.",
"By reciting a never-ending series of puns, {} leaves {} in stitches and secures a comedic victory.",
"{} emerges triumphant by unleashing an army of overly affectionate puppies, distracting and defeating {} with cuteness overload.",
"With the power of an awkward silence, {} disarms and defeats {} in a battle of uncomfortable social encounters.",
"{} claims victory over {} by summoning a torrential downpour of confetti, leaving their opponent both bewildered and sparkly.",
"By unleashing a relentless barrage of 'Yo Mama' jokes, {} overwhelms and defeats {} in a duel of comedic insults.",
"{} secures a hilarious win over {} by challenging them to a 'dance-off' and showcasing an unimaginable array of bizarre dance moves.",
"With the cunning strategy of 'reverse psychology,' {} convinces {} to defeat themselves, leaving them utterly perplexed and defeated.",
"{} emerges victorious by summoning a legion of clumsy penguins, who inadvertently trip up {} and secure the win in the most amusing fashion.",
"By harnessing the power of awkwardly timed laughter, {} confuses and defeats {} in a battle that can only be described as 'laugh-out-loud' funny.",
"{} claims victory over {} by employing an army of mischievous squirrels armed with acorns, leaving their opponent both annoyed and defeated.",
"With the precision of a somersaulting unicorn, {} outmaneuvers and defeats {} in a display of mythical combat prowess.",
"{} secures a hilarious win over {} by engaging them in an epic dance-off and showcasing a series of wildly questionable dance moves.",
"By unleashing a squad of highly trained rubber ducks, {} leaves {} splashing in defeat and quacking with laughter.",
"{} emerges triumphant by employing the power of 'awkward silence,' rendering {} unable to continue the fight due to extreme discomfort.",
"With a well-timed 'mic drop' moment, {} leaves {} speechless and defeated in a battle of epic comebacks.",
"{} claims victory over {} by skillfully executing a perfectly timed 'knock-knock' joke, leaving their opponent both entertained and defeated.",
"By employing an army of ticklish feathers, {} reduces {} to helpless laughter and claims a comical victory.",
"With a brilliantly executed 'banana slip' maneuver, {} sends {} tumbling into defeat in the most slapstick way possible.",
"{} secures a hilarious win over {} by engaging them in a rap battle and delivering an unexpected, mind-blowing performance.",
"By summoning a cloud of uncontrollable giggles, {} overwhelms and defeats {} in a battle of infectious laughter.",
"{} emerges triumphant by deploying a squad of ninja squirrels armed with whoopee cushions, leaving {} both startled and defeated.",
"With the power of their unstoppable dance moves, {} outshines and defeats {} in a battle of toe-tapping proportions.",
"{} claims victory over {} by utilizing the art of 'face-swap,' rendering their opponent disoriented and hilariously confused.",
"By launching an arsenal of marshmallows and pillow feathers, {} successfully overwhelms and defeats {} in a fluffy spectacle of victory.",
"{} secures a hilarious win over {} by challenging them to a battle of 'Dad Jokes' and delivering the ultimate punchline.",
"With the stealth of a tiptoeing hippo, {} sneaks up on {} and claims a surprise victory in the most unexpected manner.",
"By summoning a stampede of clumsy llamas, {} causes chaos and laughter, ultimately defeating {} in a riotous spectacle.",
"{} obliterates {} with the power of a thousand bad hair days, leaving their opponent in a state of follicular defeat.",
"By utilizing the ancient technique of 'tickle-fu,' {} reduces {} to a giggling mess and claims a hilarious victory.",
"{} emerges victorious by channeling the energy of a hyperactive squirrel, outmaneuvering and confusing {} at every turn.",
"With the precision of a ninja clown, {} delivers a flurry of hilarious pranks, leaving {} both entertained and defeated.",
"{} claims victory over {} by unleashing a barrage of terrible puns, rendering their opponent unable to continue due to excessive eye-rolling.",
"By summoning a legion of malfunctioning whoopee cushions, {} turns the battle into a symphony of laughter and defeats {} with comedic flair.",
"{} secures a humorous win over {} by challenging them to a 'dad joke' showdown and delivering the ultimate punchline that leaves their opponent groaning.",
"With the grace of a clumsy flamingo, {} stumbles upon victory, leaving {} bewildered and wondering how they managed to lose.",
"{} emerges triumphant by using the power of 'awkward small talk,' leaving {} cringing and defeated in a battle of uncomfortable conversations.",
"By deploying a squad of mischievous rubber chickens, {} creates a cacophony of laughter and distractions, securing a comical victory over {}.",
"{} claims victory over {} by transforming into a human whoopee cushion, causing uncontrollable laughter and sealing their triumph in a most absurd manner.",
"With the impeccable timing of a comedic genius, {} delivers a devastating one-liner that leaves {} in stitches and clinches the win with style.",
"{} secures a comical win over {} by using their unparalleled expertise in interpretive dance, leaving their opponent bewildered and tapping out in laughter.",
"By unleashing a swarm of ticklish kittens, {} reduces {} to a state of uncontrollable laughter and claims a hilarious victory in the most adorable fashion.",
"With the strategic deployment of banana peels, whoopee cushions, and a giant foam finger, {} orchestrates a slapstick symphony that leaves {} defeated and the audience in stitches.",
"{} emerges triumphant by harnessing the power of 'dad jokes' to induce groans and eye-rolls in {}, ultimately causing their opponent's defeat through sheer cringeworthiness.",
"By employing an arsenal of whoopee cushions, squirting flowers, and oversized novelty glasses, {} overwhelms {} with a spectacle of slapstick comedy, securing an uproarious victory.",
"{} claims victory over {} by transforming into the ultimate embodiment of awkwardness, rendering their opponent speechless and awkwardly defeated in a battle of uncomfortable social encounters.",
"With the stealth and finesse of a comedic ninja, {} uses pranks and puns to outwit and outmaneuver {}, leaving their opponent laughing too hard to continue the fight.",
"{} secures a hilarious win over {} by challenging them to a 'dance-off' and showcasing a repertoire of comically bizarre dance moves that leave their opponent in fits of laughter.",
"By wielding the power of sarcasm and witty comebacks, {} verbally outduels and defeats {}, leaving their opponent dumbfounded and unable to match their comedic prowess.",
"{} emerges triumphant by unleashing a barrage of 'knock-knock' jokes that reduce {} to a state of uncontrollable laughter, ultimately securing a whimsically victorious outcome.",
"With the cunning strategy of 'reverse psychology' and a well-timed comedic twist, {} convinces {} to defeat themselves, leaving their opponent both baffled and ironically defeated."
]
}
}

48
main.py Normal file
View file

@ -0,0 +1,48 @@
""" .ENV TEMPLATE
TOKEN=
OWNER_ID=
XP_GAIN=
COOLDOWN=
CASH_BALANCE_NAME=
SPECIAL_BALANCE_NAME=
"""
import logging
import os
import discord
from discord.ext import commands
from dotenv import load_dotenv
import db.tables
import sb_tools.resources
logging.basicConfig(level=logging.INFO)
load_dotenv('.env')
sbbot = discord.Bot(
owner_id=os.getenv('OWNER_ID'),
intents=discord.Intents.all(),
activity=discord.Game(f"v{sb_tools.resources.__version__}"),
status=discord.Status.do_not_disturb
)
@sbbot.event
async def on_ready():
# wait until the bot is ready
# then sync the sqlite3 database
db.tables.sync_database()
"""
https://docs.pycord.dev/en/stable/api/events.html#discord.on_ready
This function isn't guaranteed to only be called once.
Event is called when RESUME request fails.
"""
for filename in os.listdir('./modules'):
if filename.endswith('.py'):
sbbot.load_extension(f'modules.{filename[:-3]}')
sbbot.run(os.getenv('TOKEN'))

389
modules/basic.py Normal file
View file

@ -0,0 +1,389 @@
import asyncio
import discord
from discord.ext import commands
from sb_tools import interaction, embeds, universal
class Basic(commands.Cog):
def __init__(self, sbbot):
self.bot = sbbot
@commands.slash_command(
name="ping",
description="Show the bot's latency."
)
@commands.check(universal.channel_check)
async def ping(self, ctx):
await ctx.respond(f"SB latency: {round(self.bot.latency * 1000, 2)} ms")
@commands.slash_command(
name="intro",
guild_only=False,
description="This command can only be done in DMs."
)
@commands.dm_only()
async def intro(self, ctx):
guild_id = 719227135151046699
channel_id = 973619250507972618
muted_role_id = 754895743151505489
nickname = None
age = None
location = None
pronouns = None
likes = None
dislikes = None
languages = None
sexuality = None
relationship_status = None
extra = None
guild = self.bot.get_guild(guild_id)
member = await guild.fetch_member(ctx.author.id)
if member and discord.utils.get(member.roles, id=muted_role_id):
em = discord.Embed(description="You're muted in the Rave Cave. You can't perform this command.",
color=0xadcca6)
await ctx.respond(embed=em)
return
elif member and not discord.utils.get(member.roles, id=719995790319157279):
em = discord.Embed(description="It seems that you don't have permission to do that!")
await ctx.respond(embed=em)
return
embed = discord.Embed(color=0xadcca6,
title=f"Hey {ctx.author.name}!",
description=f"This command will serve as a questionnaire "
f"for your entry to <#{channel_id}>. Please keep your answers \"PG-13.\"")
embed.add_field(name="Short intro", value="Click the blue button to use the short form, this one has "
"__6 questions__, which is filled out promptly & contains the "
"most important elements needed to briefly describe you.")
embed.add_field(name="Extended intro", value="Click the green button to fill out an extended form with "
"__10 questions__ (including an \"extras\" field where you "
"can unleash your creativity), this one takes a bit longer "
"to fill out but gives a more detailed portrayal of you.")
embed.set_footer(text="Please don't abuse this command.")
embed.set_thumbnail(url="https://cdn.discordapp.com/icons/719227135151046699/49df8c284382af9dbcfd629c8eadc52c"
".webp?size=96")
view = interaction.IntroButtons(ctx)
await ctx.respond(embed=embed, view=view)
await view.wait()
def check(message):
return message.author == ctx.author and isinstance(message.channel, discord.DMChannel)
if view.clickedShort:
# START NICKNAME
await ctx.send(embed=embeds.simple_question_first("How would you like to be identified in the server?"))
try:
nickname_message = await self.bot.wait_for('message', check=check, timeout=120)
nickname = nickname_message.content
if len(nickname) > 100:
nickname = nickname[:100]
nickname = nickname.replace("\n", " ")
print(f"New form info for {ctx.author.name}: nickname {nickname}")
# START AGE
await ctx.send(embed=embeds.simple_question_5("How old are you?"),
content=f"Recorded answer: {nickname}")
try:
age_message = await self.bot.wait_for('message', check=check, timeout=120)
age = age_message.content
if len(age) > 5:
age = age[:5]
age = age.replace("\n", " ")
print(f"New form info for {ctx.author.name}: age {age}")
# START LOCATION
view = interaction.LocationOptions(ctx)
await ctx.send(embed=embeds.simple_question_none("Where do you live?"),
view=view,
content=f"Recorded answer: {age}")
await view.wait()
location = view.location
print(f"New form info for {ctx.author.name}: location {location}")
if not view.location:
await ctx.send(embed=embeds.no_time())
return
# START PRONOUNS
await ctx.send(
embed=embeds.simple_question_30("What are your preferred pronouns?"),
content=f"Recorded answer: {location}")
try:
pronouns_message = await self.bot.wait_for('message', check=check, timeout=120)
pronouns = pronouns_message.content
if len(pronouns) > 30:
pronouns = pronouns[:30]
pronouns = pronouns.replace("\n", " ")
print(f"New form info for {ctx.author.name}: pronouns {pronouns}")
# START LIKES
await ctx.send(embed=embeds.simple_question_300("Likes & interests"),
content=f"Recorded answer: {pronouns}")
try:
likes_message = await self.bot.wait_for('message', check=check, timeout=300)
likes = likes_message.content
if len(likes) > 300:
likes = likes[:300]
likes = likes.replace("\n", " ")
print(f"New form info for {ctx.author.name}: likes {likes}")
# START DISLIKES
await ctx.send(embed=embeds.simple_question_300("Dislikes"),
content=f"Recorded answer: {likes}")
try:
dislikes_message = await self.bot.wait_for('message', check=check, timeout=300)
dislikes = dislikes_message.content
if len(dislikes) > 300:
dislikes = dislikes[:300]
dislikes = dislikes.replace("\n", " ")
print(f"New form info for {ctx.author.name}: dislikes {dislikes}")
# POST EXAMPLE EMBED AND FINAL IF APPROVED
em = embeds.final_embed_short(ctx, nickname, age, location, pronouns, likes, dislikes)
view = interaction.Confirm(ctx)
await ctx.send(embed=em, content=f"Introduction of <@{ctx.author.id}>", view=view)
await view.wait()
if view.clickedConfirm:
intro_channel = guild.get_channel(channel_id)
await intro_channel.send(embed=em, content=f"Introduction of <@{ctx.author.id}>")
await ctx.send(embed=embeds.final_confirmation(channel_id))
return
else:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
elif view.clickedLong:
# START NICKNAME
await ctx.send(embed=embeds.simple_question_first_extended(
"How would you like to be identified in the server?"))
try:
nickname_message = await self.bot.wait_for('message', check=check, timeout=120)
nickname = nickname_message.content
if len(nickname) > 100:
nickname = nickname[:100]
nickname = nickname.replace("\n", " ")
print(f"New form info for {ctx.author.name}: nickname {nickname}")
# START AGE
await ctx.send(embed=embeds.simple_question_5("How old are you?"),
content=f"Recorded answer: {nickname}")
try:
age_message = await self.bot.wait_for('message', check=check, timeout=120)
age = age_message.content
if len(age) > 5:
age = age[:5]
age = age.replace("\n", " ")
print(f"New form info for {ctx.author.name}: age {age}")
# START LOCATION
view = interaction.LocationOptions(ctx)
await ctx.send(embed=embeds.simple_question_none("Where do you live?"),
view=view,
content=f"Recorded answer: {age}")
await view.wait()
location = view.location
print(f"New form info for {ctx.author.name}: location {location}")
if not view.location:
await ctx.send(embed=embeds.no_time())
return
# START LANGUAGES
await ctx.send(
embed=embeds.simple_question_100("Which languages do you speak?"),
content=f"Recorded answer: {location}"
)
try:
languages_message = await self.bot.wait_for('message', check=check, timeout=200)
languages = languages_message.content
if len(languages) > 30:
languages = languages[:30]
languages = languages.replace("\n", " ")
print(f"New form info for {ctx.author.name}: languages {languages}")
# START PRONOUNS
await ctx.send(
embed=embeds.simple_question_30("What are your preferred pronouns?"),
content=f"Recorded answer: {languages}")
try:
pronouns_message = await self.bot.wait_for('message', check=check, timeout=120)
pronouns = pronouns_message.content
if len(pronouns) > 30:
pronouns = pronouns[:30]
pronouns = pronouns.replace("\n", " ")
print(f"New form info for {ctx.author.name}: pronouns {pronouns}")
# START SEXUALITY
await ctx.send(
embed=embeds.simple_question_30("What's your sexuality?"),
content=f"Recorded answer: {pronouns}")
try:
sexuality_message = await self.bot.wait_for('message', check=check, timeout=120)
sexuality = sexuality_message.content
if len(sexuality) > 30:
sexuality = sexuality[:30]
sexuality = sexuality.replace("\n", " ")
print(f"New form info for {ctx.author.name}: sexuality {sexuality}")
# START RELATIONSHIP_STATUS
await ctx.send(
embed=embeds.simple_question_30("What's your current relationship status?"),
content=f"Recorded answer: {sexuality}")
try:
relationship_status_message = await self.bot.wait_for('message', check=check,
timeout=120)
relationship_status = relationship_status_message.content
if len(relationship_status) > 30:
relationship_status = relationship_status[:30]
relationship_status = relationship_status.replace("\n", " ")
print(
f"New form info for {ctx.author.name}: relationship_status {relationship_status}")
# START LIKES
await ctx.send(embed=embeds.simple_question_300("Likes & interests"),
content=f"Recorded answer: {relationship_status}")
try:
likes_message = await self.bot.wait_for('message', check=check, timeout=300)
likes = likes_message.content
if len(likes) > 300:
likes = likes[:300]
likes = likes.replace("\n", " ")
print(f"New form info for {ctx.author.name}: likes {likes}")
# START DISLIKES
await ctx.send(embed=embeds.simple_question_300("Dislikes"),
content=f"Recorded answer: {likes}")
try:
dislikes_message = await self.bot.wait_for('message', check=check,
timeout=300)
dislikes = dislikes_message.content
if len(dislikes) > 300:
dislikes = dislikes[:300]
dislikes = dislikes.replace("\n", " ")
print(f"New form info for {ctx.author.name}: dislikes {dislikes}")
# START EXTRA
await ctx.send(embed=embeds.simple_question_300(
"EXTRAS: job status, zodiac sign, hobbies, etc. "
"Tell us about yourself!"),
content=f"Recorded answer: {dislikes}")
try:
extra_message = await self.bot.wait_for('message', check=check,
timeout=300)
extra = extra_message.content
if len(extra) > 300:
extra = extra[:300]
extra = extra.replace("\n", " ")
print(f"New form info for {ctx.author.name}: extra {extra}")
# POST EXAMPLE EMBED AND FINAL IF APPROVED
em = embeds.final_embed_extended(ctx, nickname, age, location,
languages, pronouns, sexuality,
relationship_status, likes,
dislikes, extra)
view = interaction.Confirm(ctx)
await ctx.send(embed=em, content=f"Introduction of <@{ctx.author.id}>",
view=view)
await view.wait()
if view.clickedConfirm:
intro_channel = guild.get_channel(channel_id)
await intro_channel.send(embed=em,
content=f"Introduction of <@{ctx.author.id}>")
await ctx.send(embed=embeds.final_confirmation(channel_id))
return
else:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
except asyncio.TimeoutError:
await ctx.send(embed=embeds.no_time())
return
else:
await ctx.send(embed=embeds.no_time())
return
def setup(sbbot):
sbbot.add_cog(Basic(sbbot))

187
modules/economy.py Normal file
View file

@ -0,0 +1,187 @@
import json
import os
import time
import discord
from discord.ext import commands
from dotenv import load_dotenv
from data.Currency import Currency
from data.Dailies import Dailies
from sb_tools import economy_embeds, universal, interaction
load_dotenv('.env')
active_blackjack_games = {}
special_balance_name = os.getenv("SPECIAL_BALANCE_NAME")
cash_balance_name = os.getenv("CASH_BALANCE_NAME")
with open("json/economy.json") as file:
json_data = json.load(file)
class Economy(commands.Cog):
def __init__(self, sbbot):
self.bot = sbbot
@commands.slash_command(
name="balance",
description="See how much cash you have.",
guild_only=True
)
@commands.check(universal.channel_check)
async def balance(self, ctx):
cash_balance = Currency.get_cash_balance(ctx.author.id)
special_balance = Currency.get_special_balance(ctx.author.id)
await ctx.respond(embed=economy_embeds.currency_balance(ctx, cash_balance, special_balance))
@commands.slash_command(
name="give",
description="Give another user some currency.",
guild_only=True
)
@commands.check(universal.channel_check)
async def give(self, ctx, *,
user: discord.Option(discord.Member),
currency: discord.Option(choices=["cash", special_balance_name]),
amount: discord.Option(int)):
if ctx.author.id == user.id:
return await ctx.respond(embed=economy_embeds.give_yourself_error(currency))
elif user.bot:
return await ctx.respond(embed=economy_embeds.give_bot_error(currency))
try:
if currency == "cash":
author_cash_balance = Currency.get_cash_balance(ctx.author.id)
if author_cash_balance < amount or author_cash_balance <= 0:
return await ctx.respond(embed=economy_embeds.not_enough_cash())
target_cash_balance = Currency.get_cash_balance(user.id)
target_new_cash_balance = target_cash_balance + amount
author_new_cash_balance = author_cash_balance - amount
Currency.update_cash_balance(user.id, target_new_cash_balance)
Currency.update_cash_balance(ctx.author.id, author_new_cash_balance)
elif currency == special_balance_name:
author_special_balance = Currency.get_special_balance(ctx.author.id)
if author_special_balance < amount or author_special_balance <= 0:
return await ctx.respond(embed=economy_embeds.not_enough_special_balance())
target_special_balance = Currency.get_special_balance(user.id)
target_new_special_balance = target_special_balance + amount
author_new_special_balance = author_special_balance - amount
Currency.update_special_balance(user.id, target_new_special_balance)
Currency.update_special_balance(ctx.author.id, author_new_special_balance)
except Exception as e:
await ctx.channel.respond("Something funky happened.. Tell Tess.", ephemeral=True)
print(e)
return
await ctx.respond(embed=economy_embeds.give(ctx, user, currency, amount))
@commands.slash_command(
name="exchange",
description=f"Exchange {special_balance_name} for cash.",
guild_only=True
)
@commands.check(universal.channel_check)
async def exchange(self, ctx, *, amount: discord.Option(int)):
author_special_balance = Currency.get_special_balance(ctx.author.id)
if author_special_balance < amount or author_special_balance <= 0:
return await ctx.respond(embed=economy_embeds.not_enough_special_balance())
view = interaction.ExchangeConfirmation(ctx)
await ctx.respond(embed=economy_embeds.exchange_confirmation(amount), view=view)
await view.wait()
if view.clickedConfirm:
author_new_special_balance = author_special_balance - amount
author_new_cash_balance = Currency.get_cash_balance(ctx.author.id) + (amount * 1000)
Currency.update_cash_balance(ctx.author.id, author_new_cash_balance)
Currency.update_special_balance(ctx.author.id, author_new_special_balance)
return await ctx.edit(embed=economy_embeds.exchange_done(amount))
await ctx.edit(embed=economy_embeds.exchange_stopped())
@commands.slash_command(
name="award",
description="Award currency - owner only command.",
guild_only=True
)
@commands.check(universal.channel_check)
@commands.check(universal.owner_check)
async def award(self, ctx, *,
user: discord.Option(discord.Member),
currency: discord.Option(choices=["cash_balance", "special_balance"]),
amount: discord.Option(int)):
try:
if currency == "cash_balance":
current_cash_balance = Currency.get_cash_balance(user.id)
new_cash_balance = int(current_cash_balance) + amount
Currency.update_cash_balance(user.id, new_cash_balance)
else:
current_special_balance = Currency.get_special_balance(user.id)
new_special_balance = int(current_special_balance) + amount
Currency.update_special_balance(user.id, new_special_balance)
except Exception as e:
await ctx.channel.respond("Something went wrong. Check console.", ephemeral=True)
print(e)
return
await ctx.respond(embed=economy_embeds.award(user, currency, amount))
@commands.slash_command(
name="daily",
description="Claim your daily cash!",
guild_only=True
)
@commands.check(universal.channel_check)
async def daily(self, ctx):
(can_claim, next_claim) = Dailies.cooldown_check(ctx.author.id)
amount = json_data["daily_reward"]
current_time = time.time()
if can_claim:
await ctx.respond(embed=economy_embeds.daily_claim(amount))
# give money
current_cash_balance = Currency.get_cash_balance(ctx.author.id)
Currency.update_cash_balance(ctx.author.id, current_cash_balance + amount)
# push daily to DB
daily = Dailies(
user_id=ctx.author.id,
claimed_at=current_time,
next_available=current_time + json_data["daily_cooldown"]
)
daily.push()
else:
cooldown = next_claim - current_time
hours = int(cooldown // 3600)
minutes = int((cooldown % 3600) // 60)
seconds = int(cooldown % 60)
cooldown_text = f"{str(hours).zfill(2)}:{str(minutes).zfill(2)}:{str(seconds).zfill(2)}"
await ctx.respond(embed=economy_embeds.daily_wait(cooldown_text))
def setup(sbbot):
sbbot.add_cog(Economy(sbbot))

290
modules/gambling.py Normal file
View file

@ -0,0 +1,290 @@
import asyncio
import json
import os
import random
import discord
from discord.ext import commands
from dotenv import load_dotenv
from data.BlackJackStats import BlackJackStats
from data.Currency import Currency
from data.SlotsStats import SlotsStats
from sb_tools import economy_embeds, economy_functions, universal, interaction, embeds
load_dotenv('.env')
active_blackjack_games = {}
special_balance_name = os.getenv("SPECIAL_BALANCE_NAME")
cash_balance_name = os.getenv("CASH_BALANCE_NAME")
with open("json/economy.json") as file:
json_data = json.load(file)
class Gambling(commands.Cog):
def __init__(self, sbbot):
self.bot = sbbot
# @commands.slash_command(
# name="coinflip",
# description="Flip a coin and bet on the outcome.",
# guild_only=True
# )
# @commands.check(universal.channel_check)
# @commands.check(universal.beta_check)
# async def coinflip(self, ctx, *, side: discord.Option(choices=["heads", "tails"]), bet: discord.Option(int)):
# player_cash_balance = Currency.get_cash_balance(ctx.author.id)
# if bet > player_cash_balance:
# await ctx.respond(embed=economy_embeds.not_enough_cash())
# return
#
# side_list = ["heads", "tails"]
# throw_side = random.choice(side_list)
#
# if throw_side is side:
# await ctx.respond(embed=economy_embeds.coinflip())
@commands.slash_command(
name="blackjack",
description="Start a game of blackjack.",
guild_only=True
)
@commands.check(universal.channel_check)
async def blackjack(self, ctx, *, bet: discord.Option(int)):
# check if the player already has an active blackjack going
if ctx.author.id in active_blackjack_games:
await ctx.respond(embed=economy_embeds.already_playing("BlackJack"))
return
# check if the user has enough cash
player_cash_balance = Currency.get_cash_balance(ctx.author.id)
if bet > player_cash_balance or bet <= 0:
await ctx.respond(embed=economy_embeds.not_enough_cash())
return
active_blackjack_games[ctx.author.id] = True
try:
player_hand = []
dealer_hand = []
deck = economy_functions.blackjack_get_new_deck()
view = interaction.BlackJackButtons(ctx)
# deal initial cards (player draws two & dealer one)
player_hand.append(economy_functions.blackjack_deal_card(deck))
player_hand.append(economy_functions.blackjack_deal_card(deck))
dealer_hand.append(economy_functions.blackjack_deal_card(deck))
# calculate initial hands
player_hand_value = economy_functions.blackjack_calculate_hand_value(player_hand)
dealer_hand_value = economy_functions.blackjack_calculate_hand_value(dealer_hand)
status = "game_start"
await ctx.respond(embed=economy_embeds.blackjack_show(ctx, bet, player_hand,
dealer_hand, player_hand_value,
dealer_hand_value, status=status), view=view,
content=ctx.author.mention)
while status == "game_start":
await view.wait()
if view.clickedHit:
# player draws a card & value is calculated
player_hand.append(economy_functions.blackjack_deal_card(deck))
player_hand_value = economy_functions.blackjack_calculate_hand_value(player_hand)
if player_hand_value > 21:
status = "player_busted"
elif view.clickedStand:
# player stands, dealer draws cards until he wins OR busts
while dealer_hand_value <= player_hand_value:
dealer_hand.append(economy_functions.blackjack_deal_card(deck))
dealer_hand_value = economy_functions.blackjack_calculate_hand_value(dealer_hand)
if dealer_hand_value > 21:
status = "dealer_busted"
else:
status = "dealer_won"
else:
status = "timed_out"
break
# edit the embed, disable view if game is over.
if status == "game_start":
view = interaction.BlackJackButtons(ctx)
else:
view = None
await ctx.edit(embed=economy_embeds.blackjack_show(ctx, bet, player_hand,
dealer_hand, player_hand_value,
dealer_hand_value, status=status), view=view,
content=ctx.author.mention)
# change balance
if status == "player_busted" or status == "dealer_won":
Currency.update_cash_balance(ctx.author.id, player_cash_balance - bet)
# push stats (low priority)
stats = BlackJackStats(
user_id=ctx.author.id,
is_won=False,
bet=bet,
payout=0,
hand_player=player_hand,
hand_dealer=dealer_hand
)
stats.push_one()
elif status == "timed_out":
await ctx.send(embed=economy_embeds.out_of_time(), content=ctx.author.mention)
else:
# bet multiplier
payout = bet * 1.2
Currency.update_cash_balance(ctx.author.id, player_cash_balance + payout)
# push stats (low priority)
stats = BlackJackStats(
user_id=ctx.author.id,
is_won=True,
bet=bet,
payout=payout,
hand_player=player_hand,
hand_dealer=dealer_hand
)
stats.push_one()
except Exception as e:
await ctx.respond(embed=embeds.command_error_1())
print("Something went wrong in the gambling command:\n", e)
finally:
# remove player from active games list
del active_blackjack_games[ctx.author.id]
@commands.slash_command(
name="slots",
descriptions="Spin the slots for a chance to win the jackpot!",
guild_only=True
)
@commands.check(universal.channel_check)
async def slots(self, ctx, *, bet: discord.Option(int)):
# check if the user has enough cash
player_cash_balance = Currency.get_cash_balance(ctx.author.id)
if bet > player_cash_balance or bet <= 0:
await ctx.respond(embed=economy_embeds.not_enough_cash())
return
# calculate the results before the command is shown
results = [random.randint(0, 6) for i in range(3)]
calculated_results = economy_functions.calculate_slots_results(bet, results)
type = calculated_results[0]
payout = calculated_results[1]
multiplier = calculated_results[2]
is_won = True
if type == "lost":
is_won = False
# start with default "spinning" embed
await ctx.respond(embed=economy_embeds.slots_spinning(ctx, 3, bet, results, self.bot))
await asyncio.sleep(1)
await ctx.edit(embed=economy_embeds.slots_spinning(ctx, 2, bet, results, self.bot),
allowed_mentions=discord.AllowedMentions.none())
await asyncio.sleep(1)
await ctx.edit(embed=economy_embeds.slots_spinning(ctx, 1, bet, results, self.bot),
allowed_mentions=discord.AllowedMentions.none())
await asyncio.sleep(1)
await ctx.edit(embed=economy_embeds.slots_finished(ctx, type, multiplier, bet, results, self.bot),
allowed_mentions=discord.AllowedMentions.none())
# user payout
Currency.update_cash_balance(ctx.author.id, player_cash_balance + payout)
# push stats (low priority)
if payout <= 0:
payout = 0
stats = SlotsStats(
user_id=ctx.author.id,
is_won=is_won,
bet=bet,
payout=payout,
spin_type=type,
icons=results
)
stats.push_one()
@commands.slash_command(
name="duel",
description="Challenge another player to a fight.",
guild_only=True
)
@commands.check(universal.channel_check)
async def duel(self, ctx, *, opponent: discord.Option(discord.Member), bet: discord.Option(int)):
challenger = ctx.author
if challenger.id == opponent.id:
return await ctx.respond(content="You cannot duel yourself.")
elif opponent.bot:
return await ctx.respond(content="You cannot duel a bot.")
# check if challenger has enough cash
challenger_cash_balance = Currency.get_cash_balance(challenger.id)
if bet > challenger_cash_balance or bet <= 0:
return await ctx.respond(embed=economy_embeds.not_enough_cash())
# if opponent doesn't have sufficient money, the bet will become the opponent's cash
opponent_cash_balance = Currency.get_cash_balance(opponent.id)
all_in = ""
if opponent_cash_balance <= 0:
return await ctx.respond(f"Woops, you can't do that because **{opponent.name}** has no money.")
elif bet > opponent_cash_balance:
bet = opponent_cash_balance
all_in = " | opponent's all-in"
# challenge message
view = interaction.DuelChallenge(opponent)
await ctx.respond(
content=f"**{challenger.name}** challenges {opponent.mention} to a duel ({cash_balance_name}{bet}{all_in})\n"
f"Use the buttons to accept/deny (challenge expires after 60s)", view=view)
await view.wait()
if view.clickedConfirm:
winner = random.choice([challenger, opponent])
loser = opponent if winner == challenger else challenger
combat_message = random.choice(json_data["duel"]["combat_messages"]).format(f"**{winner.name}**",
f"**{loser.name}**")
await ctx.respond(content=f"{combat_message}\n\n"
f"{winner.mention} wins **{cash_balance_name}{bet}**\n"
f"{loser.mention} loses this bet.")
# payouts
if winner == challenger:
Currency.update_cash_balance(challenger.id, challenger_cash_balance + bet)
Currency.update_cash_balance(opponent.id, opponent_cash_balance - bet)
elif winner == opponent:
Currency.update_cash_balance(opponent.id, opponent_cash_balance + bet)
Currency.update_cash_balance(challenger.id, challenger_cash_balance - bet)
elif view.clickedDeny:
await ctx.edit(content=f"**{opponent.name}** canceled the duel.")
else:
await ctx.edit(content=f"Time ran out.")
def setup(sbbot):
sbbot.add_cog(Gambling(sbbot))

94
modules/leveling.py Normal file
View file

@ -0,0 +1,94 @@
import time
from discord.ext import commands
from data.Currency import Currency
from data.Xp import Xp
from sb_tools import embeds, universal, level_messages, reactions, xp_functions
class Leveling(commands.Cog):
def __init__(self, sbbot):
self.bot = sbbot
@commands.Cog.listener()
async def on_message(self, message):
if message.author.bot:
return
await reactions.check_for_reaction(message)
user_id = message.author.id
current_time = time.time()
xp_data = Xp.get_user_xp_data(user_id)
(current_xp, current_level, cooldown) = xp_data[0]
if cooldown and current_time < cooldown:
print(f"XP UPDATE --- {message.author.name} sent a message but is on XP cooldown.")
return
gain_data = Xp.load_gain_data()
xp_gain = gain_data[0]
cooldown = gain_data[1]
new_xp = current_xp + xp_gain
needed_xp_for_next_level = xp_functions.xp_needed_for_next_level(current_level)
if new_xp >= needed_xp_for_next_level:
# new level was reached
new_level = current_level + 1
new_xp = 0
Xp.update_user_xp(user_id, new_xp, new_level, current_time + cooldown)
print(f"XP UPDATE --- {message.author.name} leveled up; new_level = {new_level}.")
await message.channel.send(content=f"<@{user_id}> {level_messages.load_level_message(new_level)}")
# assign level role if necessary:
if new_level in [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]:
await Xp.assign_level_role(message.author, new_level)
# award a special_balance_currency
amount = 1
current_special_balance = Currency.get_special_balance(user_id)
new_special_balance = int(current_special_balance) + amount
Currency.update_special_balance(user_id, new_special_balance)
else:
# user gained XP but not new level
Xp.update_user_xp(user_id, new_xp, current_level, current_time + cooldown)
print(f"XP UPDATE --- {message.author.name} gained {xp_gain} XP; new_xp = {new_xp}.")
"""
Level calculation
Linear = 9x + 27
"""
@commands.slash_command(
name="level",
description="Displays your level and rank.",
guild_only=True
)
@commands.check(universal.channel_check)
async def level(self, ctx):
xp_data = Xp.get_user_xp_data(ctx.author.id)
(current_xp, current_level, cooldown) = xp_data[0]
rank = Xp.calculate_rank(ctx.author.id)
needed_xp_for_next_level = xp_functions.xp_needed_for_next_level(current_level)
await ctx.respond(embed=embeds.level_command_message(ctx, current_level, current_xp,
needed_xp_for_next_level, rank))
@commands.slash_command(
name="leaderboard",
description="Are ya winnin' son?",
guild_only=True
)
@commands.check(universal.channel_check)
async def leaderboard(self, ctx):
leaderboard = Xp.load_leaderboard()
embed = await embeds.leaderboard_message(ctx, leaderboard)
await ctx.respond(embed=embed)
def setup(sbbot):
sbbot.add_cog(Leveling(sbbot))

4
requirements.txt Normal file
View file

@ -0,0 +1,4 @@
py-cord==2.4.1
python-dotenv==1.0.0
setuptools==67.8.0
pytz==2023.3

347
sb_tools/economy_embeds.py Normal file
View file

@ -0,0 +1,347 @@
import datetime
import json
import os
import discord
import pytz
from dotenv import load_dotenv
load_dotenv('.env')
cash_balance_name = os.getenv("CASH_BALANCE_NAME")
special_balance_name = os.getenv("SPECIAL_BALANCE_NAME")
est = pytz.timezone('US/Eastern')
with open("json/economy.json") as file:
json_data = json.load(file)
def currency_balance(ctx, cash_balance, special_balance):
embed = discord.Embed(
description=f"**Cash**: {cash_balance_name}{cash_balance}\n"
f"**{special_balance_name.capitalize()}**: {special_balance}"
)
embed.set_author(name=f"{ctx.author.name}'s wallet", icon_url=ctx.author.avatar.url)
embed.set_footer(text=f"Level up to earn {special_balance_name}!")
return embed
def award(user, currency, amount):
reward = f"{amount}"
if currency == "cash_balance":
reward = cash_balance_name + reward
else:
reward = f"{reward} {special_balance_name}"
embed = discord.Embed(
color=discord.Color.green(),
description=f"Awarded **{reward}** to {user.name}."
)
return embed
def give(ctx, user, currency, amount):
reward = f"{amount}"
if currency == "cash":
reward = cash_balance_name + reward
else:
reward = f"{reward} {special_balance_name}"
embed = discord.Embed(
color=discord.Color.green(),
description=f"**{ctx.author.name}** gave **{reward}** to {user.name}."
)
embed.set_footer(text="Say thanks! :)")
return embed
def give_yourself_error(currency):
embed = discord.Embed(
color=discord.Color.red(),
description=f"You can't give {currency} to yourself, silly."
)
return embed
def give_bot_error(currency):
embed = discord.Embed(
color=discord.Color.red(),
description=f"You can't give {currency} to a bot, silly."
)
return embed
def already_playing(game):
embed = discord.Embed(
color=discord.Color.red(),
description=f"You're already playing {game}. Please finish this game first."
)
return embed
def not_enough_cash():
embed = discord.Embed(
color=discord.Color.red(),
description="Oops! Your current cash balance isn't sufficient to do that."
)
return embed
def not_enough_special_balance():
embed = discord.Embed(
color=discord.Color.red(),
description=f"Oops! Your current {special_balance_name} balance isn't sufficient to do that."
)
return embed
def out_of_time():
embed = discord.Embed(
color=discord.Color.red(),
description="Uh-oh! Time's up. Your bet is forfeited as the game concludes."
)
return embed
def exchange_confirmation(amount):
embed = discord.Embed(
description=f"You're about to sell {amount} {special_balance_name} for {cash_balance_name}{amount * 1000}. "
f"Are you absolutely sure about this? Keep in mind that repurchasing {special_balance_name} "
f"later is considerably more expensive."
)
return embed
def exchange_done(amount):
embed = discord.Embed(
color=discord.Color.green(),
description=f"You successfully exchanged **{amount} {special_balance_name}** "
f"for **{cash_balance_name}{amount * 1000}**."
)
return embed
def exchange_stopped():
embed = discord.Embed(
color=discord.Color.red(),
description="The exchange was canceled because you clicked \"Stop\" or ran out of time."
)
return embed
def coinflip(ctx, guess_side, throw_side, bet):
embed = discord.Embed(
title=f"You bet {cash_balance_name}{bet} on {guess_side}."
)
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
if throw_side == "heads":
embed.set_thumbnail(url="https://media.tenor.com/nEu74vu_sT4AAAAC/heads-coinflip.gif")
else:
embed.set_thumbnail(url="https://media.tenor.com/kK8D7hQXX5wAAAAC/coins-tails.gif")
return embed
def coinflip_finished(side, status):
color = None
if status == "success":
color = discord.Color.green()
def blackjack_show(ctx, bet, player_hand, dealer_hand, player_hand_value, dealer_hand_value, status):
current_time = datetime.datetime.now(est).strftime("%I:%M %p")
you_text = "You"
dealer_text = "Dealer"
title_text = "BlackJack"
thumbnail_url = None
color = discord.Color.dark_orange()
if status == "player_busted":
you_text = "You | BUSTED"
title_text = "YOU LOST!"
thumbnail_url = "https://i.imgur.com/rc68c43.png"
color = discord.Color.red()
elif status == "dealer_busted":
dealer_text = "Dealer | BUSTED"
title_text = "YOU WON!"
thumbnail_url = "https://i.imgur.com/dvIIr2G.png"
color = discord.Color.green()
elif status == "dealer_won":
title_text = "YOU LOST!"
thumbnail_url = "https://i.imgur.com/rc68c43.png"
color = discord.Color.red()
embed = discord.Embed(
title=title_text,
color=color
)
embed.add_field(name=you_text, value=f"**Score: {player_hand_value}**\n"
f"*Hand: {' + '.join(player_hand)}*")
if len(dealer_hand) < 2:
embed.add_field(name=dealer_text, value=f"**Score: {dealer_hand_value}**\n"
f"*Hand: {dealer_hand[0]} + ??*", inline=False)
else:
embed.add_field(name=dealer_text, value=f"**Score: {dealer_hand_value}**\n"
f"*Hand: {' + '.join(dealer_hand)}*", inline=False)
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
embed.set_footer(text=f"Bet {cash_balance_name}{bet} • deck shuffled • Today at {current_time}",
icon_url="https://i.imgur.com/96jPPXO.png")
if thumbnail_url:
embed.set_thumbnail(url=thumbnail_url)
return embed
def slots_spinning(ctx, spinning_icons_amount, bet, results, sbbot):
first_slots_emote = sbbot.get_emoji(json_data["slots"]["emotes"][f"slots_{results[0]}_id"])
second_slots_emote = sbbot.get_emoji(json_data["slots"]["emotes"][f"slots_{results[1]}_id"])
slots_animated_emote = sbbot.get_emoji(json_data["slots"]["emotes"][f"slots_animated_id"])
decoration = json_data["slots"]["emotes"]
S_Wide = sbbot.get_emoji(decoration["S_Wide"])
L_Wide = sbbot.get_emoji(decoration["L_Wide"])
O_Wide = sbbot.get_emoji(decoration["O_Wide"])
T_Wide = sbbot.get_emoji(decoration["T_Wide"])
CBorderBLeft = sbbot.get_emoji(decoration["CBorderBLeft"])
CBorderBRight = sbbot.get_emoji(decoration["CBorderBRight"])
CBorderTLeft = sbbot.get_emoji(decoration["CBorderTLeft"])
CBorderTRight = sbbot.get_emoji(decoration["CBorderTRight"])
HBorderB = sbbot.get_emoji(decoration["HBorderB"])
HBorderT = sbbot.get_emoji(decoration["HBorderT"])
VBorder = sbbot.get_emoji(decoration["VBorder"])
Blank = sbbot.get_emoji(decoration["Blank"])
current_time = datetime.datetime.now(est).strftime("%I:%M %p")
one = slots_animated_emote
two = slots_animated_emote
three = slots_animated_emote
if spinning_icons_amount == 3:
pass
elif spinning_icons_amount == 2:
one = first_slots_emote
elif spinning_icons_amount == 1:
one = first_slots_emote
two = second_slots_emote
description = f"🎰{S_Wide}{L_Wide}{O_Wide}{T_Wide}{S_Wide}🎰\n" \
f"{CBorderTLeft}{HBorderT}{HBorderT}{HBorderT}{HBorderT}{HBorderT}{CBorderTRight}\n" \
f"{VBorder}{one}{VBorder}{two}{VBorder}{three}{VBorder}\n" \
f"{CBorderBLeft}{HBorderB}{HBorderB}{HBorderB}{HBorderB}{HBorderB}{CBorderBRight}\n" \
f"{Blank}{Blank}❓❓❓{Blank}{Blank}{Blank}"
embed = discord.Embed(
description=description
)
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
embed.set_footer(text=f"Bet {cash_balance_name}{bet} • jackpot = x5 • {current_time}",
icon_url="https://i.imgur.com/wFsgSnr.png")
return embed
def slots_finished(ctx, payout_type, multiplier, bet, results, sbbot):
first_slots_emote = sbbot.get_emoji(json_data["slots"]["emotes"][f"slots_{results[0]}_id"])
second_slots_emote = sbbot.get_emoji(json_data["slots"]["emotes"][f"slots_{results[1]}_id"])
third_slots_emote = sbbot.get_emoji(json_data["slots"]["emotes"][f"slots_{results[2]}_id"])
current_time = datetime.datetime.now(est).strftime("%I:%M %p")
decoration = json_data["slots"]["emotes"]
S_Wide = sbbot.get_emoji(decoration["S_Wide"])
L_Wide = sbbot.get_emoji(decoration["L_Wide"])
O_Wide = sbbot.get_emoji(decoration["O_Wide"])
T_Wide = sbbot.get_emoji(decoration["T_Wide"])
CBorderBLeft = sbbot.get_emoji(decoration["CBorderBLeft"])
CBorderBRight = sbbot.get_emoji(decoration["CBorderBRight"])
CBorderTLeft = sbbot.get_emoji(decoration["CBorderTLeft"])
CBorderTRight = sbbot.get_emoji(decoration["CBorderTRight"])
HBorderB = sbbot.get_emoji(decoration["HBorderB"])
HBorderT = sbbot.get_emoji(decoration["HBorderT"])
VBorder = sbbot.get_emoji(decoration["VBorder"])
WSmall = sbbot.get_emoji(decoration["WSmall"])
ISmall = sbbot.get_emoji(decoration["ISmall"])
NSmall = sbbot.get_emoji(decoration["NSmall"])
LCentered = sbbot.get_emoji(decoration["LCentered"])
OCentered = sbbot.get_emoji(decoration["OCentered"])
SCentered = sbbot.get_emoji(decoration["SCentered"])
ECentered = sbbot.get_emoji(decoration["ECentered"])
Blank = sbbot.get_emoji(decoration["Blank"])
lost_emoji = sbbot.get_emoji(decoration["lost"])
field_name = "You lost."
field_value = f"You lost **{cash_balance_name}{bet}**."
color = discord.Color.red()
is_lost = True
if payout_type == "pair":
field_name = "Pair"
field_value = f"You won **{cash_balance_name}{bet * multiplier}**."
is_lost = False
discord.Color.dark_green()
elif payout_type == "three_of_a_kind":
field_name = "3 of a kind"
field_value = f"You won **{cash_balance_name}{bet * multiplier}**."
is_lost = False
discord.Color.dark_green()
elif payout_type == "three_diamonds":
field_name = "Triple Diamonds!"
field_value = f"You won **{cash_balance_name}{bet * multiplier}**."
is_lost = False
discord.Color.green()
elif payout_type == "jackpot":
field_name = "JACKPOT!!"
field_value = f"You won **{cash_balance_name}{bet * multiplier}**."
is_lost = False
discord.Color.green()
description = f"🎰{S_Wide}{L_Wide}{O_Wide}{T_Wide}{S_Wide}🎰\n" \
f"{CBorderTLeft}{HBorderT}{HBorderT}{HBorderT}{HBorderT}{HBorderT}{CBorderTRight}\n" \
f"{VBorder}{first_slots_emote}{VBorder}{second_slots_emote}{VBorder}{third_slots_emote}{VBorder}\n" \
f"{CBorderBLeft}{HBorderB}{HBorderB}{HBorderB}{HBorderB}{HBorderB}{CBorderBRight}"
if is_lost:
description += f"\n{Blank}{LCentered}{OCentered}{SCentered}{ECentered}{lost_emoji}{Blank}"
else:
description += f"\n{Blank}🎉{WSmall}{ISmall}{NSmall}🎉{Blank}"
embed = discord.Embed(
color=color,
description=description
)
embed.add_field(name=field_name, value=field_value)
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
embed.set_footer(text=f"Bet {cash_balance_name}{bet} • jackpot = x5 • {current_time}",
icon_url="https://i.imgur.com/wFsgSnr.png")
return embed
def daily_claim(amount):
embed = discord.Embed(
color=discord.Color.green(),
description=f"You claimed your daily reward of **{cash_balance_name}{amount}**."
)
return embed
def daily_wait(time):
embed = discord.Embed(
color=discord.Color.red(),
description=f"You can't claim that yet! Please wait **{time}**."
)
return embed

View file

@ -0,0 +1,82 @@
import random
from collections import Counter
def blackjack_get_new_deck():
suits = ['', '', '', '']
ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
deck = []
for suit in suits:
for rank in ranks:
deck.append(rank + suit)
random.shuffle(deck)
return deck
def blackjack_deal_card(deck):
return deck.pop()
def blackjack_calculate_hand_value(hand):
value = 0
has_ace = False
aces_count = 0
for card in hand:
if card is None:
continue
rank = card[:-1]
if rank.isdigit():
value += int(rank)
elif rank in ['J', 'Q', 'K']:
value += 10
elif rank == 'A':
value += 11
has_ace = True
aces_count += 1
"""
An Ace will have a value of 11 unless that would give a player
or the dealer a score in excess of 21; in which case, it has a value of 1
"""
if value > 21 and has_ace:
value -= 10 * aces_count
return value
def calculate_slots_results(bet, results):
type = None
multiplier = None
# count occurrences of each item in the list
counts = Counter(results)
# no icons match
if len(counts) == 3:
type = "lost"
multiplier = -1
# pairs
elif len(counts) == 2:
type = "pair"
multiplier = 1
# 3 of a kind
elif len(counts) == 1:
if results[0] == 5:
type = "three_diamonds"
multiplier = 4
elif results[0] == 6:
type = "jackpot"
multiplier = 5
else:
type = "three_of_a_kind"
multiplier = 3
payout = bet * multiplier
return type, payout, multiplier

145
sb_tools/embeds.py Normal file
View file

@ -0,0 +1,145 @@
import discord
from data.Xp import Xp
def command_error_1():
embed = discord.Embed(
color=discord.Color.red(),
description="I'm not even sure how you reached this error but here we are. Try the command again."
)
embed.set_footer(text="And tell Tess!!!")
return embed
def simple_question_5(question):
embed = discord.Embed(color=0xadcca6,
title=question)
embed.set_footer(text="max. 5 characters")
return embed
def simple_question_30(question):
embed = discord.Embed(color=0xadcca6,
title=question)
embed.set_footer(text="max. 30 characters")
return embed
def simple_question_100(question):
embed = discord.Embed(color=0xadcca6,
title=question)
embed.set_footer(text="max. 100 characters")
return embed
def simple_question_300(question):
embed = discord.Embed(color=0xadcca6,
title=question)
embed.set_footer(text="max. 300 characters")
return embed
def simple_question_none(question):
embed = discord.Embed(color=0xadcca6,
title=question)
return embed
def simple_question_first(question):
embed = discord.Embed(color=0xadcca6,
title=f"You chose to go with the short introduction! "
f"Let's start with your nickname. {question}")
embed.set_footer(text="max. 100 characters")
return embed
def simple_question_first_extended(question):
embed = discord.Embed(color=0xadcca6,
title=f"You chose to go with the extended introduction! "
f"Let's start with your nickname. {question}")
embed.set_footer(text="max. 100 characters")
return embed
def no_time():
embed = discord.Embed(description="You ran out of time or clicked the \"Stop\" button. "
"If you wish to start over, do **/intro**.")
return embed
def final_embed_short(ctx, nickname, age, location, pronouns, likes, dislikes):
embed = discord.Embed(color=0x2200FF, description=
f"**(Nick)name:** {nickname}\n\n**Age:** {age}\n\n"
f"**Region:** {location}\n\n**Pronouns:** {pronouns}\n\n"
f"**Likes & interests:** {likes}\n\n**Dislikes:** {dislikes}")
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
embed.set_footer(text="Type: Short Introduction")
return embed
def final_embed_extended(ctx, nickname, age, location, languages, pronouns,
sexuality, relationship_status, likes, dislikes, extra):
embed = discord.Embed(color=0xD91E1E, description=
f"**(Nick)name:** {nickname}\n\n**Age:** {age}\n\n"
f"**Region:** {location}\n\n**Languages:** {languages}\n\n"
f"**Pronouns:** {pronouns}\n\n**Sexuality** {sexuality}\n\n"
f"**Relationship status:** {relationship_status}\n\n**Likes & interests:** {likes}\n\n"
f"**Dislikes:** {dislikes}\n\n**EXTRAS:** {extra}")
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
embed.set_footer(text="Type: Extended Introduction")
return embed
def final_confirmation(channel_id):
embed = discord.Embed(color=0xadcca6,
title="Your introduction has been posted in the server!",
description=f"<#{channel_id}>")
return embed
#
# def level_up_message(level, rank):
# embed = discord.Embed(color=0xadcca6,
# title=f"You reached level {level}!")
# embed.set_footer(text=f"Rank: #{rank} | Leaderboard coming soon")
# return embed
def level_command_message(ctx, level, xp, next_level_xp, rank):
embed = discord.Embed(color=0xadcca6,
title=f"{ctx.author.name} - lv. {level}")
embed.add_field(name="Progress to Next Level", value=Xp.generate_progress_bar(xp, next_level_xp), inline=False)
embed.set_footer(text=f"The Rave Cave | Server Rank: #{rank}")
embed.set_thumbnail(url=ctx.author.avatar.url)
return embed
async def leaderboard_message(ctx, leaderboard):
embed = discord.Embed(
color=0xadcca6
)
embed.set_author(name="Rave Cave Leaderboard",
icon_url="https://cdn.discordapp.com/icons/719227135151046699/"
"49df8c284382af9dbcfd629c8eadc52c.webp?size=96")
embed.set_footer(text=f"Do /level to see your rank.")
embed.set_thumbnail(url="https://i.imgur.com/79XfsbS.png")
for i, (user_id, xp, level, rank, xp_needed_for_next_level) in enumerate(leaderboard[:5], start=1):
member = await ctx.guild.fetch_member(user_id)
embed.add_field(
name=f"#{rank} - {member.name}",
value=f"level: `{level}`\nxp: `{xp}/{xp_needed_for_next_level}`",
inline=False
)
return embed

232
sb_tools/interaction.py Normal file
View file

@ -0,0 +1,232 @@
import discord
from discord.ui import View
class IntroButtons(View):
def __init__(self, ctx):
super().__init__(timeout=300)
self.ctx = ctx
self.clickedShort = False
self.clickedLong = False
async def on_timeout(self):
for child in self.children:
child.disabled = True
await self.message.edit(view=None)
@discord.ui.button(label="Short", style=discord.ButtonStyle.primary)
async def short_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.clickedShort = True
self.stop()
@discord.ui.button(label="Extended", style=discord.ButtonStyle.green)
async def extended_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.clickedLong = True
self.stop()
@discord.ui.button(label="Stop", style=discord.ButtonStyle.red)
async def stop_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.stop()
# async def on_timeout(self):
# await self.ctx.
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message("You can't use these buttons, they're someone else's!",
ephemeral=True)
return False
else:
return True
class BlackJackButtons(View):
def __init__(self, ctx):
super().__init__(timeout=180)
self.ctx = ctx
self.clickedHit = False
self.clickedStand = False
self.clickedDoubleDown = False
async def on_timeout(self):
for child in self.children:
child.disabled = True
await self.message.edit(view=None)
@discord.ui.button(label="hit", style=discord.ButtonStyle.gray, emoji="<:hit:1119262723285467156> ")
async def hit_button_callback(self, button, interaction):
self.clickedHit = True
await interaction.response.defer()
self.stop()
@discord.ui.button(label="stand", style=discord.ButtonStyle.gray, emoji="<:stand:1118923298298929154>")
async def stand_button_callback(self, button, interaction):
self.clickedStand = True
await interaction.response.defer()
self.stop()
# @discord.ui.button(label="double down", style=discord.ButtonStyle.gray, emoji="<:double_down:1118923344549523656>")
# async def double_down_button_callback(self):
# self.clickedDoubleDown = True
# self.stop()
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message("You can't use these buttons, they're someone else's!",
ephemeral=True)
return False
else:
return True
class ExchangeConfirmation(View):
def __init__(self, ctx):
super().__init__(timeout=180)
self.ctx = ctx
self.clickedConfirm = False
async def on_timeout(self):
for child in self.children:
child.disabled = True
await self.message.edit(view=None)
@discord.ui.button(label="Confirm", style=discord.ButtonStyle.green)
async def confirm_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.clickedConfirm = True
self.stop()
@discord.ui.button(label="Stop", style=discord.ButtonStyle.red)
async def stop_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.stop()
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message("You can't use these buttons, they're someone else's!",
ephemeral=True)
return False
else:
return True
class Confirm(View):
def __init__(self, ctx):
super().__init__(timeout=300)
self.ctx = ctx
self.clickedConfirm = False
async def on_timeout(self):
for child in self.children:
child.disabled = True
await self.message.edit(view=None)
@discord.ui.button(label="Post it!", style=discord.ButtonStyle.green)
async def short_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.clickedConfirm = True
self.stop()
@discord.ui.button(label="Stop", style=discord.ButtonStyle.red)
async def extended_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.stop()
# async def on_timeout(self):
# await self.ctx.
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message("You can't use these buttons, they're someone else's!",
ephemeral=True)
return False
else:
return True
class DuelChallenge(View):
def __init__(self, opponent):
super().__init__(timeout=60)
self.opponent = opponent
self.clickedConfirm = False
self.clickedDeny = False
async def on_timeout(self):
for child in self.children:
child.disabled = True
await self.message.edit(view=None)
@discord.ui.button(label="accept", style=discord.ButtonStyle.green)
async def short_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.clickedConfirm = True
self.stop()
@discord.ui.button(label="deny", style=discord.ButtonStyle.red)
async def extended_button_callback(self, button, interaction):
await interaction.response.edit_message(view=None)
self.clickedDeny = True
self.stop()
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.opponent:
await interaction.response.send_message("You can't use these buttons, they're someone else's!",
ephemeral=True)
return False
else:
return True
class LocationOptions(discord.ui.View):
def __init__(self, ctx):
super().__init__(timeout=120)
self.ctx = ctx
self.location = None
async def on_timeout(self):
for child in self.children:
child.disabled = True
await self.message.edit(view=None)
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message("You can't use this menu, it's someone else's!", ephemeral=True)
return False
else:
return True
@discord.ui.select(
min_values=1,
max_values=1,
options=[
discord.SelectOption(
label="Choose a continent",
default=True
),
discord.SelectOption(
label="Africa"
),
discord.SelectOption(
label="Europe"
),
discord.SelectOption(
label="Asia"
),
discord.SelectOption(
label="North America"
),
discord.SelectOption(
label="South America"
),
discord.SelectOption(
label="Oceania"
)
]
)
async def select_callback(self, select, interaction):
self.location = select.values[0]
await interaction.response.edit_message(view=None)
self.stop()

150
sb_tools/level_messages.py Normal file
View file

@ -0,0 +1,150 @@
import random
def load_level_message(level):
if level in [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]:
return f"Congratulations! You've reached **Level {level}** and earned a new level role!"
elif level < 10:
return random.choice(level_under_10).format(level)
elif 10 < level < 20:
return random.choice(level_10_to_20).format(level)
elif 20 < level < 40:
return random.choice(level_20_to_40).format(level)
elif 40 < level < 60:
return random.choice(level_40_to_60).format(level)
elif level == 100:
return level_100.format(level)
else:
return random.choice(level_above_60).format(level)
level_100 = "YOU HAVE REACHED **LEVEL {}**!!I know you have something to say and I know you're eager to say it so I'll " \
"get right to the point: Shut " \
"the fuck up. Nobody wants to hear it. Nobody will ever want to hear it. Nobody cares. And the fact that " \
"you thought someone might care is honestly baffling to me. I've actually pulled the entire world. Here's " \
"a composite of the faces of everybody who wants you to shut the fuck up. It seems as if this is a " \
"composite of every human being on the planet. Interesting. Now for a composite of the faces that want " \
"you to keep talking: Interesting, it seems as if nothing has happened. Here's the world map. Now here's " \
"the text: Shut the fuck up. That's what you should do. But you know what? Maybe I am being a little too " \
"harsh here. I actually do have it on good authority thanks to my pulling data that there is as at least " \
"1 person who actually wants to hear you speak. It's a little child in Mozambique and he oh? He's dead? " \
"Well sorry man I guess nobody wants to hear you talk anymore. Please shut the fuck up."
level_under_10 = [
"Wow, look who finally managed to crawl their way to **Level {}**! Congrats, I guess.",
"You're like a **Level {}** pebble in the vast ocean of talent. Keep striving!",
"**Level {}**? That's cute. Maybe one day you'll reach mediocrity.",
"Congratulations on **Level {}**! You must be so proud of yourself... or not.",
"A wild **Level {}** appears! Brace yourself for mild amusement.",
"Oh, **Level {}**! That's like a participation trophy, right?",
"Achievement unlocked: **Level {}**! Your parents must be thrilled.",
"Breaking news: **Level {}** has entered the chat! Prepare for underwhelming feats.",
"Welcome to **Level {}**, where average is the new extraordinary.",
"**Level {}**! Slow and steady wins the race... except when it comes to leveling up.",
"Congratulations on **Level {}**. Your progress is... mildly amusing.",
"Breaking news: **Level {}** has unlocked the 'Barely Trying' achievement!",
"Attention, **Level {}**! Your achievement is about as significant as a grain of sand.",
"Behold! **Level {}** has emerged from the shadows of insignificance.",
"You've unlocked the 'Bare Minimum' achievement at **Level {}**. Bravo!",
"Welcome to the realm of **Level {}**. Prepare for mild excitement.",
"Congratulations on your ascent to **Level {}**. It's a small step for mankind.",
"At **Level {}**, you're like a firework that fizzles out before it even begins.",
"**Level {}** has been reached! Commence the average dance of mild enthusiasm.",
"Alert! **Level {}** has been activated. Don't expect any fireworks.",
"Congratulations on reaching **Level {}**. Let the underwhelming festivities commence!",
"Rumor has it that reaching **Level {}** unlocks the ability to slightly impress others.",
"**Level {}** has been achieved! Brace yourself for a lukewarm round of applause.",
"You've made it to **Level {}**. Prepare for a dose of lukewarm recognition.",
"At **Level {}**, you're one step closer to the realm of mild accomplishment.",
"Rejoice! **Level {}** has been conquered, ushering in an era of moderate achievement.",
"**Level {}** is here! Your accomplishment might raise an eyebrow or two.",
"Congratulations on reaching **Level {}**. It's a humble feat, to say the least.",
"Behold, **Level {}**! Let the celebration be as mild as the achievement itself.",
"You've reached **Level {}**, where average becomes the new extraordinary.",
"Prepare to be mildly impressed. It's **Level {}**, the master of slight accomplishments.",
"Congratulations on unlocking the 'Just Getting Started' achievement at **Level {}**!",
"Welcome to **Level {}**. It's like a lukewarm bath for your achievements.",
]
level_10_to_20 = [
"Congratulations motherfucker you leveled the fuck up to **Level {}**.",
"levle **{}** cmoning in! Let's celbraet!",
"yay you reach the level **{}** waw you are so cool many time",
"omg senpai you weach wevew **{}**",
"reached **Level {}** but you'll never get on MY level HAAHAHAHAHA",
"*elevator music* Welcome to **level {}**.",
"Oh, look who's managed to crawl their way up to **Level {}**. Prepare for disappointment.",
"Congratulations on reaching the underwhelming heights of **Level {}**. Your achievements astound no one.",
"Ah, **Level {}**, where the bar is set so low even you can stumble over it.",
"Bravo on reaching **Level {}**. It must be exhausting exerting such minimal effort.",
"Welcome to the world of **Level {}**, where mediocrity is celebrated with empty enthusiasm.",
"You've unlocked the dubious achievement of **Level {}**. Prepare for the resounding sound of indifference.",
"Kudos on reaching **Level {}**. I'm sure the world will pause to celebrate this momentous occasion... just as "
"soon as it remembers you exist.",
"Prepare for the overwhelming roar of applause as you reach **Level {}**. Just kidding, it's more like the sound "
"of crickets chirping in disappointment."
"Behold, the prodigious talent of **Level {}**. Just kidding, there's nothing impressive about it.",
"Well, well, well, **Level {}**. Your accomplishments are as impressive as a deflated balloon.",
"Prepare for the parade in your honor, oh illustrious **Level {}**. Just kidding, no one cares.",
"Ah, **Level {}**, where dreams come to die a slow and painful death. Enjoy your stay.",
"Congratulations on reaching **Level {}**. Your insignificance knows no bounds.",
]
level_20_to_40 = [
"Oh my god! Did you set up a macro for this? You're **level {}**!",
"**Level {}**. If you don't stop leveling up... **I am going to commit a fucking war crime.**",
"**Level {}** 👍",
"Wow you're **level {}**. I regret not just using Tatsumaki bot for this.",
"**Level {}**. If you don't stop leveling up, I might have to stage an intervention. Discord addiction is real!",
"**Level {}**. Are you sure your life isn't just an elaborate Discord role-playing game?",
"Look who's slacking off work to level up on Discord. **Level {}** and counting!",
"**Level {}**? Have you considered that there might be an entire world outside of Discord?",
"Congratulations on reaching **level {}**. Your dedication to Discord is truly unparalleled.",
"Wow, you've climbed to **level {}**. Is Discord your full-time job now?",
"**Level {}**. I bet your parents are so proud of the countless hours you've spent on Discord.",
"Oh look, it's **level {}**! Are you sure you're not secretly a Discord bot in disguise?",
"Achievement unlocked: **level {}**! You must have broken Discord's leveling algorithm by now.",
"You've reached **level {}**. I hope you're using your Discord powers for good and not just spamming memes.",
"**Level {}** and still going strong. Who needs a social life when you have Discord, right?",
"Oh, **level {}**. I'm starting to think you might actually be a sentient Discord notification.",
"Congratulations on leveling up to **level {}**. I hope Discord gives you a lifetime supply of virtual cookies.",
"**Level {}**. At this rate, you'll surpass even the Discord founders in Discord addiction.",
"Look who's made it to **level {}**. I'm starting to think you're more Discord than human.",
"Wow, **level {}**! Do you ever wonder if Discord should be paying you a salary at this point?",
"Congratulations on reaching **level {}**. Your dedication to Discord is both awe-inspiring and mildly concerning.",
"You've unlocked the 'Master of Procrastination' achievement at **level {}**. Your parents must be so proud.",
"**Level {}**? I bet you have more Discord badges than real-life achievements.",
"Well, well, well, **level {}**. Your Discord addiction is reaching legendary status.",
]
level_40_to_60 = [
"You've reached **Level {}**. Stop. Just stop. You've had enough of this app. Go away.",
"TOUCH GRASS. You didn't deserve **Level {}** but here it is I guess..",
"I'm so tired of giving you levels. I'm not even going to say which level you just reached. Just kidding it's **Level {}**."
"Oh, look who's flexing their **Level {}** status. Don't strain a muscle.",
"Congratulations on reaching **Level {}**. Are you trying to make the rest of us feel inadequate?",
"Breaking news: **Level {}** has officially mastered the art of pressing buttons. Amazing.",
"Hats off to **Level {}**. Your dedication is truly admirable... or slightly concerning.",
"Are you okay...? **Level {}** is seriously unhealthy bro. Sleep.",
"STOP. LEVELING. LEAVE. ME. ALONE. Here's your damn level: **{}**"
"HAS REACHED **LEVEL {}**, FUCK YEAH."
"**Level {}**. The second-hand embarrassment is real."
]
level_above_60 = [
"You've weached **W-Wevew {}**. stawp. Just stawp. Y-Y-You've had enyough of this a-app. Go a-away.",
"TOUCH GWASS. Y-You didn't d-desewve **W-Wevew {}** but h-hewe it is I guess..",
"I'm so tiwed of giving you w-wevews. I'm nyot even going to say which wevew you just weached. Just kidding it's **{}**."
"Oh, wook who's fwexing theiw **W-Wevew {}** status. Don't stwain a muscwe.",
"Congwatuwations on weaching **W-Wevew {}**. Awe you twying to make the w-west of us feew inyadequate?",
"Bweaking nyews: **W-Wevew {}** has officiawwy wiciawwy mastewed the awt of pwessing buttons. Amazing.",
"Hats o-o-off to **W-Wevew {}**. Youw dedication is twuwy wuwy admiwabwe... ow swightwy wightwy concewnying.",
"Awe you okay...? **W-Wevew {}** i-is s-s-sewiouswy wewiouswy unheawthy weawthy bwo. Sweep.",
"STAWP. WEVEWING. WEAVE. ME. AWONYE. Hewe's youw dawn wevew: **{}**"
"HAS WEACHED **WEVEW {}**, FWICK YEAH."
"**Wevew {}**. The second-hand embawwassment is w-w-weaw."
]

19
sb_tools/reactions.py Normal file
View file

@ -0,0 +1,19 @@
import discord
trigger_list=[
"good bot",
"racu"
]
async def check_for_reaction(message):
content = message.content.lower()
# check if whole message = trigger
if content in trigger_list:
if content == trigger_list[0]:
await message.reply(content="Thanks!")
# check if trigger is in message
if trigger_list[1] in content:
await message.add_reaction("❤️")

5
sb_tools/resources.py Normal file
View file

@ -0,0 +1,5 @@
__title__ = "RCU"
__version__ = "1.2.17"
__author__ = "Esther J. J."
__author_email__ = "dokimakimaki@gmail.com"
__license__ = "GNU GENERAL PUBLIC LICENSE v2"

42
sb_tools/universal.py Normal file
View file

@ -0,0 +1,42 @@
import discord
from discord.ext import commands
from dotenv import load_dotenv
import os
load_dotenv('.env')
async def channel_check(ctx):
desired_channel_id = 1118587309365940407 # bot-chat in RCU
owner_id = os.getenv("OWNER_ID")
if ctx.channel.id != desired_channel_id and ctx.author.id != int(owner_id):
channel_mention = f"<#{desired_channel_id}>"
await ctx.respond(f"You can only do that command in {channel_mention}.", ephemeral=True)
return False
return True
async def beta_check(ctx):
owner_id = os.getenv("OWNER_ID")
if ctx.author.id != int(owner_id):
embed = discord.Embed(description=f"You can't use this command just yet! It's currently undergoing testing and "
f"fine-tuning to ensure the best experience for all users. Stay tuned for its "
f"official release.",
color=discord.Color.red())
await ctx.respond(embed=embed)
return False
return True
async def owner_check(ctx):
owner_id = os.getenv("OWNER_ID")
if ctx.author.id != int(owner_id):
embed = discord.Embed(description=f"Only Tess can do this command.",
color=discord.Color.red())
await ctx.respond(embed=embed)
return False
return True

20
sb_tools/xp_functions.py Normal file
View file

@ -0,0 +1,20 @@
def xp_needed_for_next_level(current_level):
formula_mapping = {
(10, 19): lambda level: 12 * level + 27,
(20, 29): lambda level: 15 * level + 27,
(30, 39): lambda level: 18 * level + 27,
(40, 49): lambda level: 21 * level + 27,
(50, 59): lambda level: 24 * level + 27,
(60, 69): lambda level: 27 * level + 27,
(70, 79): lambda level: 30 * level + 27,
(80, 89): lambda level: 33 * level + 27,
(90, 99): lambda level: 36 * level + 27,
(100, 109): lambda level: 39 * level + 27,
}
for level_range, formula in formula_mapping.items():
if level_range[0] <= current_level <= level_range[1]:
return formula(current_level)
# For levels below 10 and levels 110 and above
return 9 * current_level + 27 if current_level < 30 else 42 * current_level + 27