def __init__(self, bot):
     self.wowsnews_jp = WowsNewsJP()
     self.bot = bot
     statuses = self.wowsnews_jp.get_latest_statuses()
     self.latest_id = statuses[0].id
     self.logger = Logger(__name__)
     self.check_task.start()
Beispiel #2
0
 def __init__(self, db_path):
     self.database = Database(db_path)
     self.logger = Logger(self.__class__.__name__)
     # if db file not found or empty, create file
     try:
         with open(db_path, 'rb') as f:
             if f.read() == b'':
                 self._create_table()
     except Exception as e:
         self.logger.info('Database not found.')
         self._create_table()
Beispiel #3
0
class Weather(commands.Cog):
    __slots__ = ('bot', 'logger', 'last_sent_date')

    def __init__(self, bot, logger=None):
        self.bot = bot
        self.logger = Logger(__name__) if logger is None else logger
        self.last_sent_date = None
        self.weather_task.start()

    @commands.command()
    async def weather(self, ctx):
        """ 天気を教えるよ! """
        self.logger.debug('Creating weather embed.')
        scraper = Scrape_weather()
        e, c = scraper.embed_builder()
        self.logger.debug('Created weather embed.')
        await ctx.send('```' + c + '```', embed=e)
        del scraper, e, c

    @tasks.loop(seconds=50)
    async def weather_task(self):
        now = datetime.datetime.now(tz=tz)
        if not (now.hour == 6 and now.minute == 30):
            return
        if self.last_sent_date == now.date():
            return
        else:
            self.last_sent_date = now.date()

        scraper = Scrape_weather()
        e, c = scraper.embed_builder()
        for guild in self.bot.guilds:
            for channel in guild.channels:
                if channel.name == 'main':
                    await channel.send('```' + c + '```', embed=e)
        del scraper, e, c
class Listener(commands.Cog):
    __slots__ = ('bot', 'logger')

    def __init__(self, bot, logger=None):
        self.bot = bot
        self.logger = Logger(__name__) if logger is None else logger

    @commands.Cog.listener()
    async def on_ready(self):
        print('----------')
        print('Logged in as')
        print('name:\t' + self.bot.user.name)
        print('id:\t' + str(self.bot.user.id))
        print('----------')

    @commands.Cog.listener()
    async def on_message(self, mes):
        self.logger.info(
            f'Message:{mes.content} author:{mes.author.name} id:{mes.author.id}'
        )
        # if mes.attachments:
        # 	for attachment in mes.attachments:
        # 		try:
        # 			await attachment.save(attachmentpath + str(attachment.id) + attachment.filename, seek_begin=True, use_cached=True)
        # 		except:
        # 			continue

    @commands.Cog.listener()
    async def on_command_error(self, ctx, error):
        pass

    @commands.Cog.listener()
    async def on_member_remove(self, member):
        self.logger.info(f'Member removed:{member.name} id:{member.id}')

    @commands.Cog.listener()
    async def on_raw_message_delete(self, payload):
        message = payload.cached_message
        if message:
            self.logger.info(
                f'Message deleted:{message.content} author:{message.author.id}'
            )
        else:
            self.logger.info('Message deleted. No content found.')
class Twitter_manager(commands.Cog):
    """
	twitter_manager class.
	Responsible for interactions with twitter.
	"""
    def __init__(self, bot):
        self.wowsnews_jp = WowsNewsJP()
        self.bot = bot
        statuses = self.wowsnews_jp.get_latest_statuses()
        self.latest_id = statuses[0].id
        self.logger = Logger(__name__)
        self.check_task.start()

    @tasks.loop(seconds=30)
    async def check_task(self):
        self.logger.debug('Checking for latest tweets.')
        statuses = self.wowsnews_jp.get_latest_statuses()
        # return if up to date
        if self.latest_id == statuses[0].id:
            self.logger.debug('Twitter_manager is up to date.')
            return
        to_send = []
        for status in statuses:
            # stop if id is the one saved
            if status.id == self.latest_id:
                self.logger.debug('This tweet has already been sent.')
                break
            to_send.insert(0, status)

        for guild in self.bot.guilds:
            for channel in guild.channels:
                if channel.name == 'wows-news':
                    for status in to_send:
                        await channel.send(
                            f'{status.text}\n{_create_url(status)}')

        self.latest_id = statuses[0].id
        self.logger.debug('Finished sending.')

    @check_task.before_loop
    async def before_check(self):
        await self.bot.wait_until_ready()
        await asyncio.sleep(1)
Beispiel #6
0
class WowsApi:
	def __init__(self, application_id):
		self.application_id = application_id
		self.logger = Logger(self.__class__.__name__)

	def get_warships_count(self):
		"""
		Get the number of warships registered in wows API.
		"""
		self.logger.debug('Counting warships.')
		response = requests.get('https://api.worldofwarships.asia/wows/encyclopedia/ships/?' \
			f'application_id={self.application_id}&limit=1')
		if response.status_code != 200:
			self.logger.critical('Invalid status code.')
			return
		text = response.text
		text_json = json.loads(text)
		if text_json['status'] != 'ok':
			self.logger.critical('Invalid status.')
			return
		warships_count = text_json['meta']['total']
		self.logger.debug(f'Found {warships_count} ships.')
		return warships_count

	def get_warships(self, pages):
		"""
		Get list of warships as list of Warship instance.
		"""
		self.logger.debug(f'Getting warships for {pages} pages.')
		warship_list = []
		for i in range(pages):
			response = requests.get('https://api.worldofwarships.asia/wows/encyclopedia/ships/?' \
				f'application_id={self.application_id}&page_no={i+1}&language=ja')
			if response.status_code != 200:
				self.logger.critical('Invalid status code.')
				return
			text = response.text
			text_json = json.loads(text)
			if text_json['status'] != 'ok':
				self.logger.critical('Invalid status code.')
				return
			values = text_json['data'].values()
			for v in values:
				temp = Warship.warship_from_dict(v)
				warship_list.append(temp)
		self.logger.debug(f'Created {len(warship_list)} warships.')
		return warship_list

	def get_ship_profile(self, ship_id):
		"""
		Get ShipParam instance of given ship id.
		"""
		response = requests.get('https://api.worldofwarships.asia/wows/encyclopedia/shipprofile/?' \
			f'application_id={self.application_id}&ship_id={ship_id}')
		if response.status_code != 200:
			self.logger.critical('Invalid status code.')
			return
		text = response.text
		text_json = json.loads(text)
		if text_json['status'] != 'ok':
			self.logger.debug('Invalid status code.')
			return
		param = text_json['data'][str(ship_id)]
		shipparam = ShipParam.shipparam_from_dict(param)
		return shipparam
		
	def information_about_encyclopedia(self):
		"""
		Get when encyclopedia was last updated.
		"""
		self.logger.debug('Fetching last ships_updated_at.')
		response = requests.get('https://api.worldofwarships.asia/wows/encyclopedia/info/?' \
			f'application_id={self.application_id}&fields=ships_updated_at')
		if response.status_code != 200:
			self.logger.critical('Invalid status code.')
			return
		text = response.text
		text_json = json.loads(text)
		if text_json['status'] != 'ok':
			self.logger.debug('Invalid status code.')
			return
		version = text_json['data']['ships_updated_at']
		self.logger.debug(f'Encyclopedia was last updated at {version}.')
		return version
class Database:
    """
	Database class.
	"""
    def __init__(self, db_path: str, logger=None):
        self.db_path = db_path
        self.logger = Logger(__name__) if logger is None else logger

    def fetchone(self, command: str, values=()):
        """
		Get one result from database.
		"""
        self.logger.debug(f'Executing script on {self.db_path}.')
        # connect and execute script
        try:
            conn = self._create_connection()
            cursor = conn.cursor()
            cursor.execute(command, values)
            result = cursor.fetchone()
        # sql errors
        except Exception as e:
            self.logger.critical(e)
            self.logger.critical(traceback.format_exc())
            result = None
        # close connection
        finally:
            self._close_connection(conn)

        self.logger.debug(f'Executing script finished on {self.db_path}.')
        return result

    def execute(self, command: str, values=()):
        """
		Get one result from database.
		"""
        self.logger.debug(f'Executing script on {self.db_path}.')
        # connect and execute script
        try:
            conn = self._create_connection()
            cursor = conn.cursor()
            cursor.execute(command, values)
        # sql errors
        except Exception as e:
            self.logger.critical(e)
            self.logger.critical(traceback.format_exc())
            result = None
        # close connection
        finally:
            self._close_connection(conn)

        self.logger.debug(f'Executing script finish on {self.db_path}.')

    def executescript(self, command: str):
        """
		Execute script on database.
		"""
        self.logger.debug(f'Executing script on {self.db_path}.')
        # connect and execute script
        try:
            conn = self._create_connection()
            cursor = conn.cursor()
            cursor.executescript(command)
        # sql errors
        except Exception as e:
            self.logger.critical(e)
            self.logger.critical(traceback.format_exc())
            result = None
        # close connection
        finally:
            self._close_connection(conn)

        self.logger.debug(f'Executing script finished on {self.db_path}.')

    def _create_connection(self) -> Connection:
        self.logger.debug('Connecting to database.')
        conn = sqlite3.connect(self.db_path)
        self.logger.debug('Connected to database.')
        return conn

    def _close_connection(self, conn):
        self.logger.debug('Closing connection to database.')
        conn.commit()
        conn.close()
        self.logger.debug('Closed connection to database.')
 def __init__(self, db_path: str, logger=None):
     self.db_path = db_path
     self.logger = Logger(__name__) if logger is None else logger
Beispiel #9
0
class Roles(commands.Cog):
    __slots__ = ('bot', 'logger')

    def __init__(self, bot):
        self.bot = bot
        self.logger = Logger(__name__)

    @commands.group()
    async def roles(self, ctx):
        """ 役職をいじれるよ! """
        if ctx.invoked_subcommand is None:
            await ctx.send('コマンドも教えてね!')

    @roles.command()
    async def create(self, ctx, name, color='red'):
        """ 役職を作るよ! roles create '役職の名前' '色(英語で教えてね!)' """
        try:
            color = matplotlib.colors.cnames.get(color)
        except IndexError:
            await ctx.send('名前と色も教えてね!')
            return

        color = discord.Colour(int(str(color)[1:], 16))
        await ctx.guild.create_role(name=name, colour=color)
        await ctx.send(name + ', いっちょあがり!')

    # @roles.command()
    # async def random(self, ctx, target=None):
    # 	if target is None:
    # 		await ctx.send('役職誰にあげるのかわかんないよ〜')
    # 		return
    # 	elif not check_user(target):
    # 		await ctx.send('誰この人!')
    # 		return

    # 	user = get_user(name=target)
    # 	give_role(user, role)

    # 	await ctx.send('じゃーん!何あげたでしょー')

    @roles.command()
    async def listnotused(self, ctx):
        """ 使ってない役職の一覧を貼るよ! """
        self.logger.debug('Processing listnotused.')
        b = False
        for role in ctx.guild.roles:
            if role.is_default():
                continue
            for member in ctx.guild.members:
                if role in member.roles:
                    b = True
            if not (b):
                await ctx.send(role.name + ',\t誰も使ってないよ!')
            b = False

        await ctx.send('はい、終わり!')

    @roles.command()
    async def deletenotused(self, ctx):
        """ 使ってない役職をすべて削除するよ! """
        self.logger.debug('Processing deletenotused.')
        b = False
        for role in ctx.guild.roles:
            if role.is_default():
                continue
            for member in ctx.guild.members:
                if role in member.roles:
                    b = True

            if not (b):
                self.logger.debug('Deleting role.')
                await ctx.send(role.name + ', バーン!')
                await role.delete()
                self.logger.debug('Deleted role.')
            b = False
        self.logger.debug('Processed deletenotused.')
        await ctx.send('はい、終わり!')

    # @roles.command()
    # async def hoist(self, ctx):
    # 	""" 全ての役職をオンラインメンバーとは別に役職メンバーを表示するよ! """
    # 	for role in ctx.guild.roles:
    # 		if not role.hoist:
    # 			await role.edit(hoist=True)
    # 	await ctx.send(':thumbsup:')

    @roles.command()
    async def mentionoff(self, ctx):
        """ 全ての役職をメンション不可能にするよ! """
        for role in ctx.guild.roles:
            if role.mentionable:
                await role.edit(mentionable=False)
        await ctx.send(':thumbsup:')
	def __init__(self, key):
		self.logger = Logger(self.__class__.__name__)
		self.api = WowsApi(key)
Beispiel #11
0
class WowsCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.logger = Logger(self.__class__.__name__)
        self.wowsdb = Wows_database(db_path)

    @commands.command()
    async def param(self, ctx, *, name):
        """
		そのぽふねのデータ教えてあげる!
		"""
        self.logger.info('Recieved param command.')
        if name is None:
            await ctx.send('どのぽふねのデータがほしいの?\n日本艦は漢字で登録されてるから気を付けて!')
            return
        result = self.wowsdb.get_warship(name)
        # exact match
        if isinstance(result, Warship):
            self.logger.info('Found exact match for a warship.')
            embed = self.embed_builder(result)
            await ctx.send(embed=embed)
        #another exact match
        elif len(result) == 1:
            self.logger.info('Found exact match for a warship.')
            embed = self.embed_builder(result[0])
            await ctx.send(embed=embed)
        elif not result:
            self.logger.debug('No result found.')
            await ctx.send('そんなもんねーよ!あ、日本艦は漢字で書いてね♡')
            return
        else:
            self.logger.info('Found multiple matches.')
            name_list = map(lambda ship: ship.name, result)
            mes = 'いっぱいヒットしちゃったよ~\n' \
             '```' + ', '.join(name_list) + '```'
            await ctx.send(mes)

    def embed_builder(self, warship: Warship):
        self.logger.debug('Creating embed.')

        d = warship.to_dict()
        name = d['name']
        tier = d['tier']
        nation = d['nation'][:2]
        shiptype = d['shiptype']
        embed = Embed(colour=0x793DB6,
                      title=d['name'],
                      description=f'T{tier} {nation.upper()} {shiptype}')
        a = embed.add_field

        s = self.wowsdb.get_shipparam(warship.ship_id)
        s = s.to_dict()

        mobility = ast.literal_eval(s['mobility'])
        if mobility is not None:
            rudder_time = mobility['rudder_time']
            turning_radius = mobility['turning_radius']
            max_speed = mobility['max_speed']
            a(name='機動性',
              value=f'{max_speed}kts 転舵時間{rudder_time}s 転舵半径{turning_radius}m',
              inline=False)

        hull = ast.literal_eval(s['hull'])
        if hull is not None:
            torp_barrels = hull['torpedoes_barrels']
            health = hull['health']
            artillery_barrels = hull['artillery_barrels']
            if torp_barrels == 0:
                a(name='船体性能',
                  value=f'体力{health}({health+tier*350}) 主砲{artillery_barrels}基',
                  inline=False)
            else:
                a(name='船体性能',
                  value=
                  f'体力{health}({health+tier*350}) 主砲{artillery_barrels}基 魚雷{torp_barrels}基',
                  inline=False)

        artillery = ast.literal_eval(s['artillery'])
        if artillery is not None:
            max_dispersion = artillery['max_dispersion']
            shot_delay = artillery['shot_delay']
            shells = artillery['shells']
            for key, shell in shells.items():
                if key == 'HE':
                    a(name=f'{key}',
                      value=
                      f'{shell["bullet_speed"]}ms^-1 最大{shell["damage"]} 装填{shot_delay}s 発火率{shell["burn_probability"]}%',
                      inline=False)
                else:
                    a(name=f'{key}',
                      value=
                      f'{shell["bullet_speed"]}ms^-1 最大{shell["damage"]} 装填{shot_delay}s',
                      inline=False)

        torpedoes = ast.literal_eval(s['torpedoes'])
        if torpedoes is not None:
            visibility_dist = torpedoes['visibility_dist']
            distance = torpedoes['distance']
            reload_time = torpedoes['reload_time']
            torp_speed = torpedoes['torpedo_speed']
            max_damage = torpedoes['max_damage']
            a(name='魚雷性能',
              value=
              f'被発見{visibility_dist}km 装填{reload_time}s 雷速{torp_speed}kts^-1 最大{max_damage}',
              inline=False)

        fire_control = ast.literal_eval(s['fire_control'])
        if fire_control is not None:
            distance = fire_control['distance']
            distance_increase = fire_control['distance_increase']
            a(name='射程', value=f'{distance}km', inline=False)

        concealment = ast.literal_eval(s['concealment'])
        if concealment is not None:
            detect_dist_plane = concealment['detect_distance_by_plane']
            detect_dist_ship = concealment['detect_distance_by_ship']
            if tier < 8:
                best_concealment = detect_dist_ship * 0.9 * 0.97
            else:
                best_concealment = detect_dist_ship * 0.9 * 0.9 * 0.97
            best_concealment = round(best_concealment, 2)
            a(name='隠蔽性',
              value=
              f'航空発見{detect_dist_plane}km 艦艇発見{detect_dist_ship}km 最良{best_concealment}km(誤差有)',
              inline=False)

        del a
        return embed
Beispiel #12
0
class Wows_database:
	"""
	Scrapes and registers data into database.
	"""
	__slots__ = ('database', 'logger')

	def __init__(self, db_path):
		self.database = Database(db_path)
		self.logger = Logger(__name__)
		# if db file not found or empty, create file
		try:
			with open(db_path, 'rb') as f:
				if f.read() == b'':
					self._create_table()
		except Exception as e:
			self.logger.info('Database not found.')
			self._create_table()


	async def update(self):
		"""
		Update database.
		"""
		self.logger.info('Update started.')
		try:
			# await self._update_medium()
			# await self._update_facebook()
			await self._update_hp()
		except Exception:
			self.logger.critical(f'Exception while updating: {traceback.format_exc()}')
		self.logger.info('Update finished.')


	def _create_table(self):
		self.logger.debug('Creating wows database table.')
		self.database.executescript("""
		CREATE TABLE wowsnews(
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			source TEXT,
			title TEXT,
			description TEXT,
			url TEXT,
			img TEXT
		);
		""")
		self.logger.debug('Created wows database table.')


	def _get_latest(self, source:str):
		"""
		Get latest news stored in database.

		Returns
		-------
		res : tuple, None
		"""
		self.logger.debug(f'Starting _get_latest source: {source}')
		res = self.database.fetchone('SELECT * FROM wowsnews WHERE source==? ORDER BY id DESC', (source,))
		self.logger.debug(f'_get_latest result: {res}')
		
		return res


	async def _update_hp(self):
		"""
		Check for new articles, if found update db.
		"""
		self.logger.info('Updating wows hp.')
		# get data and data from db.
		try:
			data = get_hp_articles()
		except ScrapingException:
			self.logger.critical('Scraping failed.')
			return
		data_db = self._get_latest('wowshomepage')
		
		# if database is up to date return
		if _is_same_data(data_db, data[0]):
			self.logger.info('Wows hp is up to date.')
			return
		# if same url already exists in database, return
		elif self._url_exists(data[0][3]):
			self.logger.info('Article with same url exists.')
			return
		# update db
		self.logger.info('Saving data.')
		try:
			self.database.execute('INSERT INTO wowsnews(source, title, description, url, img) VALUES(?, ?, ?, ?, ?)', data[0])
		except Exception as e:
			self.logger.critical(f'Inserting into database failed: {e}')
			return
		self.logger.info('Updated wows hp.')


	async def _update_facebook(self):
		"""
		Check for new articles, if found update db.
		"""
		self.logger.info('Updating facebook.')
		try:
			data = get_facebook_articles()
		except ScrapingException:
			self.logger.critical('Scraping failed.')
			return
		data_db = self._get_latest('facebook')

		# if up to date, return
		if _has_same_url(data_db, data[0]):
			self.logger.info('Facebook is up to date.')
			return
		# counter shows how many articles to update
		counter = 0
		for d in data:
			# if data is most recent in db
			if d == data_db:
				break
			counter += 1
		# data.reverse() not working, so using temp.reverse()
		temp = data
		temp.reverse()
		news = temp[:counter]
		# update db
		try:
			for new in news:
				# continue if url already exists in database
				if self._url_exists(new[3]):
					self.logger.info('Article with same url exists.')
					continue
				self.database.execute('INSERT INTO wowsnews(source, title, description, url, img) VALUES(?, ?, ?, ?, ?)', new)
		except Exception as e:
			self.logger.critical(f'Inserting into database failed: {e}')
			return
		self.logger.info('Updated facebook.')


	async def _update_medium(self):
		"""
		Check for new articles, if found update db.
		"""
		self.logger.info('Updating medium.')
		try:
			data = get_medium_articles()
		except ScrapingException:
			self.logger.critical('Scraping failed.')
			return

		# get latest data in database
		data_db = self._get_latest('medium')
		# if up to date, return
		if _is_same_data(data_db, data[0]):
			self.logger.info('Medium is up to date.')
			return
		# counter shows how many articles to update
		counter = 0
		for d in data:
			# if url is most recent in db
			if d == data_db:
				break
			counter += 1
		# data.reverse() not working, so using temp reverse()
		temp = data
		temp.reverse()
		news = temp[:counter]
		try:
			for new in news:
				self.database.execute('INSERT INTO wowsnews(source, title, description, url, img) VALUES(?, ?, ?, ?, ?)', new)
		except Exception as e:
			self.logger.critical(f'Inserting into database failed: {e}')
			return
		self.logger.info('Updated medium.')


	def _url_exists(self, url:str):
		self.logger.debug('Checking if url already exists in database.')
		self.logger.debug(f'url is {url[10:]}')
		try:
			res = self.database.fetchone(f'SELECT * FROM wowsnews WHERE url==?', (url,))
		except Exception as e:
			self.logger.critical(f'Fetching datbase failed: {e}')
			res = None
		self.logger.debug(f'Result: {res}')
		if not res:
			return False
		return True
Beispiel #13
0
 def __init__(self, key, db_path):
     self.logger = Logger(self.__class__.__name__)
     self.logger.debug('Initializing wows class.')
     self.wowsapi = WowsApi(key)
     self.wowsdb = Wows_database(db_path)
Beispiel #14
0
class WorldofWarships:
    def __init__(self, key, db_path):
        self.logger = Logger(self.__class__.__name__)
        self.logger.debug('Initializing wows class.')
        self.wowsapi = WowsApi(key)
        self.wowsdb = Wows_database(db_path)

    def update(self):
        # check version
        version_db = self.wowsdb.get_db_version()
        version_api = self.wowsapi.get_api_version()

        # return if version is up to date.
        if version_db == version_api:
            self.logger.debug(
                f'Returning as database has latest version {version_db}.')
            return
        self.update_warships()
        self.update_shipparams()

        # finally update version
        self.wowsdb.update_version(version_api)

    def update_warships(self):
        """
		Update warships table in database.
		"""
        self.logger.debug('Updating warships in database.')
        warships_count = self.wowsapi.get_warships_count()
        pages = math.ceil(warships_count / 100)

        warships_api = self.wowsapi.get_warships(pages)
        warships_db = self.wowsdb.get_warships()
        warships_db_ids = list(
            map(lambda warship: warship.ship_id, warships_db))

        for warship in warships_api:
            # if warship not found in db, register
            if warship.ship_id not in warships_db_ids:
                self.wowsdb.register_ship(warship)
            else:
                index = warships_db_ids.index(warship.ship_id)
                warship_db = warships_db[index]
                assert warship.ship_id == warship_db.ship_id
                # if warship from api differes from warship in db, update
                if warship != warship_db:
                    self.wowsdb.update_warship(warship)
        self.logger.debug('Warships updated.')

    def update_shipparams(self):
        """
		Update shipparameters table in database.
		"""
        self.logger.debug('Updating shipparams in database.')
        ship_ids = self.wowsdb.get_ship_ids()
        for ship_id in ship_ids:
            param = self.wowsapi.get_ship_profile(ship_id[0])
            self.wowsdb.update_shipparam(param)

        self.logger.debug('Ship parameters updated.')
Beispiel #15
0
	def __init__(self, application_id):
		self.application_id = application_id
		self.logger = Logger(self.__class__.__name__)
Beispiel #16
0
 def __init__(self, bot):
     self.bot = bot
     self.logger = Logger(self.__class__.__name__)
     self.wowsdb = Wows_database(db_path)
Beispiel #17
0
 def __init__(self, bot, logger=None):
     self.bot = bot
     self.logger = Logger(__name__) if logger is None else logger
Beispiel #18
0
class NewRoles(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.logger = Logger(__name__)

    @commands.command()
    async def dl(self, ctx):
        """ Temporal command for deleting guild activity roles. """
        ceiling = ctx.guild.get_role(632304461087506442)
        roles = ctx.guild.roles
        # for role in roles:
        # 	if role.position is not 0 and \
        # 		role < ceiling:
        # 		self.logger.debug(f'deleting {role}')
        # 		await role.delete()
        # self.logger.debug('done.')
        roles = await self._get_guild_activity_roles()
        for role in roles:
            self.logger.debug(f'deleting {role}')
            await role.delete()
        self.logger.debug('done.')

    @commands.command()
    async def role_task(self, ctx):
        self.logger.debug('starting role_task.')
        members = ctx.guild.members
        self.logger.debug(f'found {len(members)} members.')
        guild_activity_roles = await self._get_guild_activity_roles()
        self.logger.debug('got guild activity roles.')

        # give or remove roles
        for member in members:
            await self._configure_roles(member)

        # remove unused roles
        await self._remove_unused_activity_roles(guild_activity_roles)

        # # configure hierarchy
        # guild_activity_roles = await self._get_guild_activity_roles()
        # await self._configure_hierarchy(guild_activity_roles)

        self.logger.debug('finished role_task.')

    async def _configure_roles(self, member):
        """
		Give or remove activity roles of the member.
		"""
        self.logger.debug('configuring roles.')
        activities = member.activities  # member's activities
        anames = [a.name for a in activities]
        activity_roles = await self._get_activity_roles(
            member)  # member's activity roles given
        rnames = [r.name for r in activity_roles]
        self.logger.debug(
            f'{len(anames)} activity names and {len(rnames)} role names found.'
        )
        # removing process
        for rname in rnames:
            self.logger.debug(f'processing role name {rname}.')
            # if member has a role which the member does not play, remove
            if rname not in anames:
                self.logger.debug('removing role.')
                role = self._get_role(activity_roles, rname)
                if not role:
                    self.logger.critical('role not found.')
                    return
                await member.remove_role(role)
            # else, member has a role which the member plays, so pass

        # giving process
        for aname in anames:
            # if it was Custom status, you can't fetch the status name
            # thus skip giving process
            if aname == 'Custom Status':
                continue
            self.logger.debug(f'giving role named {aname}.')
            # if member has activity which the member does not have a role of, give that
            if aname not in rnames:
                self.logger.debug('giving role.')
                role = await self._get_opt_role(aname)
                self.logger.debug('adding role.')
                await member.add_roles(role)
                self.logger.debug('added role.')
            # else, member has activity and has role of, pass

    async def _get_opt_role(self, aname):
        """
		Get a role where name is aname.
		If that role exists, return that.
		If it does not exist, create one and return that.
		"""
        self.logger.debug('finding for optimum role.')
        roles = await self._get_guild_activity_roles()
        for role in roles:
            if role.name == aname:
                return role
        role = await self._create_role(aname)
        return role

    async def _create_role(self, aname):
        """
		Return role with given name aname and position where one larger than role_floor.
		"""
        self.logger.debug('creating role.')
        guild = get_guild(self.bot)
        self.logger.debug('found guild.')
        role = await guild.create_role(name=aname, hoist=True)
        self.logger.debug(f'created role {aname}.')
        floor_role = get_guild(self.bot).get_role(_activity_role_floor)
        self.logger.debug('found floor_role.')
        self.logger.debug(f'floor position is {floor_role.position}.')
        position = floor_role.position
        # role.edit does not work sometimes
        while position is not role.position:
            self.logger.debug(
                f'position is {position} and role.position is {role.position}')
            await role.edit(position=position)

        self.logger.debug('returning role.')
        return role

    def _get_role(self, activity_roles, rname):
        """
		Get role where name is rname in activity_roles.
		Returns None if no role found.
		"""
        for arole in activity_roles:
            if arole.name == rname:
                return arole
        return None

    # merge _get_guild_activity_roles() and _get_activity_roles() later
    async def _get_guild_activity_roles(self):
        """
		Return list of activity roles of a given guild.
		"""
        self.logger.debug('finding for guild activity roles.')
        guild = get_guild(self.bot)
        roles = guild.roles

        floor = guild.get_role(_activity_role_floor)
        ceiling = guild.get_role(_activity_role_ceiling)

        self.logger.debug(f'{len(roles)} roles found.')
        activity_roles = []
        self.logger.debug(
            f'floor position is {floor.position} and ceiling position is {ceiling.position}.'
        )
        for role in roles:
            if role < ceiling \
             and floor < role:
                activity_roles.append(role)
        self.logger.debug(
            f'returning roles list with {len(activity_roles)} items.')
        return activity_roles

    async def _get_activity_roles(self, member):
        """
		Return list of activity roles of a given member.
		"""
        roles = member.roles
        guild = get_guild(self.bot)
        floor = guild.get_role(_activity_role_floor)
        ceiling = guild.get_role(_activity_role_ceiling)

        activity_roles = []
        for role in roles:
            if role < ceiling \
             and floor < role:
                activity_roles.append(role)
        return activity_roles

    async def _remove_unused_activity_roles(self, guild_activity_roles):
        """
		Removes all unused activity roles.
		"""
        for role in guild_activity_roles:
            if not role.members:
                await role.delete()

    async def _configure_hierarchy(self, guild_activity_roles):
        """
		Configures hierarchy of guild's activity roles.
		Hirarchy will be configured by its number of players.
		"""
        self.logger.debug('Configuring hierarchy.')
        new_pos = get_guild(self.bot).get_role(_activity_role_floor).position
        # sort roles in order of members
        roles = sorted(guild_activity_roles,
                       key=lambda role: len(role.members))
        roles.reverse()
        for role in roles:
            # edit role if needed
            self.logger.debug(
                f'{role} is at {role.position} and new position is {new_pos}')
            if not role.position == new_pos:
                await role.edit(position=new_pos)
            pos = +1
Beispiel #19
0
 def __init__(self, bot, logger=None):
     self.bot = bot
     self.logger = Logger(__name__) if logger is None else logger
     self.last_sent_date = None
     self.weather_task.start()
Beispiel #20
0
 def __init__(self, bot):
     self.bot = bot
     self.logger = Logger(__name__)
Beispiel #21
0
class Wows_database:
    """
	Wows_database class.
	Responsible for interactions with database.
	"""
    __slots__ = ('database', 'logger')

    def __init__(self, db_path):
        self.database = Database(db_path)
        self.logger = Logger(self.__class__.__name__)
        # if db file not found or empty, create file
        try:
            with open(db_path, 'rb') as f:
                if f.read() == b'':
                    self._create_table()
        except Exception as e:
            self.logger.info('Database not found.')
            self._create_table()

    def _create_table(self):
        self.logger.debug('Creating wows database table.')
        self.database.executescript("""
		CREATE TABLE players(
			discord_id INTEGER PRIMARY KEY AUTOINCREMENT,
			wows_id INTEGER,
			in_game_name TEXT,
			clan TEXT
		);
		CREATE TABLE version (
			version_id INTEGER PRIMARY KEY AUTOINCREMENT,
			ships_updated_at INTGER
		);
		CREATE TABLE updates(
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			ship_id INTEGER,
			diff TEXT
		);
		CREATE TABLE warships(
			price_gold INTEGER,
			ship_id_str TEXT,
			has_demo_profile INTEGER,
			images TEXT,
			modules TEXT,
			modules_tree TEXT,
			nation TEXT,
			is_premium INTEGER,
			ship_id INTEGER PRIMARY KEY,
			price_credit INTEGER,
			default_profile TEXT,
			upgrades TEXT,
			tier INTEGER,
			next_ships TEXT,
			mod_slots INTEGER,
			type TEXT,
			is_special INTEGER,
			name TEXT
		);
		CREATE TABLE shipparams(
			engine TEXT,
			anti_aircraft TEXT,
			mobility TEXT,
			hull TEXT,
			atbas TEXT,
			artillery TEXT,
			torpedoes TEXT,
			fighters TEXT,
			ship_id INTEGER PRIMARY KEY,
			fire_control TEXT,
			weaponry TEXT,
			flight_control TEXT,
			concealment REAL,
			armour TEXT,
			dive_bomber TEXT
		);
		INSERT INTO version(ships_updated_at) VALUES('initial value');
		""")
        self.logger.debug('Created wows database table.')

    def get_db_version(self):
        """
		Get the version of database.
		"""
        command = 'SELECT ships_updated_at from version ORDER BY version_id desc'
        result = self.database.fetch(command)
        version = result[0]
        self.logger.debug('Returning database version.')
        return version

    def update_version(self, version):
        """
		Update version to given version.
		"""
        command = 'INSERT INTO version(ships_updated_at) VALUES(?)'
        self.database.execute(command, (version, ))
        self.logger.debug('Database updated.')

    def get_warship(self, name) -> Warship:
        """
		Get information of a warship of given name.
		If many data match, returns as list of Warship instance.
		"""
        self.logger.debug(f'Searching for a warship with {name=}.')
        # exact match
        result = self.database.fetch('SELECT * FROM warships WHERE name=?',
                                     (name, ))
        if result:
            self.logger.debug('Found exact match.')
            warship = Warship.warship_from_tuple(result)
            return warship
        results = self.database.fetch(
            f'SELECT * FROM warships WHERE name LIKE ?', (f'{name}%', ),
            count=10)
        self.logger.debug('Found close match.')
        warships = list(
            map(lambda result: Warship.warship_from_tuple(result), results))
        return warships

    def get_warships(self) -> list:
        """
		Get list of warships as list of Warship instance.
		"""
        results = self.database.fetch('SELECT * FROM warships', count=-1)
        warships = list(
            map(lambda result: Warship.warship_from_tuple(result), results))
        return warships

    def get_ship_ids(self) -> list:
        """
		Get ship ids stored in database as a list.
		"""
        result = self.database.fetch('SELECT ship_id from warships', count=-1)
        return result

    def get_shipparam(self, ship_id) -> ShipParam:
        """
		Get ship parameters of given ship_id.
		"""
        result = self.database.fetch(
            'SELECT * FROM shipparams WHERE ship_id=?', (ship_id, ))
        if not result:
            return None
        param = ShipParam.shipparam_from_tuple(result)
        return param

    def update_warship(self, warship):
        """
		Update database with given warship.
		"""
        self.deregister_ship(warship.ship_id)
        self.register_ship(warship)

    def update_shipparam(self, param: ShipParam):
        self.deregister_shipparam(param.ship_id)
        self.register_shipparam(param)

    def register_shipparam(self, param: ShipParam):
        command = 'INSERT INTO shipparams VALUES (?,?,?,?,?,?,?,' \
         '?,?,?,?,?,?,?,?)'
        values = param.to_tuple()
        self.database.execute(command, values)

    def deregister_shipparam(self, ship_id: int):
        command = 'DELETE FROM shipparams WHERE ship_id=?'
        values = (ship_id, )
        self.database.execute(command, values)

    def register_ship(self, warship: Warship):
        """
		Register ship into database.
		"""
        command = 'INSERT INTO warships VALUES(?,?,?,?,?,?,?,?,?,?,' \
                  '?,?,?,?,?,?,?,?)'
        values = warship.to_tuple()
        self.database.execute(command, values)

    def deregister_ship(self, ship_id: int):
        """
		Deregister warship from database.
		"""
        command = 'DELETE FROM warships WHERE ship_id=?'
        values = (ship_id, )
        self.database.execute(command, values)

    def register_user(self, player, discord_id):
        """
		Register discord user into database.
		"""
        self.logger.debug(f'Registering {player["nickname"]}.')
        self.database.execute(
            'INSERT INTO players VALUES(?, ?, ?, ?) ',
            (discord_id, player['account_id'], player['nickname'], ''))
        self.logger.debug('Registered player.')

    def deregister_user(self, discord_id):
        """
		Deregister discord user from database.
		"""
        self.logger.debug('Deregistering user.')
        self.database.execute('DELETE FROM players WHERE discord_id = ?',
                              (discord_id, ))
        self.logger.debug('Deregistered user.')

    def is_user_registered(self, discord_id):
        """
		Checks is given discord_id is registered.
		"""
        result = self.database.fetch(
            'SELECT discord_id from players WHERE discord_id = ?',
            (discord_id, ))
        self.logger.debug(f'{result=}')
        return result is not None
class ApiManager:
	def __init__(self, key):
		self.logger = Logger(self.__class__.__name__)
		self.api = WowsApi(key)

	def get_player_info(self, player_name):
		self.logger.debug(f'Creating player info for {player_name}.')
		player = self.api.players(Region.AS, player_name)
		if not player:
			return
		elif player['status'] != 'ok':
			return
		player_id = player['data'][0]['account_id']
		player_data = self.api.player_personal_data(Region.AS, player_id)
		if not player_data:
			return
		elif player_data['status'] != 'ok':
			return
		player_data = player_data['data'][str(player_id)]
		self.logger.debug('Created player_data successfully.')
		return player_data
	
	def get_api_version(self):
		"""
		Get api's version.
		"""
		self.logger.debug('Fetching version for api.')
		version = self.api.information_about_encyclopedia()
		self.logger.debug('Returning api version.')
		return version

	def get_warships(self):
		"""
		Get warships fetched from wows api.
		"""
		self.logger.debug('Fetching for warships api.')
		warships = []
		warships_count = self.api.get_warships_count()
		pages = math.ceil(warships_count/100) 
		warships = self.api.get_warships(pages)
		self.logger.debug('Created warships.')
		return warships