コード例 #1
0
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)
コード例 #2
0
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()
コード例 #3
0
 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()
コード例 #4
0
ファイル: db.py プロジェクト: goeo-/memebot-2.0
    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)
コード例 #5
0
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
コード例 #6
0
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)
コード例 #7
0
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)
コード例 #8
0
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()
コード例 #9
0
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()
コード例 #10
0
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
コード例 #11
0
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"
    })
コード例 #12
0
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
コード例 #13
0
ファイル: spaceteam.py プロジェクト: openspaceteam/backend
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
    )
コード例 #14
0
ファイル: game.py プロジェクト: openspaceteam/backend
    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()
コード例 #15
0
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)
コード例 #16
0
ファイル: game.py プロジェクト: openspaceteam/backend
    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")
コード例 #17
0
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
コード例 #18
0
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()
コード例 #19
0
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:
コード例 #20
0
    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!")
コード例 #21
0
ファイル: game.py プロジェクト: openspaceteam/backend
    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"]))
コード例 #22
0
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")
コード例 #23
0
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.