def main(): logging.basicConfig( level=logging.DEBUG if Config()["DEBUG"] else logging.INFO) Bot(Config()["TELEGRAM_API_TOKEN"]) from bot import start from bot import splitit aiogram.executor.start_polling(Bot().dispatcher, skip_updates=True)
def main(): # Read config conf = Config().config # Connect to MySQL asyncio.get_event_loop().run_until_complete(Db().create( host=conf["DB_HOST"], port=conf["DB_PORT"], username=conf["DB_USERNAME"], password=conf["DB_PASSWORD"], database=conf["DB_DATABASE"], maxsize=conf["DB_POOL_SIZE"])) # Initialize sentry if Config().config["SENTRY_DSN"] != "": SentryClient(conf["SENTRY_DSN"], enable_breadcrumbs=True, transport=ThreadedHTTPTransport, string_max_length=8192) else: print("Sentry logging disabled") # Initialize bot bot = Bot(conf["TELEGRAM_API_TOKEN"]) from commands import start from commands import meme from commands import chatid from commands import callback print("Click da circlez") bot.run()
async def call(self, endpoint, params): if not self.session: self.session = aiohttp.ClientSession() params["k"] = Config()["osu"]["api_key"] async with self.session.get("%s%s" % (Config()["osu"]["api_url"], endpoint), params=params) as resp: return await resp.json()
def __init__(self): self.database = PooledMySQLDatabase( Config()['sql']['db'], user=Config()['sql']['user'], password=Config()['sql']['password'], host=Config()['sql']['host'], port=int(Config()['sql']['port']), max_connections=10) self.objects = Manager(self.database, loop=asyncio.get_event_loop()) self.objects.database.allow_sync = False self.user_locks = defaultdict(asyncio.Lock)
async def get_pp_spread(beatmap_id, enabled_mods, combo=None): # get spread (95, 98, 99, 100 acc pps) await ensure_map_exists(beatmap_id) ez = ezpp_new() ezpp_set_autocalc(ez, 1) ezpp_dup(ez, '%s/%s.osu' % (Config()['oppai']['map_dir'], beatmap_id)) if enabled_mods & 4: ezpp_set_mods(ez, enabled_mods ^ 64) ezpp_set_mods(ez, enabled_mods) if combo: ezpp_set_combo(ez, combo) ezpp_set_accuracy_percent(ez, 95) pp95 = ezpp_pp(ez) ezpp_set_accuracy_percent(ez, 98) pp98 = ezpp_pp(ez) ezpp_set_accuracy_percent(ez, 99) pp99 = ezpp_pp(ez) ezpp_set_accuracy_percent(ez, 100) pp100 = ezpp_pp(ez) stars = ezpp_stars(ez) ar = ezpp_ar(ez) od = ezpp_od(ez) ezpp_free(ez) return pp95, pp98, pp99, pp100, stars, ar, od
async def last(request): resp = {} try: secret = request.headers.get("Secret", None) if secret is None or secret != Config()["INTERNAL_API_SECRET"]: raise FokaAPIError(403, "Forbidden") request_data = await request.json() if "user_id" not in request_data: raise FokaAPIError(400, "Missing required arguments.") users = await Bot().ripple_api_client.get_user( user_id=request_data["user_id"]) if users is None or not users: raise FokaAPIError(404, "No such user") username = users[0]["username"] msg = await pp.last_inner(username, pm=True) Bot().send_message(msg, username) resp = {"code": 200, "message": "ok"} except FokaAPIError as e: resp = {"code": e.status, "message": e.message} except: resp = {"code": 500, "message": "Internal server error"} traceback.print_exc() finally: code = resp["code"] if "code" in resp else 200 return web.json_response(resp, status=code)
async def ensure_map_exists(beatmap_id): path = '%s/%s.osu' % (Config()['oppai']['map_dir'], beatmap_id) try: stat = await aiofiles.os.stat(path) except FileNotFoundError: return await download_map(beatmap_id) if stat.st_size == 0: return await download_map(beatmap_id)
async def download_map(beatmap_id): path = '%s/%s.osu' % (Config()['oppai']['map_dir'], beatmap_id) async with aiohttp.ClientSession() as session: async with session.get('https://osu.ppy.sh/osu/%s' % beatmap_id) as resp: if resp.status == 200: f = await aiofiles.open(path, mode='wb') await f.write(await resp.read()) await f.close()
async def connect_db(): print("=> Connecting to database") # Connect to database and create table if needed await Database().connect(Config()["DB_DSN"], loop=asyncio.get_event_loop()) await Database().execute(""" CREATE TABLE IF NOT EXISTS `banned_words` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `word` TEXT UNIQUE );""") # Load forbidden words await WordsCache().reload()
async def handle(request: Request, *, params): ok_response = web.json_response({"message": "ok"}) logging.debug("Requested password reset for {}".format(params["email"])) async with EmaNews().db.acquire() as conn: async with conn.cursor() as cur: await cur.execute( "SELECT * FROM users WHERE email = %s AND privileges & 2 > 0 LIMIT 1", (params["email"], )) db_user = await cur.fetchone() if not db_user: logging.debug("Failed silently") return ok_response # Cancella token scaduti per questo utente await cur.execute( "DELETE FROM password_reset_tokens WHERE `expire` <= UNIX_TIMESTAMP() AND user_id = %s", (db_user["id"])) # Recupera eventuale token esistente await cur.execute( "SELECT token FROM password_reset_tokens WHERE user_id = %s AND `expire` > UNIX_TIMESTAMP() LIMIT 1", (db_user["id"], )) db_token = await cur.fetchone() if not db_token: # Nessun token, generane uno logging.debug("Generating new token") token = general.random_string_secure(64) await cur.execute( "INSERT INTO password_reset_tokens (user_id, token, `expire`) " "VALUES (%s, %s, UNIX_TIMESTAMP() + 3600)", (db_user["id"], token)) await conn.commit() else: # Token esistente logging.debug("Using pre-existing token") token = db_token["token"] # Invia email await EmaNews().mailgun_client.send( to=params["email"], subject="Recupero password EmaNews", html= "Clicca sul seguente link per reimpostare la tua password del tuo account EmaNews: " "<a href='{}/password_reset/{}'>Reimposta password</a>.<br>" "Il link scade tra 60 minuti. Se non sei stato tu a richiedere il reset " "della tua password, ignora questa email.".format( Config()["WEB_BASE_URL"].rstrip("/"), token)) return ok_response
async def post(request: Request, *, params): async with EmaNews().db.acquire() as conn: async with conn.cursor() as cur: # Controlla se l'indirizzo email è stato già usato await cur.execute("SELECT id FROM users WHERE email = %s LIMIT 1", (params["email"],)) other_user = await cur.fetchone() if other_user: # Già usato raise ConflictError("Esiste già un altro utente registrato con questo indirizzo email.") # Ok, hash password con bcrypt bcrypted_password = bcrypt.hashpw(params["password"], bcrypt.gensalt()) # Insert in db await cur.execute( "INSERT INTO users (name, surname, email, password, privileges) " "VALUES (%s, %s, %s, %s, %s)", ( params["name"], params["surname"], params["email"], bcrypted_password.decode(), int(Privileges.PENDING_ACTIVATION) ) ) # Genera e salva token attivazione account token = general.random_string_secure(64) await cur.execute("INSERT INTO activation_tokens (user_id, token) VALUES (%s, %s)", (cur.lastrowid, token)) await conn.commit() # Invio email await EmaNews().mailgun_client.send( to=params["email"], subject="Conferma il tuo account EmaNews", html="Clicca sul seguente link per attivare il tuo account EmaNews: " "<a href='{}/activate/{}'>Attiva account</a>".format( Config()["WEB_BASE_URL"].rstrip("/"), token ) ) # Ok! return web.json_response({ "message": "ok" })
async def get_pps(beatmap_id, enabled_mods, maxcombo, countmiss, count50, count100): # returns total_pp, aim_pp, speed_pp, acc_pp await ensure_map_exists(beatmap_id) ez = ezpp_new() ezpp_set_mods(ez, enabled_mods) if maxcombo: ezpp_set_combo(ez, maxcombo) if countmiss: ezpp_set_nmiss(ez, countmiss) if count100 and count50: ezpp_set_accuracy(ez, count100, count50) ezpp(ez, '%s/%s.osu' % (Config()['oppai']['map_dir'], beatmap_id)) ret = (ezpp_pp(ez), ezpp_aim_pp(ez), ezpp_speed_pp(ez), ezpp_acc_pp(ez)) ezpp_free(ez) return ret
def main(): logging.getLogger("aiohttp").setLevel(logging.CRITICAL) logging.getLogger().setLevel(logging.DEBUG if Config()["DEBUG"] else logging.INFO) # Debug alert if Config()["DEBUG"]: logging.debug("Running in debug mode") if Config()["SINGLE_PLAYER"]: logging.debug("Running in single player mode") # ASCII art print(HEADER) # Load words storage WordsStorage().load() # Create sio and aiohttp server app = web.Application() Sio().attach(app) # Load SSL context cert_path = Config()["SSL_CERT"] key_path = Config()["SSL_KEY"] if cert_path and key_path and os.path.isfile(cert_path) and os.path.isfile(key_path): logging.info("Using SSL") ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) ssl_context.load_cert_chain(Config()["SSL_CERT"], Config()["SSL_KEY"]) else: logging.warning("SSL is disabled!") ssl_context = None # Start server web.run_app( app, host=Config()["SIO_HOST"], port=Config()["SIO_PORT"], ssl_context=ssl_context )
async def join_client(self, client): """ Adds a client to the match and notifies match and lobby :param client: `Client` object :return: """ if self.playing: raise RuntimeError("The game is in progress!") if type(client) is not Client: raise TypeError("`client` must be a Client object") # if client in self.clients: # raise ValueError("This client is already in that lobby") # Make sure the room is not completely full if len(self.slots) >= self.max_players: await Sio().emit("game_join_fail", {"message": "La partita è piena"}, room=client.sid) return # Add the client to this match's clients self.slots.append(Slot(client, host=len(self.slots) == 0)) # Enter sio room Sio().enter_room(client.sid, self.sio_room) # Bind client to this game await client.join_game(self) # Notify joined client await Sio().emit("game_join_success", {"game_id": self.uuid}, room=client.sid) # Notify other clients (if this is not the first one joining aka the one creating the room) # await Sio().emit("client_joined", room=self.sio_room, skip_sid=client.sid) if len(self.slots) > 0: await self.notify_game() # Notify lobby if public await self.notify_lobby() logging.info("{} joined game {}".format(client.sid, self.uuid)) if Config()["SINGLE_PLAYER"]: await self.start()
async def send_message(request): resp = {} try: secret = request.headers.get("Secret", None) if secret is None or secret != Config()["INTERNAL_API_SECRET"]: raise FokaAPIError(403, "Forbidden") request_data = await request.json() if "message" not in request_data or "target" not in request_data: raise FokaAPIError(400, "Missing required arguments.") Bot().send_message(request_data["message"], request_data["target"]) resp = {"code": 200, "message": "ok"} except FokaAPIError as e: resp = {"code": e.status, "message": e.message} except: resp = {"code": 500, "message": "Internal server error"} traceback.print_exc() finally: code = resp["code"] if "code" in resp else 200 return web.json_response(resp, status=code)
async def start(self): """ Starts the game :return: """ if len(self.slots) > 1 and all([x.ready for x in self.slots ]) or Config()["SINGLE_PLAYER"]: # Game starts self.playing = True # Remove game from lobby await self.notify_lobby_dispose() # First level await self.next_level() # Notify all clients await Sio().emit("game_started", room=self.sio_room) else: raise RuntimeError("Conditions not met for game to start")
async def get_pp(beatmap_id, enabled_mods, accuracy, combo=None): # returns total_pp for a specific accuracy await ensure_map_exists(beatmap_id) ez = ezpp_new() ezpp_set_autocalc(ez, 1) ezpp_dup(ez, '%s/%s.osu' % (Config()['oppai']['map_dir'], beatmap_id)) if enabled_mods & 4: ezpp_set_mods(ez, enabled_mods ^ 64) ezpp_set_mods(ez, enabled_mods) if combo: ezpp_set_combo(ez, combo) ezpp_set_accuracy_percent(ez, accuracy) pp = ezpp_pp(ez) stars = ezpp_stars(ez) ar = ezpp_ar(ez) od = ezpp_od(ez) ezpp_free(ez) return pp, stars, ar, od
def main() -> None: # Logging logging.basicConfig( level=logging.DEBUG if Config()["DEBUG"] else logging.INFO) logging.info(""" __ _ / _| | | | |_ ___ | | ____ ___ _____ ___ ___ | _/ _ \\| |/ / _` \\ \\ /\\ / / _ \\ / _ \\ / _ \\ | || (_) | < (_| |\\ V V / (_) | (_) | (_) | |_| \\___/|_|\\_\\__,_| \\_/\\_/ \\___/ \\___/ \\___/ """) # Setup Bot singleton if use_uvloop: uvloop.install() logging.info("Using uvloop") else: logging.warning("Using asyncio") Bot( wss=Config()["WSS"], nickname=Config()["BOT_NICKNAME"], commands_prefix=Config()["COMMANDS_PREFIX"], bancho_api_client=BanchoApiClient(Config()["BANCHO_API_TOKEN"], Config()["BANCHO_API_BASE"]), ripple_api_client=RippleApiClient(Config()["RIPPLE_API_TOKEN"], Config()["RIPPLE_API_BASE"]), lets_api_client=LetsApiClient(Config()["LETS_API_BASE"]), cheesegull_api_client=CheesegullApiClient( Config()["CHEESEGULL_API_BASE"]), osu_api_client=OsuAPIClient(Config()["OSU_API_TOKEN"]), misirlou_api_client=MisirlouApiClient( Config()["MISIRLOU_API_TOKEN"], Config()["MISIRLOU_API_BASE"], ), http_host=Config()["HTTP_HOST"], http_port=Config()["HTTP_PORT"], redis_host=Config()["REDIS_HOST"], redis_port=Config()["REDIS_PORT"], redis_database=Config()["REDIS_DATABASE"], redis_password=Config()["REDIS_PASSWORD"], redis_pool_size=Config()["REDIS_POOL_SIZE"], tinydb_path=Config()["TINYDB_PATH"], ) # Register all events import events # Import all required plugins (register bot commands) for plugin in Config()["BOT_PLUGINS"]: imported_plugin = importlib.import_module(f"plugins.{plugin}") if hasattr(imported_plugin, "init"): logging.debug(f"Plugin {plugin} has init hook.") Bot().init_hooks.append( InitHook(plugin, getattr(imported_plugin, "init"))) Bot().logger.info(f"Loaded plugin plugins.{plugin}") # Finally, run the bot Bot().run()
from cogs.welcome import Welcome from singletons.bot import Bot from singletons.config import Config if __name__ == "__main__": logging.getLogger("discord").setLevel(logging.ERROR) logging.basicConfig(level=logging.INFO) logging.info("""\n _ _ _ ___| |_ ___ _| |_| |___ _ _ _ _ | . | | -_| . | . | .'| | |_'_| |_ |_|_|___|___|___|__,|___|_,_| |___| Gheddaux - Made by Nyo""") bot = Bot(command_prefix=";", allowed_server_ids=Config()["SERVER_IDS"], log_channel_id=Config()["LOG_CHANNEL_ID"], welcome_channel_id=Config()["WELCOME_CHANNEL_ID"], reports_user_channel_id=Config()["REPORTS_USER_CHANNEL_ID"], reports_admin_channel_id=Config()["REPORTS_ADMIN_CHANNEL_ID"], db_file=Config()["DB_FILE"]).bot @bot.event async def on_command_error(ctx, exception) -> None: # I don't even want to know why the f**k I have to do this in the first place try: raise exception except: Bot().logger.exception("An unhandled exception has been raised.") if Bot().welcome_channel_id:
await Database().execute("DELETE FROM banned_words WHERE word = ? LIMIT 1", [word]) await WordsCache().reload() # Bot's reply await bot.say("**{}** isn't censored anymore!".format(word)) @bot.command(pass_context=True, no_pm=True) @checks.admin_only() async def censoredwords(ctx, word=None): await bot.say("**Censored words:** {}".format(", ".join(WordsCache()))) try: print("""\033[92m _ _ _ ___ ___ ___|_| |_ ___| |_ | | .'|- _| | . | . | _| |_|_|__,|___|_|___|___|_| Nazi Bot - Made by Nyo\033[0m\n""") print("=> Logging in") bot.loop.run_until_complete(connect_db()) bot.loop.run_until_complete(bot.start(Config()["BOT_TOKEN"])) except KeyboardInterrupt: print("=> Disposing bot") bot.loop.run_until_complete(bot.logout()) bot.loop.run_until_complete(Database().dispose()) finally: bot.loop.close() print("=> Bot stopped, goodbye!")
async def generate_instruction(self, slot, expired=None, stop_old_task=True): """ Generates and sets a valid and unique Instruction for `Slot` and schedules an asyncio Task to run :param slot: `Slot` object that will be the target of that instruction :param stop_old_task: if `True`, stop the old generation task. Set to `False` if running in the generation loop, `True` if calling from outside the loop. :param expired: Send this to the client with the new instruction. If `True`, the old instruction expired. If `False`, the old instruction was successful. If `None` (or not present), not specified. The client will play sounds and visual fx accordingly. :return: """ # Stop the old next generation task if needed if slot.next_generation_task is not None and stop_old_task: slot.next_generation_task.cancel() old_instruction = slot.instruction # Choose between an asteroid/black hole or normal command command = None if random.random() < self.difficulty[ "asteroid_chance"] and slot.special_command_cooldown <= 0: # Asteroid, force target and command target = None command = DummyAsteroidCommand() slot.special_command_cooldown = self.difficulty[ "special_command_cooldown"] + 1 elif random.random() < self.difficulty[ "black_hole_chance"] and slot.special_command_cooldown <= 0: # Black hole, force target and command target = None command = DummyBlackHoleCommand() slot.special_command_cooldown = self.difficulty[ "special_command_cooldown"] + 1 elif Config()["SINGLE_PLAYER"]: # Single player debug mode, force target only target = slot else: # Normal, choose a target # Choose a random slot and a random command. # We don't do this in `Instruction` because we need to access # match's properties and passing match and next_levelinstruction to `Instruction` is not elegant imo if random.randint(0, 5) == 0: # 1/5 chance of getting a command in our grid target = slot else: # Filter out our slot and chose another one randomly target = random.choice( list(filter(lambda z: z != slot, self.slots))) # Decrease special command cooldown slot.special_command_cooldown = max(0, slot.special_command_cooldown - 1) logging.debug("SPECIAL {}".format(slot.special_command_cooldown)) # Generate a command if needed if command is None: # Find a random command that is not used in any other instructions at the moment and is not the same as the # previous one valid_command = False while not valid_command: valid_command = True command = random.choice(target.grid.objects) print(self.instructions + [slot.instruction]) print(slot.instruction) for x in self.instructions + [slot.instruction]: # x is `None` if slot.instructions is None (first generation) if x is not None and x.target_command == command: valid_command = False break # Set this slot's instruction and notify the client slot.instruction = Instruction(slot, target, command) # Add new one self.instructions.append(slot.instruction) # Notify the client about the new command and the status of the old command await Sio().emit("command", { "text": slot.instruction.text, "time": self.difficulty["instructions_time"], "expired": expired, }, room=slot.client.sid) if old_instruction is not None and issubclass( type(old_instruction.target_command), SpecialCommand): await Sio().emit("safe", room=self.sio_room) # Schedule a new generation slot.next_generation_task = asyncio.Task( self.schedule_generation(slot, self.difficulty["instructions_time"]))
async def callback(chat, cq): if cq.data == "referral": # Check if we have already used this account ref = await Db().fetch("SELECT referrals.* FROM invited LEFT JOIN referrals " "ON invited.referral_id = referrals.id WHERE invited.telegram_id = %s LIMIT 1", [cq.src["from"]["id"]]) # Remove last two lines and reply keyboard markup await chat.edit_text( cq.src["message"]["message_id"], "\n".join(cq.src["message"]["text"].split("\n")[:-2]).strip(), markup={} ) # Send new message with inline query keyboard if ref is None: # New user await chat.send_text(text.INSTRUCTIONS_WARNING, parse_mode="markdown", reply_markup=json.dumps({ "inline_keyboard": [[{ "text": emojize( ":white_check_mark: Ho tutto pronto, dimmi cosa fare!", use_aliases=True ), "callback_data": "start" }], [{ "text": emojize(":thinking_face: Ci devo ancora pensare..."), "callback_data": "stop" }]] }), disable_web_page_preview=True) else: # Already used await chat.send_text(text.ALREADY_USED, parse_mode="markdown") elif cq.data == "start": # Check if we have already used a referral ref = await Db().fetch("SELECT referrals.* FROM invited LEFT JOIN referrals " "ON invited.referral_id = referrals.id WHERE invited.telegram_id = %s LIMIT 1", [cq.src["from"]["id"]]) if ref is None: # Get referral index referral_index = await Db().fetch("SELECT latest_referral FROM latest_referral WHERE 1 LIMIT 1") referral_index = referral_index["latest_referral"] # Increment referral index await Db().execute("UPDATE latest_referral SET latest_referral = (latest_referral + 1) %% " "(SELECT COUNT(*) FROM referrals WHERE 1 LIMIT 1) WHERE 1 LIMIT 1") ref = await Db().fetch("SELECT * FROM referrals WHERE 1 LIMIT 1 OFFSET {}".format(referral_index)) # Insert invited await Db().execute("INSERT INTO invited (id, telegram_id, `time`, referral_id) VALUES (NULL, %s, %s, %s)", [ cq.src["from"]["id"], int(time.time()), ref["id"] ]) # Send message to referral await bot.send_message(ref["telegram_id"], text.ADMIN_REFERRAL_NOTIFY.format( cq.src["from"]["first_name"] if "first_name" in cq.src["from"] else "Boh", cq.src["from"]["last_name"] if "last_name" in cq.src["from"] else "Boh", cq.src["from"]["username"] if "username" in cq.src["from"] else "boh", cq.src["from"]["id"]), parse_mode="markdown") # Send message await chat.edit_text(cq.src["message"]["message_id"], text.INSTRUCTIONS.format(code=ref["referral"]), markup={ "inline_keyboard": [[{ "text": emojize(":money_with_wings: Registrati e ricevi 5€ gratis"), "url": "https://www.circle.com/invite/{}".format(ref["referral"]) }], [{ "text": emojize(":thumbs_up: Ho ricevuto i miei 5€!"), "callback_data": "done" }]] }, parse_mode="markdown") else: # This user has already used a referral await chat.send_text(text.ALREADY_USED, parse_mode="markdown") elif cq.data == "done": # Make sure we have used a referral ref = await Db().fetch("SELECT referrals.* FROM invited LEFT JOIN referrals " "ON invited.referral_id = referrals.id WHERE invited.telegram_id = %s LIMIT 1", [cq.src["from"]["id"]]) if ref is None: return # Kick from main group try: await Chat(bot, Config().config["GROUP_ID"]).kick_chat_member(cq.src["from"]["id"]) except: pass # Bastardata await chat.edit_text(cq.src["message"]["message_id"], text.DONE, parse_mode="markdown") elif cq.data == "stop": # Make sure we have already used a referral ref = await Db().fetch("SELECT referrals.* FROM invited LEFT JOIN referrals " "ON invited.referral_id = referrals.id WHERE invited.telegram_id = %s LIMIT 1", [cq.src["from"]["id"]]) if ref is None: await chat.edit_text(cq.src["message"]["message_id"], text.STOP, parse_mode="markdown")
from time import strftime, gmtime from recommend.maps import find_map, CouldNotFindMapException from recommend.beatmap import Beatmap, get_beatmap_by_id from recommend.pp import get_pp_spread from recommend.target import target, widen_target from recommend.user import get_user_best from singletons.config import Config config = Config() class Recommendation(Beatmap): def __init__(self, beatmap_id, beatmap, enabled_mods, future_you, pp_95, pp_98, pp_99, pp_100, stars, ar, od): super().__init__(beatmap_id, beatmap, enabled_mods, stars, ar, od) self.future_you = future_you self.pp_95 = pp_95 self.pp_98 = pp_98 self.pp_99 = pp_99 self.pp_100 = pp_100 @classmethod async def get(cls, criteria): user_best = await get_user_best(criteria.user) criteria.targets = await target(user_best) try: beatmap_id, enabled_mods, future_you = await find_map(criteria) except CouldNotFindMapException: widen_target(criteria.targets) # if it still can't find a map, the exception will be raised to the recommend handler.