Exemplo n.º 1
0
async def screenshot(_, message: Message):
    await asyncio.gather(
        message.delete(),
        UserBot.send(
            functions.messages.SendScreenshotNotification(
                peer=await UserBot.resolve_peer(message.chat.id),
                reply_to_msg_id=0,
                random_id=UserBot.rnd_id(),
            )
        )
    )
Exemplo n.º 2
0
async def restart(bot: UserBot, message: Message):
    await message.edit(f"Restarting {UserBot.__class__.__name__}.")
    await bot.send_message(
        "me", f"#userbot_restart, {message.chat.id}, {message.message_id}")

    if "p" in message.text and "g" in message.text:
        asyncio.get_event_loop().create_task(
            UserBot.restart(git_update=True, pip=True))
    elif "p" in message.text:
        asyncio.get_event_loop().create_task(UserBot.restart(pip=True))
    elif "g" in message.text:
        asyncio.get_event_loop().create_task(UserBot.restart(git_update=True))
    else:
        asyncio.get_event_loop().create_task(UserBot.restart())
Exemplo n.º 3
0
async def restart(bot: UserBot, message: Message):
    await message.edit(f"Restarting {UserBot.__name__}.")
    await bot.send_message(
        'me', f'#userbot_restart, {message.chat.id}, {message.message_id}')

    if 'p' in message.text and 'g' in message.text:
        asyncio.get_event_loop().create_task(
            bot.restart(git_update=True, pip=True))
    elif 'p' in message.text:
        asyncio.get_event_loop().create_task(bot.restart(pip=True))
    elif 'g' in message.text:
        asyncio.get_event_loop().create_task(bot.restart(git_update=True))
    else:
        asyncio.get_event_loop().create_task(bot.restart())
Exemplo n.º 4
0
    def __init__(self, token, group_id, debug=True):
        Vk.__init__(self, token=token, group_id=group_id, debug=debug)
        self.messages_to_delete = {}
        self.userbot = UserBot()
        self.debug = True

        base = BetterBotBase("users", "dat")
        base.addPattern("karma", 0)
        base.addPattern("programming_languages", [])
        base.addPattern("github_profile", "")
        base.addPattern("supporters", [])
        base.addPattern("opponents", [])
        base.addPattern("last_collective_vote", 0)

        self.base = base
Exemplo n.º 5
0
async def unsplash_pictures(bot: UserBot, message: Message):
    cmd = message.command

    if len(cmd) > 1 and isinstance(cmd[1], str):
        keyword = cmd[1]

        if len(cmd) > 2 and int(cmd[2]) < 10:
            await message.edit("```Getting Pictures```")
            count = int(cmd[2])
            images = []
            while len(images) is not count:
                img = await AioHttp().get_url(
                    f"https://source.unsplash.com/1600x900/?{keyword}")
                if img not in images:
                    images.append(img)

            for img in images:
                await bot.send_photo(message.chat.id, str(img))

            await message.delete()
            return
        else:
            await message.edit("```Getting Picture```")
            img = await AioHttp().get_url(
                f"https://source.unsplash.com/1600x900/?{keyword}")
            await asyncio.gather(message.delete(),
                                 bot.send_photo(message.chat.id, str(img)))
Exemplo n.º 6
0
async def quotly(_, message: Message):
    if not message.reply_to_message:
        await message.edit("Reply to any users text message")
        return
    await message.edit("```Making a Quote```")
    await message.reply_to_message.forward("@QuotLyBot")
    is_sticker = False
    progress = 0
    while not is_sticker:
        try:
            msg = await UserBot.get_history("@QuotLyBot", 1)
            check = msg[0]["sticker"]["file_id"]
            is_sticker = True
        except:
            await sleep(0.5)
            progress += random.randint(0, 10)
            try:
                await message.edit(
                    "```Making a Quote```\nProcessing {}%".format(progress))
            except:
                await message.edit("ERROR SUUUU")
    if msg_id := msg[0]['message_id']:
        await asyncio.gather(
            message.delete(),
            UserBot.forward_messages(message.chat.id, "@QuotLyBot", msg_id))
Exemplo n.º 7
0
async def paste(_, message: Message):
    text = message.reply_to_message.text
    try:
        async with aiohttp.ClientSession() as session:
            async with session.post(
                    'https://nekobin.com/api/documents',
                    json={"content": text},
                    timeout=3
            ) as response:
                key = (await response.json())["result"]["key"]
    except Exception:
        await message.edit_text("`Pasting failed`")
        await asyncio.sleep(2)
        await message.delete()
        return
    else:
        url = f'https://nekobin.com/{key}'
        reply_text = f'Nekofied to **Nekobin** : {url}'
        delete = True if len(message.command) > 1 \
                         and message.command[1] in ['d', 'del'] \
                         and message.reply_to_message.from_user.is_self else False
        if delete:
            await asyncio.gather(
                UserBot.send_message(message.chat.id, reply_text, disable_web_page_preview=True),
                message.reply_to_message.delete(),
                message.delete()
            )
        else:
            await message.edit_text(
                reply_text,
                disable_web_page_preview=True,
            )
Exemplo n.º 8
0
async def mark_chat_unread(_, message: Message):
    await asyncio.gather(
        message.delete(),
        UserBot.send(
            functions.messages.MarkDialogUnread(peer=await
                                                UserBot.resolve_peer(
                                                    message.chat.id),
                                                unread=True)))
Exemplo n.º 9
0
async def generate_qr(bot: UserBot, message: Message):
    if qr_text := await UserBot.extract_command_text(message):
        img = qrcode.make(qr_text)

        with open('downloads/qr.png', 'wb') as f:
            img.save(f)

        await asyncio.gather(
            bot.send_photo(message.chat.id, 'downloads/qr.png'),
            message.delete()
        )
Exemplo n.º 10
0
async def give_pats(_, message: Message):
    URL = "https://some-random-api.ml/animu/pat"
    async with aiohttp.ClientSession() as session:
        async with session.get(URL) as request:
            if request.status == 404:
                return await message.edit("`no Pats for u :c")
            result = await request.json()
            url = result.get("link", None)
            await asyncio.gather(
                message.delete(),
                UserBot.send_video(GetChatID(message), url, reply_to_message_id=ReplyCheck(message))
            )
Exemplo n.º 11
0
 def __init__(
     self,
     token: str,
     group_id: int,
     debug: bool = True
 ):
     """Auth as VK group and register commands.
     """
     Vk.__init__(self, token=token, group_id=group_id, debug=debug)
     self.messages_to_delete = {}
     self.userbot = UserBot()
     self.data = BetterBotBaseDataService()
     self.commands = Commands(self, self.data)
     self.commands.register_cmds(
         (patterns.HELP, self.commands.help_message),
         (patterns.INFO, self.commands.info_message),
         (patterns.UPDATE, self.commands.update_command),
         (patterns.ADD_PROGRAMMING_LANGUAGE,
          lambda: self.commands.change_programming_language(True)),
         (patterns.REMOVE_PROGRAMMING_LANGUAGE,
          lambda: self.commands.change_programming_language(False)),
         (patterns.ADD_GITHUB_PROFILE,
          lambda: self.commands.change_github_profile(True)),
         (patterns.REMOVE_GITHUB_PROFILE,
          lambda: self.commands.change_github_profile(False)),
         (patterns.KARMA, self.commands.karma_message),
         (patterns.TOP, self.commands.top),
         (patterns.PEOPLE, self.commands.top),
         (patterns.BOTTOM,
          lambda: self.commands.top(True)),
         (patterns.TOP_LANGUAGES, self.commands.top_langs),
         (patterns.PEOPLE_LANGUAGES, self.commands.top_langs),
         (patterns.BOTTOM_LANGUAGES,
          lambda: self.commands.top_langs(True)),
         (patterns.APPLY_KARMA, self.commands.apply_karma),
     )
Exemplo n.º 12
0
    def __new__(cls, configuration):
        if type(configuration) is not Configuration:
            raise TypeError("'configuration' must be instance of 'configuration.Configuration'")

        self = super().__new__(cls)

        self.__configuration = configuration

        self.__loop = asyncio.get_event_loop()  # todo on new event loop doesn't works userbot configuration

        self.__userbot = UserBot(configuration, self.__loop)
        self.__nativebot = NativeBot(configuration, self.__loop)
        self.__userbot.nativebot = self.__nativebot.client
        self.__nativebot.userbot = self.__userbot.client

        self.__both_connected_locker = asyncio.locks.Lock(loop=self.__loop)

        return self
Exemplo n.º 13
0
async def spamhammer(bot: UserBot, message: Message):
    await message.edit("```Initializing the database```")

    url = 'https://feed.spamwat.ch/'

    content = requests.get(
        url,
        headers={
            "User-Agent":
            "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1"
        })

    spam_ids = []
    for x in content.iter_lines():
        line: dict = json.loads(x)
        the_id = line.get('id')
        if the_id not in spam_ids:
            spam_ids.append(the_id)

    await message.edit("Starting to kick spam accounts.")

    count = 0
    async for member in bot.iter_chat_members(message.chat.id):
        member: ChatMember = member
        if member.user.id in spam_ids:
            try:
                await bot.kick_chat_member(message.chat.id,
                                           member.user.id,
                                           until_date=0)
                await message.edit(
                    f"```Kicked {count} spam accounts from here.```")
                count += 1
            except:
                ban_message = (
                    f"{member.user.id} could not be banned from Baivaru Requests for some reason."
                )
                await bot.send_message(LOG_GROUP, ban_message)

            ban_message = (
                f"{member.user.id} just got banned from Baivaru Requests.")
            await bot.send_message(LOG_GROUP, ban_message)

    print(f"```Kicked {count} spam accounts from here.```")
Exemplo n.º 14
0
async def commit_graph(_, message: Message):
    if len(message.command) < 2:
        await message.edit(
            "Please provide a github profile username to generate the graph!"
        )
        await sleep(2)
        await message.delete()
        return
    else:
        git_user = message.command[1]

    url = f"https://ghchart.rshah.org/{git_user}"
    file_name = f"{randint(1, 999)}{git_user}"

    resp = await AioHttp.get_raw(url)
    f = await aiofiles.open(f"{file_name}.svg", mode="wb")
    await f.write(resp)
    await f.close()

    try:
        drawing = svg2rlg(f"{file_name}.svg")
        renderPM.drawToFile(drawing, f"{file_name}.png")
    except UnboundLocalError:
        await message.edit("Username does not exist!")
        await sleep(2)
        await message.delete()
        return

    await asyncio.gather(
        UserBot.send_photo(
            chat_id=message.chat.id,
            photo=f"{file_name}.png",
            caption=git_user,
            reply_to_message_id=ReplyCheck(message),
        ),
        message.delete(),
    )

    for file in iglob(f"{file_name}.*"):
        os.remove(file)
Exemplo n.º 15
0
async def word_count(bot: UserBot, message: Message):
    await message.delete()
    words = Custom()
    progress = await bot.send_message(message.chat.id, "`Processed 0 messages...`")
    total = 0
    async for msg in bot.iter_history(message.chat.id, 1000):
        total += 1
        if total % 100 == 0:
            await progress.edit_text(f"`Processed {total} messages...`")
            time.sleep(0.5)
        if msg.text:
            for word in msg.text.split():
                words[word.lower()] += 1
        if msg.caption:
            for word in msg.caption.split():
                words[word.lower()] += 1
    freq = sorted(words, key=words.get, reverse=True)
    out = "Word Counter\n"
    for i in range(25):
        out += f"{i + 1}. **{words[freq[i]]}**: {freq[i]}\n"

    await progress.edit_text(out)
Exemplo n.º 16
0
async def quotly(bot: UserBot, message: Message):
    if not message.reply_to_message:
        await message.edit("Reply to any users text message")
        return

    await message.edit("```Making a Quote```")

    await message.reply_to_message.forward("@QuotLyBot")

    is_sticker = False
    progress = 0

    while not is_sticker:
        try:
            await sleep(4)
            msg = await bot.get_history("@QuotLyBot", 1)
            print(msg)
            is_sticker = True
        except:
            await sleep(1)

            progress += random.randint(0, 5)

            if progress > 100:
                await message.edit('There was a long running error')
                return

            try:
                await message.edit(
                    "```Making a Quote\nProcessing {}%```".format(progress))
            except:
                await message.edit("ERROR")

    if msg_id := msg[0]['message_id']:
        await asyncio.gather(
            message.delete(),
            bot.forward_messages(message.chat.id, "@QuotLyBot", msg_id))
Exemplo n.º 17
0
class V(Vk):
    def __init__(self, token, group_id, debug=True):
        Vk.__init__(self, token=token, group_id=group_id, debug=debug)
        self.messages_to_delete = {}
        self.userbot = UserBot()
        self.debug = True

        base = BetterBotBase("users", "dat")
        base.addPattern("karma", 0)
        base.addPattern("programming_languages", [])
        base.addPattern("github_profile", "")
        base.addPattern("supporters", [])
        base.addPattern("opponents", [])
        base.addPattern("last_collective_vote", 0)

        self.base = base

    def message_new(self, event):
        """
        Handling all new messages.
        """
        event = event["object"]["message"]

        if event['peer_id'] in self.messages_to_delete:
            peer = CHAT_ID_OFFSET + config.userbot_chats[event['peer_id']]
            new_messages_to_delete = []
            ids = []

            for item in self.messages_to_delete[event['peer_id']]:
                if item['date'] > datetime.now():
                    new_messages_to_delete.append(item)
                else:
                    ids.append(item['id'])

            if new_messages_to_delete:
                self.messages_to_delete[event['peer_id']] = new_messages_to_delete
            else:
                self.messages_to_delete.pop(event['peer_id'])

            if ids:
                self.userbot.delete_messages(ids, peer)

        user = self.base.autoInstall(event["from_id"], self) if event["from_id"] > 0 else None

        message = event["text"].lstrip("/")
        messages = self.get_messages(event)
        selected_message = messages[0] if len(messages) == 1 else None
        selected_user = self.base.autoInstall(selected_message["from_id"], self) if selected_message else None
        is_bot_selected = selected_message and (selected_message["from_id"] < 0)

        karma_enabled = event["peer_id"] in config.chats_karma_whitelist
        group_chat = event["peer_id"] >= CHAT_ID_OFFSET

        if group_chat:
            if karma_enabled:
                match = regex.match(patterns.KARMA, message)
                if match:
                    return self.send_karma(event, selected_user if selected_user else user, not selected_user)
                match = regex.match(patterns.TOP, message)
                if match:
                    maximum_users = match.group("maximum_users")
                    maximum_users = int(maximum_users) if maximum_users else 0
                    return self.send_top(event, maximum_users)
                match = regex.match(patterns.BOTTOM, message)
                if match:
                    maximum_users = match.group("maximum_users")
                    maximum_users = int(maximum_users) if maximum_users else 0
                    return self.send_bottom(event, maximum_users)
                match = regex.match(patterns.APPLY_KARMA, message)
                if match:
                    # Only regular users can be selected
                    if is_bot_selected:
                        return

                    if not selected_user:
                        selected_user_id = match.group("selectedUserId")
                        if selected_user_id:
                            selected_user = self.base.autoInstall(int(selected_user_id), self)

                    if selected_user and (user.uid != selected_user.uid):
                        operator = match.group("operator")[0]
                        amount = match.group("amount")
                        amount = int(amount) if amount else 0

                        utcnow = datetime.utcnow()

                        # Downvotes disabled for users with negative karma
                        if (operator == "-") and (user.karma < 0):
                            self.delete_message(event)
                            self.send_not_enough_karma_error(event, user)
                            return

                        # Collective votes limit
                        if amount == 0:
                            utclast = datetime.fromtimestamp(float(user.last_collective_vote));
                            difference = utcnow - utclast
                            hours_difference = difference.total_seconds() / 3600;
                            hours_limit = self.get_karma_hours_limit(user.karma);
                            if hours_difference < hours_limit:
                                self.delete_message(event)
                                self.send_not_enough_hours_error(event, user, hours_limit, difference.total_seconds() / 60)
                                return

                        user_karma_change, selected_user_karma_change, collective_vote_applied, voters = self.apply_karma_change(event, user, selected_user, operator, amount)

                        if collective_vote_applied:
                            user.last_collective_vote = int(utcnow.timestamp())
                            self.base.save(user)

                        self.base.save(selected_user)

                        if user_karma_change:
                            self.base.save(user)
                        self.send_karma_change(event, user_karma_change, selected_user_karma_change, voters)
                        self.delete_message(event)
                        return
                match = regex.match(patterns.TOP_LANGUAGES, message)
                if match:
                    languages = match.group("languages")
                    return self.send_top_languages(event, languages)
            else:
                match = regex.match(patterns.PEOPLE, message)
                if match:
                    maximum_users = match.group("maximum_users")
                    maximum_users = int(maximum_users) if maximum_users else 0
                    return self.send_people(event, maximum_users)
                match = regex.match(patterns.PEOPLE_LANGUAGES, message)
                if match:
                    languages = match.group("languages")
                    return self.send_people_languages(event, languages)

        match = regex.match(patterns.HELP, message)
        if match:
            return self.send_help(event, group_chat, karma_enabled)
        match = regex.match(patterns.INFO, message)
        if match:
            return self.send_info(event, karma_enabled, selected_user if selected_user else user, not selected_user)
        match = regex.match(patterns.ADD_PROGRAMMING_LANGUAGE, message)
        if match:
            language = match.group('language')
            language = self.get_default_programming_language(language)
            if not language:
                return
            if language not in user.programming_languages:
                user.programming_languages.append(language)
                self.base.save(user)
            return self.send_programming_languages_list(event, user)
        match = regex.match(patterns.REMOVE_PROGRAMMING_LANGUAGE, message)
        if match:
            language = match.group('language')
            language = self.get_default_programming_language(language)
            if not language:
                return
            if language in user.programming_languages:
                user.programming_languages.remove(language)
                self.base.save(user)
            return self.send_programming_languages_list(event, user)
        match = regex.match(patterns.ADD_GITHUB_PROFILE, message)
        if match:
            profile = match.group('profile')
            if not profile:
                return
            if profile != user.github_profile:
                if requests.get(f'https://github.com/{profile}').status_code == 200:
                    user.github_profile = profile
                    self.base.save(user)
            return self.send_github_profile(event, user)
        match = regex.match(patterns.REMOVE_GITHUB_PROFILE, message)
        if match:
            profile = match.group('profile')
            if not profile:
                return
            if profile == user.github_profile:
                user.github_profile = ""
                self.base.save(user)
            return self.send_github_profile(event, user)

    def delete_message(self, event, delay=2):
        peer_id = event['peer_id']
        if peer_id in config.userbot_chats and peer_id in config.chats_deleting:
            if peer_id not in self.messages_to_delete:
                self.messages_to_delete.update({peer_id: []})

            message_id = event['conversation_message_id']
            data = {'date': datetime.now() + timedelta(seconds=delay), 'id': message_id}
            self.messages_to_delete[peer_id].append(data)

    def get_karma_hours_limit(self, karma):
        for limit_item in config.karma_limit_hours:
            if (not limit_item["min_karma"]) or (karma >= limit_item["min_karma"]):
                if (not limit_item["max_karma"]) or (karma < limit_item["max_karma"]):
                    return limit_item["limit"]
        return 168 # hours (a week)

    def apply_karma_change(self, event, user, selected_user, operator, amount):
        selected_user_karma_change = None
        user_karma_change = None
        collective_vote_applied = None
        voters = None

        # Personal karma transfer
        if amount > 0:
            if user.karma < amount:
                self.send_not_enough_karma_error(event, user)
                return user_karma_change, selected_user_karma_change, collective_vote_applied, voters
            else:
                user_karma_change = self.apply_user_karma(user, -amount)
                amount = -amount if operator == "-" else amount
                selected_user_karma_change = self.apply_user_karma(selected_user, amount)

        # Collective vote
        elif amount == 0:
            if operator == "+":
                selected_user_karma_change, voters, collective_vote_applied = self.apply_collective_vote(user, selected_user, "supporters", config.positive_votes_per_karma, +1)
            else:
                selected_user_karma_change, voters, collective_vote_applied = self.apply_collective_vote(user, selected_user, "opponents", config.negative_votes_per_karma, -1)

        return user_karma_change, selected_user_karma_change, collective_vote_applied, voters

    def apply_collective_vote(self, user, selected_user, current_voters, number_of_voters, amount):
        vote_applied = None
        if user.uid not in selected_user[current_voters]:
            selected_user[current_voters].append(user.uid)
            vote_applied = True
        if len(selected_user[current_voters]) >= number_of_voters:
            voters = selected_user[current_voters]
            selected_user[current_voters] = []
            return self.apply_user_karma(selected_user, amount), voters, vote_applied
        return None, None, vote_applied

    def apply_user_karma(self, user, amount):
        user.karma += amount
        return (user.uid, user.name, user.karma - amount, user.karma)

    def get_messages(self, event):
        reply_message = event.get("reply_message", {})
        return [reply_message] if reply_message else event.get("fwd_messages", [])

    def get_programming_languages_string_with_parentheses_or_empty(self, user):
        programming_languages_string = self.get_programming_languages_string(user)
        if programming_languages_string == "":
            return programming_languages_string
        else:
            return "(" + programming_languages_string + ")"

    def get_github_profile(self, user):
        if isinstance(user, dict):
            return user["github_profile"] if "github_profile" in user else ""
        else:
            return user.github_profile

    def get_github_profile_top_string(self, user):
        profile = self.get_github_profile(user)
        if profile:
            profile = f" — github.com/{profile}"
        return profile

    def get_programming_languages_string(self, user):
        if isinstance(user, dict):
            languages = user["programming_languages"] if "programming_languages" in user else []
        else:
            languages = user.programming_languages
        if len(languages) > 0:
            languages.sort()
            return ", ".join(languages)
        else:
            return ""

    def get_default_programming_language(self, language):
        for default_programming_language in config.default_programming_languages:
            default_programming_language = default_programming_language.replace('\\', '')
            if default_programming_language.lower() == language.lower():
                return default_programming_language
        return None

    def contains_string(self, strings, matchedString, ignoreCase):
        if ignoreCase:
            for string in strings:
                if string.lower() == matchedString.lower():
                    return True
        else:
            for string in strings:
                if string == matchedString:
                    return True
        return False

    def contains_all_strings(self, strings, matchedStrings, ignoreCase):
        matched_strings_count = len(matchedStrings)
        for string in strings:
            if self.contains_string(matchedStrings, string, ignoreCase):
                matched_strings_count -= 1
                if matched_strings_count == 0:
                    return True
        return False

    def send_karma_change(self, event, user_karma_change, selected_user_karma_change, voters):
        if selected_user_karma_change and user_karma_change:
            self.send_message(event, "Карма изменена: [id%s|%s] [%s]->[%s], [id%s|%s] [%s]->[%s]." % (user_karma_change + selected_user_karma_change))
        elif selected_user_karma_change:
            self.send_message(event, "Карма изменена: [id%s|%s] [%s]->[%s]. Голосовали: (%s)" % (selected_user_karma_change + (", ".join([f"@id{voter}" for voter in voters]),)))

    def send_karma(self, event, user, is_self=True):
        if is_self:
            response = "[id%s|%s], Ваша карма — %s."
        else:
            response = "Карма [id%s|%s] — %s."
        self.send_message(event, response % (user.uid, user.name, self.get_karma_string(user)))

    def send_info(self, event, karma_enabled, user, is_self=True):
        programming_languages_string = self.get_programming_languages_string(user)
        if not programming_languages_string:
            programming_languages_string = "отсутствуют"
        profile = self.get_github_profile(user)
        if not profile:
            profile = "отсутствует"
        else:
            profile = f"github.com/{profile}"
        if karma_enabled:
            if is_self:
                response = "[id%s|%s], Ваша карма — %s.\nВаши языки программирования: %s\nВаша страничка на GitHub — %s"
            else:
                response = "Карма [id%s|%s] — %s.\nЯзыки программирования: %s\nCтраничка на GitHub — %s"
            return self.send_message(event, response % (user.uid, user.name, self.get_karma_string(user), programming_languages_string, profile))
        else:
            if is_self:
                response = "[id%s|%s], \nВаши языки программирования: %s\nВаша страничка на GitHub — %s"
            else:
                response = "[id%s|%s]. \nЯзыки программирования: %s\nCтраничка на GitHub — %s"
            return self.send_message(event, response % (user.uid, user.name, programming_languages_string, profile))

    def get_karma_string(self, user):
        plus_string = ""
        minus_string = ""
        if isinstance(user, dict):
            karma = user["karma"]
            plus_votes = len(user["supporters"])
            minus_votes = len(user["opponents"])
        else:
            karma = user.karma
            plus_votes = len(user.supporters)
            minus_votes = len(user.opponents)
        if plus_votes > 0:
            plus_string = "+%.1f" % (plus_votes / config.positive_votes_per_karma)
        if minus_votes > 0:
            minus_string = "-%.1f" % (minus_votes / config.negative_votes_per_karma)
        if plus_votes > 0 or minus_votes > 0:
            return f"[{karma}][{plus_string}{minus_string}]"
        else:
            return f"[{karma}]"

    def send_top_users(self, event, users):
        if not users:
            return
        user_strings = ["%s [id%s|%s]%s %s" % (self.get_karma_string(user), user["uid"], user["name"], self.get_github_profile_top_string(user), self.get_programming_languages_string_with_parentheses_or_empty(user)) for user in users]
        total_symbols = 0
        i = 0
        for user_string in user_strings:
            user_string_length = len(user_string)
            if (total_symbols + user_string_length + 2) >= 4096: # Maximum message size for VK API (messages.send)
                user_strings = user_strings[:i]
            else:
                total_symbols += user_string_length + 2
                i += 1
        response = "\n".join(user_strings)
        self.send_message(event, response)

    def get_users_sorted_by_karma(self, peer_id):
        members = self.get_members_ids(peer_id);
        users = self.base.getSortedByKeys("karma", otherKeys=["programming_languages", "supporters", "opponents", "github_profile", "uid"])
        if members:
            users = [u for u in users if u["uid"] in members]
        return users

    def get_users_sorted_by_name(self, peer_id):
        members = self.get_members_ids(peer_id);
        users = self.base.getSortedByKeys("name", otherKeys=["programming_languages", "github_profile", "uid"])
        if members:
            users = [u for u in users if u["uid"] in members]
        users.reverse()
        return users

    def send_bottom(self, event, maximum_users):
        peer_id = event["peer_id"]
        users = self.get_users_sorted_by_karma(peer_id)
        users = [i for i in users if (i["karma"] != 0) or ("programming_languages" in i and len(i["programming_languages"]) > 0)]
        if (maximum_users > 0) and (len(users) >= maximum_users):
            users.reverse()
            self.send_top_users(event, users[:maximum_users])
        else:
            self.send_top_users(event, reversed(users))
    
    def send_people_users(self, event, users):
        if not users:
            return
        user_strings = ["[id%s|%s]%s %s" % (user["uid"], user["name"], self.get_github_profile_top_string(user), self.get_programming_languages_string_with_parentheses_or_empty(user)) for user in users]
        total_symbols = 0
        i = 0
        for user_string in user_strings:
            user_string_length = len(user_string)
            if (total_symbols + user_string_length + 2) >= 4096: # Maximum message size for VK API (messages.send)
                user_strings = user_strings[:i]
            else:
                total_symbols += user_string_length + 2
                i += 1
        response = "\n".join(user_strings)
        self.send_message(event, response)

    def send_people(self, event, maximum_users):
        peer_id = event["peer_id"]
        users = self.get_users_sorted_by_name(peer_id)
        users = [i for i in users if i["github_profile"] or ("programming_languages" in i and len(i["programming_languages"]) > 0)]
        if (maximum_users > 0) and (len(users) >= maximum_users):
            self.send_people_users(event, users[:maximum_users])
        else:
            self.send_people_users(event, users)

    def send_top(self, event, maximum_users):
        peer_id = event["peer_id"]
        users = self.get_users_sorted_by_karma(peer_id)
        users = [i for i in users if (i["karma"] != 0) or ("programming_languages" in i and len(i["programming_languages"]) > 0)]
        if (maximum_users > 0) and (len(users) >= maximum_users):
            self.send_top_users(event, users[:maximum_users])
        else:
            self.send_top_users(event, users)

    def send_people_languages(self, event, languages):
        languages = regex.split(r"\s+", languages)
        peer_id = event["peer_id"]
        users = self.get_users_sorted_by_name(peer_id)
        users = [i for i in users if ("programming_languages" in i and len(i["programming_languages"]) > 0) and self.contains_all_strings(i["programming_languages"], languages, True)]
        self.send_people_users(event, users)

    def send_top_languages(self, event, languages):
        languages = regex.split(r"\s+", languages)
        peer_id = event["peer_id"]
        users = self.get_users_sorted_by_karma(peer_id)
        users = [i for i in users if ("programming_languages" in i and len(i["programming_languages"]) > 0) and self.contains_all_strings(i["programming_languages"], languages, True)]
        self.send_top_users(event, users)

    def send_github_profile(self, event, user):
        profile = self.get_github_profile(user)
        if not profile:
            self.send_message(event, f"[id{user.uid}|{user.name}], у Вас не указана страничка на GitHub.")
        else:
            self.send_message(event, f"[id{user.uid}|{user.name}], Ваша страничка на GitHub — github.com/{profile}.")

    def send_programming_languages_list(self, event, user):
        programming_languages_string = self.get_programming_languages_string(user)
        if not programming_languages_string:
            self.send_message(event, f"[id{user.uid}|{user.name}], у Вас не указано языков программирования.")
        else:
            self.send_message(event, f"[id{user.uid}|{user.name}], Ваши языки программирования: {programming_languages_string}.")

    def send_help(self, event, group_chat, karma_enabled):
        if group_chat:
            if karma_enabled:
                self.send_message(event, config.help_string_with_karma)
            else:
                self.send_message(event, config.help_string)
        else:
            self.send_message(event, config.help_string_private_chat)

    def send_not_in_whitelist(self, event, user):
        peer_id = event["peer_id"]
        message = f"Извините, [id{user.uid}|{user.name}], но Ваша беседа [{peer_id}] отсутствует в белом списке для начисления кармы."
        self.send_message(event, message)

    def send_not_enough_karma_error(self, event, user):
        message = f"Извините, [id{user.uid}|{user.name}], но Вашей кармы [{user.karma}] недостаточно :("
        self.send_message(event, message)

    def send_not_enough_hours_error(self, event, user, hours_limit, difference_minutes):
        message = f"Извините, [id{user.uid}|{user.name}], но с момента вашего последнего голоса ещё не прошло {hours_limit} ч. :( До следующего голоса осталось {int(hours_limit * 60 - difference_minutes)} м."
        self.send_message(event, message)

    def get_members(self, peer_id):
        return self.messages.getConversationMembers(peer_id=peer_id)

    def get_members_ids(self, peer_id):
        members = self.get_members(peer_id)
        if "error" in members:
            return None
        else:
            return [m["member_id"] for m in members["response"]["items"] if m["member_id"] > 0]

    def send_message(self, event, message):
        self.messages.send(message=message, peer_id=event["peer_id"], disable_mentions=1, random_id=0)
Exemplo n.º 18
0
class Bot(Vk):
    """Provides working with VK API as group.
    """
    def __init__(
        self,
        token: str,
        group_id: int,
        debug: bool = True
    ):
        """Auth as VK group and register commands.
        """
        Vk.__init__(self, token=token, group_id=group_id, debug=debug)
        self.messages_to_delete = {}
        self.userbot = UserBot()
        self.data = BetterBotBaseDataService()
        self.commands = Commands(self, self.data)
        self.commands.register_cmds(
            (patterns.HELP, self.commands.help_message),
            (patterns.INFO, self.commands.info_message),
            (patterns.UPDATE, self.commands.update_command),
            (patterns.ADD_PROGRAMMING_LANGUAGE,
             lambda: self.commands.change_programming_language(True)),
            (patterns.REMOVE_PROGRAMMING_LANGUAGE,
             lambda: self.commands.change_programming_language(False)),
            (patterns.ADD_GITHUB_PROFILE,
             lambda: self.commands.change_github_profile(True)),
            (patterns.REMOVE_GITHUB_PROFILE,
             lambda: self.commands.change_github_profile(False)),
            (patterns.KARMA, self.commands.karma_message),
            (patterns.TOP, self.commands.top),
            (patterns.PEOPLE, self.commands.top),
            (patterns.BOTTOM,
             lambda: self.commands.top(True)),
            (patterns.TOP_LANGUAGES, self.commands.top_langs),
            (patterns.PEOPLE_LANGUAGES, self.commands.top_langs),
            (patterns.BOTTOM_LANGUAGES,
             lambda: self.commands.top_langs(True)),
            (patterns.APPLY_KARMA, self.commands.apply_karma),
        )

    def message_new(
        self,
        event: Dict[str, Any]
    ) -> NoReturn:
        """Handling all new messages.
        """
        event = event["object"]["message"]
        msg = event["text"].lstrip("/")
        peer_id = event["peer_id"]
        from_id = event["from_id"]
        msg_id = event["conversation_message_id"]

        if peer_id in self.messages_to_delete:
            peer = CHAT_ID_OFFSET + config.USERBOT_CHATS[peer_id]
            new_messages_to_delete = []
            ids = []

            for item in self.messages_to_delete[peer_id]:
                if item['date'] > datetime.now():
                    new_messages_to_delete.append(item)
                else:
                    ids.append(item['id'])

            if new_messages_to_delete:
                self.messages_to_delete[peer_id] = new_messages_to_delete
            else:
                self.messages_to_delete.pop(peer_id)

            if ids:
                self.userbot.delete_messages(ids, peer)

        user = self.data.get_user(from_id, self) if from_id > 0 else None

        messages = self.get_messages(event)
        selected_message = messages[0] if len(messages) == 1 else None
        selected_user = (
            self.data.get_user(selected_message["from_id"], self)
            if selected_message else None)

        self.commands.process(
            msg, peer_id, from_id, messages, msg_id,
            user, selected_user)


    def delete_message(
        self,
        peer_id: int,
        msg_id: int,
        delay: int = 2
    ) -> NoReturn:
        """Assigns messages to deleting.
        """
        if peer_id in config.USERBOT_CHATS and peer_id in config.CHATS_DELETING:
            if peer_id not in self.messages_to_delete:
                self.messages_to_delete.update({peer_id: []})
            data = {
                'date': datetime.now() + timedelta(seconds=delay),
                'id': msg_id
            }
            self.messages_to_delete[peer_id].append(data)

    def get_members(
        self,
        peer_id: int
    ) -> Dict[str, Any]:
        """Returns all conversation members.
        """
        return self.messages.getConversationMembers(peer_id=peer_id)

    def get_members_ids(
        self,
        peer_id: int
    ) -> List[int]:
        """Returns all conversation member's IDs
        """
        members = self.get_members(peer_id)
        if "error" in members:
            return None
        return [m["member_id"]
                for m in members["response"]["items"] if m["member_id"] > 0]

    def send_msg(
        self,
        msg: str,
        peer_id: int
    ) -> NoReturn:
        """Sends message to chat with {peer_id}.

        :param msg: message text
        :param peer_id: chat ID
        """
        self.messages.send(
            message=msg, peer_id=peer_id,
            disable_mentions=1, random_id=0
        )

    def get_user_name(
        self,
        uid: int,
        name_case: str = "nom"
    ) -> str:
        """Returns user firstname.

        :param uid: user ID
        :param name_case: The declension case for the user's first and last name.
            Possible values:
            • Nominative – nom,
            • Genitive – gen,
            • dative – dat,
            • accusative – acc,
            • instrumental – ins,
            • prepositional – abl.
        """
        return self.users.get(user_ids=uid, name_case=name_case)['response'][0]["first_name"]

    @staticmethod
    def get_messages(
        event: Dict[str, Any]
    ) -> List[Dict[str, Any]]:
        """Returns forward messages or reply message if available.
        """
        reply_message = event.get("reply_message", {})
        return [reply_message] if reply_message else event.get("fwd_messages", [])
Exemplo n.º 19
0
class V(Vk):
    def __init__(self):
        Vk.__init__(self, token=BotToken, group_id=bot_group_id, debug=True)
        self.messages_to_delete = {}
        self.userbot = UserBot()
        self.debug = True

    def message_new(self, event):
        """
        Handling all new messages.
        """
        event = event["object"]["message"]

        if event['peer_id'] in self.messages_to_delete:
            peer = 2000000000 + userbot_chats[event['peer_id']]
            new_messages_to_delete = []
            ids = []

            for item in self.messages_to_delete[event['peer_id']]:
                if item['date'] > datetime.now():
                    new_messages_to_delete.append(item)
                else:
                    ids.append(item['id'])

            if new_messages_to_delete:
                self.messages_to_delete[
                    event['peer_id']] = new_messages_to_delete
            else:
                self.messages_to_delete.pop(event['peer_id'])

            if ids:
                self.userbot.delete_messages(ids, peer)

        user = base.autoInstall(event["from_id"],
                                self) if event["from_id"] > 0 else None

        message = event["text"].lstrip("/")
        messages = self.get_messages(event)
        selected_message = messages[0] if len(messages) == 1 else None
        selected_user = base.autoInstall(selected_message["from_id"],
                                         self) if selected_message else None
        is_bot_selected = selected_message and (selected_message["from_id"] <
                                                0)

        if regex.findall(patterns.HELP, message):
            self.send_help(event)
        elif regex.findall(patterns.KARMA, message):
            self.send_karma(event, selected_user if selected_user else user,
                            not selected_user)
        elif regex.findall(patterns.TOP, message):
            self.send_top(event)
        elif regex.findall(patterns.BOTTOM, message):
            self.send_bottom(event)
        elif regex.findall(patterns.INFO, message):
            self.send_info(event, selected_user if selected_user else user,
                           not selected_user)
        elif regex.findall(patterns.APPLY_KARMA, message):
            # Only for chat rooms
            if event["peer_id"] < 2000000000:
                return
            # Only for whitelisted chat rooms
            if event["peer_id"] not in chats_whitelist:
                self.send_not_in_whitelist(event, user)
                return
            # Only regular users can be selected
            if is_bot_selected:
                return

            if selected_user and (user.uid != selected_user.uid):
                match = regex.match(patterns.APPLY_KARMA, message)
                operator = match.group("operator")[0]
                amount = match.group("amount")

                # Downvotes disabled for users with negative rating
                if (operator == "-") and (user.rating < 0):
                    self.send_not_enough_karma_error(event, user)
                    return

                user_karma_change, selected_user_karma_change, voters = self.apply_karma_change(
                    event, user, selected_user, operator, amount)
                base.save(selected_user)
                if user_karma_change:
                    base.save(user)
                self.send_karma_change(event, user_karma_change,
                                       selected_user_karma_change, voters)
                self.delete_message(event)
        elif regex.findall(patterns.ADD_PROGRAMMING_LANGUAGE, message):
            language = regex.match(patterns.ADD_PROGRAMMING_LANGUAGE,
                                   message).group('language')
            language = self.get_default_programming_language(language)
            if not language:
                return
            if "programming_languages" not in user.obj:
                user.programming_languages = []
                base.save(user)
            if language not in user.programming_languages:
                user.programming_languages.append(language)
                base.save(user)
            self.send_programming_languages_list(event, user)
        elif regex.findall(patterns.REMOVE_PROGRAMMING_LANGUAGE, message):
            language = regex.match(patterns.REMOVE_PROGRAMMING_LANGUAGE,
                                   message).group('language')
            language = self.get_default_programming_language(language)
            if not language:
                return
            if "programming_languages" not in user.obj:
                user.programming_languages = []
                base.save(user)
            if language in user.programming_languages:
                user.programming_languages.remove(language)
                base.save(user)
            self.send_programming_languages_list(event, user)
        elif regex.findall(patterns.TOP_LANGUAGES, message):
            match = regex.match(patterns.TOP_LANGUAGES, message)
            languages = match.group("languages")
            self.send_top_languages(event, languages)

    def delete_message(self, event, delay=2):
        peer_id = event['peer_id']
        if peer_id in userbot_chats and peer_id in chats_deleting:
            if peer_id not in self.messages_to_delete:
                self.messages_to_delete.update({peer_id: []})

            message_id = event['conversation_message_id']
            data = {
                'date': datetime.now() + timedelta(seconds=delay),
                'id': message_id
            }
            self.messages_to_delete[peer_id].append(data)

    def apply_karma_change(self, event, user, selected_user, operator, amount):
        selected_user_karma_change = None
        user_karma_change = None
        voters = None

        amount = int(amount) if amount else 0

        # Personal karma transfer
        if amount > 0:
            if user.rating < amount:
                self.send_not_enough_karma_error(event, user)
                return user_karma_change, selected_user_karma_change, voters
            else:
                user_karma_change = self.apply_user_karma(user, -amount)
                amount = -amount if operator == "-" else amount
                selected_user_karma_change = self.apply_user_karma(
                    selected_user, amount)

        # Collective vote
        elif amount == 0:
            if operator == "+":
                selected_user_karma_change, voters = self.apply_collective_vote(
                    user, selected_user, "current", 2, +1)
            else:
                selected_user_karma_change, voters = self.apply_collective_vote(
                    user, selected_user, "current_sub", 3, -1)

        return user_karma_change, selected_user_karma_change, voters

    def apply_collective_vote(self, user, selected_user, current_voters,
                              number_of_voters, amount):
        if user.uid not in selected_user[current_voters]:
            selected_user[current_voters].append(user.uid)
        if len(selected_user[current_voters]) >= number_of_voters:
            voters = selected_user[current_voters]
            selected_user[current_voters] = []
            return self.apply_user_karma(selected_user, amount), voters
        return None, None

    def apply_user_karma(self, user, amount):
        user.rating += amount
        return (user.uid, user.name, user.rating - amount, user.rating)

    def get_messages(self, event):
        reply_message = event.get("reply_message", {})
        return [reply_message] if reply_message else event.get(
            "fwd_messages", [])

    def get_programming_languages_string_with_parentheses_or_empty(self, user):
        programming_languages_string = self.get_programming_languages_string(
            user)
        if programming_languages_string == "":
            return programming_languages_string
        else:
            return "(" + programming_languages_string + ")"

    def get_programming_languages_string(self, user):
        if isinstance(user, dict):
            languages = user["programming_languages"] if "programming_languages" in user else []
        else:
            languages = user.programming_languages
        if len(languages) > 0:
            languages.sort()
            return ", ".join(languages)
        else:
            return ""

    def get_default_programming_language(self, language):
        for default_programming_language in default_programming_languages:
            default_programming_language = default_programming_language.replace(
                '\\', '')
            if default_programming_language.lower() == language.lower():
                return default_programming_language
        return None

    def contains_string(self, strings, matchedString, ignoreCase):
        if ignoreCase:
            for string in strings:
                if string.lower() == matchedString.lower():
                    return True
        else:
            for string in strings:
                if string == matchedString:
                    return True
        return False

    def contains_all_strings(self, strings, matchedStrings, ignoreCase):
        matchedStringsCount = len(matchedStrings)
        for string in strings:
            if self.contains_string(matchedStrings, string, ignoreCase):
                matchedStringsCount -= 1
                if matchedStringsCount == 0:
                    return True
        return False

    def send_karma_change(self, event, user_karma_change,
                          selected_user_karma_change, voters):
        if selected_user_karma_change and user_karma_change:
            self.send_message(
                event,
                "Карма изменена: [id%s|%s] [%s]->[%s], [id%s|%s] [%s]->[%s]." %
                (user_karma_change + selected_user_karma_change))
        elif selected_user_karma_change:
            self.send_message(
                event,
                "Карма изменена: [id%s|%s] [%s]->[%s]. Голосовали: (%s)" %
                (selected_user_karma_change +
                 (", ".join(["@id%s" % (voter) for voter in voters]), )))

    def send_karma(self, event, user, is_self=True):
        if is_self:
            response = "[id%s|%s], Ваша карма - [%s]."
        else:
            response = "Карма [id%s|%s] - [%s]."
        self.send_message(event, response % (user.uid, user.name, user.rating))

    def send_info(self, event, user, is_self=True):
        programming_languages_string = self.get_programming_languages_string(
            user)
        if is_self:
            response = "[id%s|%s], Ваша карма - [%s].\nВаши языки программирования - %s"
        else:
            response = "Карма [id%s|%s] - [%s].\nЯзыки программирования - %s"
        if not programming_languages_string:
            programming_languages_string = "отсутствуют"
        self.send_message(
            event, response %
            (user.uid, user.name, user.rating, programming_languages_string))

    def send_top_users(self, event, users):
        if not users:
            return
        user_strings = [
            "[%s] [id%s|%s] %s" %
            (user["rating"], user["uid"], user["name"],
             self.get_programming_languages_string_with_parentheses_or_empty(
                 user)) for user in users
        ]

        total_symbols = 0
        i = 0
        for user_string in user_strings:
            user_string_length = len(user_string)
            if (total_symbols + user_string_length + 2
                ) >= 4096:  # Maximum message size for VK API (messages.send)
                user_strings = user_strings[:i]
            else:
                total_symbols += user_string_length + 2
                i += 1

        response = "\n".join(user_strings)
        self.send_message(event, response)

    def send_bottom(self, event):
        users = base.getSortedByKeys("rating",
                                     otherKeys=["programming_languages"])
        users = [
            i for i in users
            if (i["rating"] != 0) or ("programming_languages" in i
                                      and len(i["programming_languages"]) > 0)
        ]
        self.send_top_users(event, reversed(users))

    def send_top(self, event):
        users = base.getSortedByKeys("rating",
                                     otherKeys=["programming_languages"])
        users = [
            i for i in users
            if (i["rating"] != 0) or ("programming_languages" in i
                                      and len(i["programming_languages"]) > 0)
        ]
        self.send_top_users(event, users)

    def send_top_languages(self, event, languages):
        languages = regex.split(r"\s+", languages)
        users = base.getSortedByKeys("rating",
                                     otherKeys=["programming_languages"])
        users = [
            i for i in users
            if ("programming_languages" in i
                and len(i["programming_languages"]) > 0) and self.
            contains_all_strings(i["programming_languages"], languages, True)
        ]
        self.send_top_users(event, users)

    def send_programming_languages_list(self, event, user):
        programming_languages_string = self.get_programming_languages_string(
            user)
        if not programming_languages_string:
            self.send_message(
                event, "[id%s|%s], у Вас не указано языков программирования." %
                (user.uid, user.name))
        else:
            self.send_message(
                event, "[id%s|%s], Ваши языки программирования: %s." %
                (user.uid, user.name, programming_languages_string))

    def send_help(self, event):
        self.send_message(event, help_string)

    def send_not_in_whitelist(self, event, user):
        self.send_message(
            event,
            "Извините, [id%s|%s], но Ваша беседа [%s] отсутствует в белом списке для начисления кармы."
            % (user.uid, user.name, event["peer_id"]))

    def send_not_enough_karma_error(self, event, user):
        self.send_message(
            event, "Извините, [id%s|%s], но Вашей кармы [%s] недостаточно :(" %
            (user.uid, user.name, user.rating))

    def send_message(self, event, message):
        self.messages.send(message=message,
                           peer_id=event["peer_id"],
                           disable_mentions=1,
                           random_id=0)
Exemplo n.º 20
0
import userbot
from userbot import UserBot
from userbot import scheduler

if __name__ == "__main__":
    userbot.client = UserBot

    scheduler.start()

    UserBot.run()
Exemplo n.º 21
0
 def __init__(self):
     Vk.__init__(self, token=BotToken, group_id=bot_group_id, debug=True)
     self.messages_to_delete = {}
     self.userbot = UserBot()
     self.debug = True