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.')
Beispiel #2
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
Beispiel #3
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 #4
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