Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce max user size per instance #45

Merged
merged 1 commit into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions ronnia/bots/bot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ def __init__(self, ):
self.twitch_client = TwitchAPI(os.getenv('TWITCH_CLIENT_ID'), os.getenv('TWITCH_CLIENT_SECRET'))
self._loop = asyncio.get_event_loop()

self.user_per_instance = 150
self.sleep_after_instance = (self.user_per_instance // 20 + 1) * 11
self.user_per_instance = 60
self.channel_join_cooldown = 11
self.sleep_after_instance = (self.user_per_instance // 20 + 1) * self.channel_join_cooldown

self.servicebus_connection_string = os.getenv('SERVICE_BUS_CONNECTION_STR')
self.servicebus_webserver_queue_name = 'webserver-signups'
Expand Down
30 changes: 7 additions & 23 deletions ronnia/bots/twitch_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from multiprocessing import Lock
from typing import AnyStr, Tuple, Union, List

import aiohttp
from azure.servicebus import ServiceBusMessage
from azure.servicebus.aio import ServiceBusClient
from azure.servicebus.exceptions import ServiceBusError
Expand All @@ -25,7 +24,6 @@


class TwitchBot(commands.Bot, ABC):
PER_REQUEST_COOLDOWN = 30 # each request has 30 seconds cooldown

def __init__(self, initial_channel_names: List[str], join_lock: Lock, max_users: int):
self.users_db = UserDatabase()
Expand Down Expand Up @@ -124,21 +122,6 @@ async def receive_and_parse_message(self, message):
def run(self):
super().run()

@staticmethod
async def _get_access_token():
client_id = os.getenv('TWITCH_CLIENT_ID'),
client_secret = os.getenv('TWITCH_CLIENT_SECRET')
grant_type = 'client_credentials'
scope = 'chat:read chat:edit'
payload = {'client_id': client_id,
'client_secret': client_secret,
'grant_type': grant_type,
'scope': scope}
async with aiohttp.ClientSession() as session:
async with session.post('https://id.twitch.tv/oauth2/token', data=payload) as resp:
response_json = await resp.json()
return response_json['access_token']

async def event_message(self, message: Message):
if message.author is None:
logger.info(f"{message.channel.name}: {message.content}")
Expand Down Expand Up @@ -276,25 +259,26 @@ async def _check_user_cooldown(self, author: Chatter):
"""
Check if user is on cooldown, raise an exception if the user is on request cooldown.
:param author: Twitch user object
:return: Exception if user has requested a beatmap before TwitchBot.PER_REQUEST_COOLDOWN seconds passed.
:return: Exception if user has requested a beatmap before channel_cooldown seconds passed.
"""
author_id = author.id
time_right_now = datetime.datetime.now()

await self._prune_cooldowns(time_right_now)
channel_cooldown = await self.users_db.get_setting("cooldown", author_id)
await self._prune_cooldowns(time_right_now, channel_cooldown)

if author_id not in self.user_last_request:
self.user_last_request[author_id] = time_right_now
else:
last_message_time = self.user_last_request[author_id]
seconds_since_last_request = (time_right_now - last_message_time).total_seconds()
assert seconds_since_last_request >= TwitchBot.PER_REQUEST_COOLDOWN, \
assert seconds_since_last_request >= channel_cooldown, \
f'{author.name} is on cooldown.'
self.user_last_request[author_id] = time_right_now

return

async def _prune_cooldowns(self, time_right_now: datetime.datetime):
async def _prune_cooldowns(self, time_right_now: datetime.datetime, channel_cooldown: int):
"""
Prunes users on that are on cooldown list so it doesn't get too cluttered.
:param time_right_now:
Expand All @@ -303,7 +287,7 @@ async def _prune_cooldowns(self, time_right_now: datetime.datetime):
pop_list = []
for user_id, last_message_time in self.user_last_request.items():
seconds_since_last_request = (time_right_now - last_message_time).total_seconds()
if seconds_since_last_request >= TwitchBot.PER_REQUEST_COOLDOWN:
if seconds_since_last_request >= channel_cooldown:
pop_list.append(user_id)

for user in pop_list:
Expand Down Expand Up @@ -463,7 +447,7 @@ async def update_user_db_info(self, user: sqlite3.Row, osu_info: dict, twitch_in
twitch_id = twitch_info.id
await self.users_db.update_user(new_twitch_username=twitch_name, new_osu_username=osu_username,
osu_user_id=osu_user_id, twitch_id=twitch_id)
logger.info(
logger.debug(
f'Updated user information for {user["twitch_username"]}: '
f'{osu_username} | {twitch_name} | {twitch_id} | {osu_user_id}')

Expand Down
18 changes: 14 additions & 4 deletions ronnia/helpers/database_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def __init__(self, db_path=None):
f"INNER JOIN users ON users.user_id=user_settings.user_id " \
f"WHERE user_settings.key=? AND users.twitch_username=?"

self.sql_string_get_setting_by_id = f"SELECT value FROM user_settings " \
f"INNER JOIN settings ON user_settings.key=settings.key " \
f"INNER JOIN users ON users.user_id=user_settings.user_id " \
f"WHERE user_settings.key=? AND users.twitch_id=?"

self.sql_string_get_range_setting = f"SELECT range_start, range_end FROM user_range_settings " \
f"INNER JOIN range_settings ON user_range_settings.key=range_settings.key " \
f"INNER JOIN users ON users.user_id=user_range_settings.user_id " \
Expand Down Expand Up @@ -105,6 +110,7 @@ async def initialize(self):
await self.define_setting('sub-only', 0, 'Subscribers only request mode.')
await self.define_setting('cp-only', 0, 'Channel Points only request mode.')
await self.define_setting('test', 0, 'Enables test mode.')
await self.define_setting('cooldown', 30, 'Cooldown for requests.')
await self.define_range_setting('sr', -1, -1, 'Star rating limit for requests.')

async def set_channel_updated(self, twitch_username: str):
Expand Down Expand Up @@ -180,7 +186,7 @@ async def get_multiple_users_by_ids(self, twitch_ids: List[int]) -> List[sqlite3
async def get_multiple_users_by_username(self, twitch_names: List[str]) -> List[sqlite3.Row]:
"""
Gets multiple users from database
:param twitch_ids: List of twitch ids
:param twitch_names: List of twitch names
:return: List of users
"""
query = f"SELECT * FROM users WHERE twitch_username IN ({','.join('?' for i in twitch_names)})"
Expand Down Expand Up @@ -315,7 +321,7 @@ async def handle_none_type_setting(self, value: str, setting_key: str):
if value is None:
r = await self.c.execute(f"SELECT default_value FROM settings WHERE key=?", (setting_key,))
value = await r.fetchone()
return bool(value[0])
return value[0]

async def handle_none_type_range_setting(self, value: Optional[sqlite3.Row], setting_key: str):
"""
Expand All @@ -331,14 +337,18 @@ async def handle_none_type_range_setting(self, value: Optional[sqlite3.Row], set
return value['default_low'], value['default_high']
return value['range_start'], value['range_end']

async def get_setting(self, setting_key: str, twitch_username: str):
async def get_setting(self, setting_key: str, twitch_username_or_id: Union[str, int]):
"""
Get the setting's current value for user
:param setting_key: Key of the setting
:param twitch_username: Twitch username
:return:
"""
result = await self.c.execute(self.sql_string_get_setting, (setting_key, twitch_username))
if isinstance(twitch_username_or_id, str):
result = await self.c.execute(self.sql_string_get_setting, (setting_key, twitch_username_or_id))
else:
result = await self.c.execute(self.sql_string_get_setting_by_id, (setting_key, twitch_username_or_id))

value = await result.fetchone()
return await self.handle_none_type_setting(value, setting_key)

Expand Down