Example #1
0
def receive_watch_user(data: dict) -> bool:
    # Receive watch users that other bots shared
    try:
        # Basic data
        the_type = data["type"]
        uid = data["id"]
        until = data["until"]

        # Decrypt the data
        until = crypt_str("decrypt", until, glovar.key)
        until = get_int(until)

        # Add to list
        if the_type == "ban":
            glovar.watch_ids["ban"][uid] = until
        elif the_type == "delete":
            glovar.watch_ids["delete"][uid] = until
        else:
            return False

        save("watch_ids")

        return True
    except Exception as e:
        logger.warning(f"Receive watch user error: {e}", exc_info=True)

    return False
Example #2
0
def resolve_username(client: Client, username: str, cache: bool = True) -> (str, int):
    # Resolve peer by username
    peer_type = ""
    peer_id = 0
    try:
        username = username.strip("@")
        if not username:
            return "", 0

        result = glovar.usernames.get(username)
        if result and cache:
            return result["peer_type"], result["peer_id"]

        result = resolve_peer(client, username)
        if result:
            if isinstance(result, InputPeerChannel):
                peer_type = "channel"
                peer_id = result.channel_id
                peer_id = get_int(f"-100{peer_id}")
            elif isinstance(result, InputPeerUser):
                peer_type = "user"
                peer_id = result.user_id

        glovar.usernames[username] = {
            "peer_type": peer_type,
            "peer_id": peer_id
        }
    except Exception as e:
        logger.warning(f"Resolve username {username} error: {e}", exc_info=True)

    return peer_type, peer_id
Example #3
0
def unban(client: Client, message: Message) -> bool:
    # Unban a user

    if not message or not message.chat:
        return True

    # Basic data
    gid = message.chat.id
    mid = message.message_id

    try:
        # Check permission
        if not is_class_c(None, None, message):
            return True

        aid = message.from_user.id
        command_type, command_context = get_command_context(message)

        # Text prefix
        text = (
            f"{lang('admin')}{lang('colon')}{code(aid)}\n"
            f"{lang('action')}{lang('colon')}{code(lang('action_unban'))}\n")

        # Check command format
        if not command_type:
            text += (
                f"{lang('status')}{lang('colon')}{code(lang('status_failed'))}\n"
                f"{lang('reason')}{lang('colon')}{code(lang('command_usage'))}\n"
            )
            thread(send_report_message, (15, client, gid, text))
            return True

        # Get user id
        uid = get_int(command_context)
        if not uid:
            peer_type, peer_id = resolve_username(client, command_type)
            if peer_type == "user" and peer_id:
                uid = peer_id

        # Proceed
        if not uid:
            text += (
                f"{lang('status')}{lang('colon')}{code(lang('status_failed'))}\n"
                f"{lang('reason')}{lang('colon')}{code(lang('command_para'))}\n"
            )
            thread(send_report_message, (15, client, gid, text))
            return True

        # Proceed
        text = unban_user(client, message, uid, aid)
        thread(send_report_message, (30, client, gid, text))

        return True
    except Exception as e:
        logger.warning(f"Unban error: {e}", exc_info=True)
    finally:
        delete_message(client, gid, mid)

    return False
Example #4
0
def version(client: Client, message: Message) -> bool:
    # Check the program's version
    result = False

    try:
        # Basic data
        cid = message.chat.id
        aid = message.from_user.id
        mid = message.message_id

        # Get command type
        command_type = get_command_type(message)

        # Check the command type
        if command_type and command_type.upper() != glovar.sender:
            return False

        # Version info
        git_change = bool(
            run("git diff-index HEAD --", stdout=PIPE,
                shell=True).stdout.decode().strip())
        git_date = run("git log -1 --format='%at'", stdout=PIPE,
                       shell=True).stdout.decode()
        git_date = get_readable_time(get_int(git_date), "%Y/%m/%d %H:%M:%S")
        git_hash = run("git rev-parse --short HEAD", stdout=PIPE,
                       shell=True).stdout.decode()
        get_hash_link = f"https://github.com/scp-079/scp-079-{glovar.sender.lower()}/commit/{git_hash}"
        command_date = get_readable_time(message.date, "%Y/%m/%d %H:%M:%S")

        # Generate the text
        text = (
            f"{lang('admin')}{lang('colon')}{mention_id(aid)}\n\n"
            f"{lang('project')}{lang('colon')}{code(glovar.sender)}\n"
            f"{lang('version')}{lang('colon')}{code(glovar.version)}\n"
            f"{lang('本地修改')}{lang('colon')}{code(git_change)}\n"
            f"{lang('哈希值')}{lang('colon')}{general_link(git_hash, get_hash_link)}\n"
            f"{lang('提交时间')}{lang('colon')}{code(git_date)}\n"
            f"{lang('命令发送时间')}{lang('colon')}{code(command_date)}\n")

        # Send the report message
        result = send_message(client, cid, text, mid)
    except Exception as e:
        logger.warning(f"Version error: {e}", exc_info=True)

    return result
Example #5
0
def get_class_d_id(message: Message) -> (int, int):
    # Get Class D personnel's id
    uid = 0
    mid = 0

    try:
        r_message = message.reply_to_message

        if not r_message or not is_from_user(None, None, r_message):
            return 0, 0

        if not is_class_c(None, None, r_message):
            uid = r_message.from_user.id
            mid = r_message.message_id
        elif r_message.from_user.is_self:
            uid = get_int(
                r_message.text.split("\n")[0].split(lang("colon"))[1])

            if uid in glovar.admin_ids[message.chat.id]:
                uid = 0
    except Exception as e:
        logger.warning(f"Get class d id error: {e}", exc_info=True)

    return uid, mid
Example #6
0
def config_directly(client: Client, message: Message) -> bool:
    # Config the bot directly

    if not message or not message.chat:
        return True

    # Basic data
    gid = message.chat.id
    mid = message.message_id

    try:
        # Check permission
        if not is_class_c(None, None, message):
            return True

        aid = message.from_user.id
        success = True
        reason = lang("config_updated")
        new_config = deepcopy(glovar.configs[gid])
        text = f"{lang('admin_group')}{lang('colon')}{code(aid)}\n"

        # Check command format
        command_type, command_context = get_command_context(message)
        if command_type:
            if command_type == "show":
                text += f"{lang('action')}{lang('colon')}{code(lang('config_show'))}\n"
                text += get_config_text(new_config)
                thread(send_report_message, (30, client, gid, text))
                return True

            now = get_now()
            if now - new_config["lock"] > 310:
                if command_type == "default":
                    new_config = deepcopy(glovar.default_config)
                else:
                    if command_context:
                        if command_type in {"delete", "mention"}:
                            if command_context == "off":
                                new_config[command_type] = False
                            elif command_context == "on":
                                new_config[command_type] = True
                            else:
                                success = False
                                reason = lang("command_para")
                        elif command_type == "limit":
                            limit = get_int(command_context)
                            if 2 <= limit <= 5:
                                new_config["limit"] = limit
                            else:
                                success = False
                                reason = lang("command_para")
                        elif command_type == "report":
                            if not new_config.get("report"):
                                new_config["report"] = {}

                            if command_context == "off":
                                new_config["report"]["auto"] = False
                                new_config["report"]["manual"] = False
                            elif command_context == "auto":
                                new_config["report"]["auto"] = True
                                new_config["report"]["manual"] = False
                            elif command_context == "manual":
                                new_config["report"]["auto"] = False
                                new_config["report"]["manual"] = True
                            elif command_context == "both":
                                new_config["report"]["auto"] = True
                                new_config["report"]["manual"] = True
                            else:
                                success = False
                                reason = lang("command_para")
                        else:
                            success = False
                            reason = lang("command_type")
                    else:
                        success = False
                        reason = lang("command_lack")

                    if success:
                        new_config["default"] = False
            else:
                success = False
                reason = lang("config_locked")
        else:
            success = False
            reason = lang("command_usage")

        if success and new_config != glovar.configs[gid]:
            # Save new config
            glovar.configs[gid] = new_config
            save("configs")

            # Send debug message
            debug_text = get_debug_text(client, message.chat)
            debug_text += (
                f"{lang('admin_group')}{lang('colon')}{code(message.from_user.id)}\n"
                f"{lang('action')}{lang('colon')}{code(lang('config_change'))}\n"
                f"{lang('more')}{lang('colon')}{code(f'{command_type} {command_context}')}\n"
            )
            thread(send_message, (client, glovar.debug_channel_id, debug_text))

        text += (
            f"{lang('action')}{lang('colon')}{code(lang('config_change'))}\n"
            f"{lang('status')}{lang('colon')}{code(reason)}\n")
        thread(send_report_message,
               ((lambda x: 10 if x else 5)(success), client, gid, text))

        return True
    except Exception as e:
        logger.warning(f"Config directly error: {e}", exc_info=True)
    finally:
        delete_message(client, gid, mid)

    return False
Example #7
0
def report_answer(client: Client,
                  message: Message,
                  gid: int,
                  aid: int,
                  mid: int,
                  action_type: str,
                  key: str,
                  reason: str = None) -> str:
    # Answer the user's report
    try:
        report_record = glovar.reports.get(key)

        if not report_record:
            message_text = get_text(message)
            uid = get_int(message_text.split("\n")[0].split(lang("colon"))[1])
            text = (
                f"{lang('description')}{lang('colon')}{code(lang('description_by_admin'))}\n"
                f"{lang('status')}{lang('colon')}{code(lang('status_failed'))}\n"
                f"{lang('reason')}{lang('colon')}{code(lang('expired'))}\n")
            thread(edit_message_text, (client, gid, mid, text))
            delay(15, delete_message, [client, gid, mid])
            glovar.user_ids[uid]["waiting"].discard(gid)
            save("user_ids")
            return ""

        if not report_record["time"]:
            return ""

        rid = report_record["reporter_id"]
        uid = report_record["user_id"]
        r_mid = report_record["message_id"]
        record_reason = report_record["reason"]

        if not reason:
            reason = record_reason

        if not (init_user_id(rid) and init_user_id(uid)):
            return ""

        # Check users' locks
        if gid in glovar.user_ids[uid]["lock"] or gid in glovar.user_ids[rid][
                "lock"]:
            return lang("answer_proceeded")

        # Lock the report status
        glovar.reports[key]["time"] = 0
        try:
            if action_type == "ban":
                text, markup = ban_user(client, message, uid, aid, 0, reason)
                thread(delete_message, (client, gid, r_mid))
            elif action_type == "warn":
                text, markup = warn_user(client, message, uid, aid, reason)
                thread(delete_message, (client, gid, r_mid))
            elif action_type == "abuse":
                if not rid:
                    return ""

                message.reply_to_message.from_user.id = rid
                message.reply_to_message.from_user.is_self = lang(
                    "abuse_report")
                text, markup = warn_user(client, message, rid, aid)
                text += f"{lang('reason')}{lang('colon')}{code(lang('reason_abuse'))}\n"
            else:
                reported_link = general_link(
                    r_mid, f'{get_channel_link(message)}/{r_mid}')

                if rid:
                    reporter_text = code(rid)
                else:
                    reporter_text = code(lang("auto_triggered"))

                text = (
                    f"{lang('reported_user')}{lang('colon')}{mention_id(uid)}\n"
                    f"{lang('reported_message')}{lang('colon')}{reported_link}\n"
                    f"{lang('reporter')}{lang('colon')}{reporter_text}\n"
                    f"{lang('action')}{lang('colon')}{code(lang('action_cancel'))}\n"
                    f"{lang('status')}{lang('colon')}{code(lang('status_succeeded'))}\n"
                    f"{lang('description')}{lang('colon')}{code(lang('description_by_admin'))}\n"
                )
                markup = None

            if markup:
                secs = 180
            else:
                secs = 15

            thread(edit_message_text, (client, gid, mid, text, markup))
            delay(secs, delete_message, [client, gid, mid])
        finally:
            glovar.user_ids[uid]["lock"].discard(gid)
            glovar.user_ids[rid]["lock"].discard(gid)
            glovar.user_ids[uid]["waiting"].discard(gid)
            glovar.user_ids[rid]["waiting"].discard(gid)
            save("user_ids")
    except Exception as e:
        logger.warning(f"Report answer error: {e}", exc_info=True)

    return ""
Example #8
0
# Config session
app = Client(
    session_name="bot",
    ipv6=glovar.ipv6,
    bot_token=glovar.bot_token,
    workdir=glovar.SESSION_DIR_PATH,
    config_file=glovar.CONFIG_PATH,
    sleep_threshold=0
)
app.start()

# Start the bot
delay(10, restart_program, [app, glovar.creator_id])

# Start update
sleep(glovar.interval)
interval_sec_n(app)

# Timer
scheduler = BackgroundScheduler(job_defaults={"misfire_grace_time": 60})
scheduler.add_job(interval_min_10, "interval", minutes=10)
scheduler.add_job(log_rotation, "cron", hour=23, minute=59)
scheduler.add_job(restart_program, "cron", [app], hour=glovar.restart, minute=get_int(glovar.restart_text))
scheduler.start()

# Hold
idle()

# Stop
app.stop()