<commit_before>import discord
import os
from discord.ext import commands
from cogs.utils.dataIO import dataIO
from copy import deepcopy
import time
import asyncio
import datetime


class VoiceScore:

	def __init__(self,bot):
		self.bot=bot
		self.settings_path = "data/voicescore/settings.json"
		self.settings = dataIO.load_json(self.settings_path)
		self.scores_path = "data/voicescore/scores.json"
		self.scores = dataIO.load_json(self.scores_path)
		self.eligibleChannels_path = "data/voicescore/channels.json"
		self.activeVCUsers = {}
		self.eligibleChannels = {}
		self.activeVClist = []
		self.payoutMembers = []
		self.timeLast = int(time.time())

	@commands.command(pass_context=True)
	async def setchannel(self,ctx):
		""" This sets the channel which you send the command to as the text channel for announcements"""
		channel=ctx.message.channel

		self.settings["ChannelID"] = channel.id
		self.settings["ChannelName"] = channel.name
		self.save_settings()
		await self.bot.say("Set this channel for all Voice state Announcements")
		await self._getchannel(ctx)

	@commands.command(pass_context=True)
	async def getchannel(self,ctx):
		"""Returns the set announcement channel. Try using setchannel first."""
		await self._getchannel(ctx)

	@commands.command(pass_context=True)
	async def setpayoutscore(self,ctx, message:int):
		"""Sets the payout for when a user crosses the score threshold"""
		channel=ctx.message.channel

		self.settings["CreditsPerScore"] = message
		self.save_settings()
		await self.bot.say("New Payout set to {}".format(self.settings["CreditsPerScore"]))

	@commands.command(pass_context=True)
	async def getpayoutscore(self,ctx):
		"""Returns the current payout for when a user crosses the score threshold."""
		await self.bot.say("Payout set to {}".format(self.settings["CreditsPerScore"]))

	@commands.command(pass_context=True)
	async def set_tts(self,ctx,message):
		"""Sets whether the bot repeats what you said in Text to Speech or not. Accepts only true or false as the operator."""
		if "true" in message:
			self.settings["TTS"] = True
			await self.bot.say("TTS is now active")
		elif "false" in message:
			self.settings["TTS"] = False
			await self.bot.say("TTS is no longer active")
		else:
			await self.bot.say("Please say either true or false.")
		self.save_settings()

	@commands.command(pass_context = True)
	async def get_all_vcmembers(self,ctx):
		await self.bot.say("***Current users active in Voice Channels:*** \n ```{}```".format(await self.voice_state(ctx.message.author,ctx.message.author)))

	@commands.command(pass_context = True)
	async def get_score(self,ctx):
		member = ctx.message.author
		server = ctx.message.server
		if server.id in self.scores:
			if member.id in self.scores[server.id]:
				output = self.scores[server.id][member.id]
				await self.bot.say("{}, your score is {}".format(member.mention, output))
			else:
				await self.bot.say("{}, you have no score yet! Connect to a voice channel to earn some.".format(member.mention))
		else:
			await self.bot.say("{}, you have no score yet! Connect to a voice channel to earn some.".format(member.mention))

	@commands.command(pass_context=True)
	async def unixtime(self,ctx):
		print("Unix Time: {}".format(time.time()))
		print("DateTime: {}".format(time.time()))
		printtime = datetime.datetime.fromtimestamp(int(time.time()))
		await self.bot.say("Unix Time:{} \nDate Time: {}".format(time.time(),printtime))

	async def _getchannel(self,ctx):
		channelID = self.settings["ChannelID"]
		channelName = self.settings["ChannelName"]

		await self.bot.say("Name: {} \nID: {}".format(channelName,channelID))

	async def voice_state_message_primer(self,message):
		author = message.author
		await asyncio.sleep(5)
		await self.voice_state(author,author)
		return

	async def voice_state(self,userbefore,userafter):
		server = userbefore.server
		sid = server.id
		afkChannel = userbefore.server.afk_channel
		timeNow = int(time.time())
		if sid not in self.activeVCUsers.keys():
			self.activeVCUsers[sid] = {}
		if sid not in self.eligibleChannels.keys():
			self.eligibleChannels[sid] = {}
		if sid not in self.scores.keys():
			self.scores[sid] = {}
		if sid not in self.scores.keys():
			self.scores[sid] = {}

		vcMembers = 0
		ovcMembers = 0
		eligibleChannel = False
		# for loop that checks each channels eligability for score and assings the json true or not.
		# needs to be here for updating.
		# doesnt actually need to save to json. Did that for figurings
		tempEligible = []
		for currServer in self.bot.servers:
			for channel in currServer.channels:
				vcMembers = len(channel.voice_members)
				ovcMembers = vcMembers - 1
				if ovcMembers > 0:
					if channel != afkChannel:
						tempEligible.append("{}".format(channel))


		

		# for loop to check conditions of eligibility of member. not deafened, not single channel afk,
		# not afk channel. if works, update the active voice client list.
		tempVClist = []
		for member in server.members:
			if member.voice_channel is not None:
				vcID = member.voice.voice_channel.id
				if self._finditem(self.eligibleChannels, vcID):
					if not member.self_deaf and not member.is_afk and not member.bot:
						tempVClist.append(member)

		self.activeVClist = tempVClist
		totalVCmembers = len(self.activeVClist)

		tempNameList = []
		timeBetween = timeNow - self.timeLast
		adjustAmount = int(timeBetween/10)
		adjustAmount = adjustAmount * totalVCmembers
		adjustedScore = timeBetween + adjustAmount

		for member in self.activeVClist:
			if member.id not in self.scores[sid]:
				self.scores[sid][member.id] = 0
			self.scores[sid][member.id] += adjustedScore
			finalScore = self.checkScores(server, member)
			self.scores[sid][member.id] = finalScore
			tempNameList.append(member.name)

		timestamp = datetime.datetime.fromtimestamp(int(time.time()))
		scoreGiven = "\nScore given: {} \nMembers: {}".format(adjustedScore, tempNameList)
		eligChannels = "Eligible Channels: {}".format(tempEligible)

		if len(self.payoutMembers) > 0:
			payOutMems = "Payed out members: {}".format(self.payoutMembers)
			with open("data/voicescore/log.txt", "a") as log_file:
				log_file.write("Time: {} \n{} \n{}".format(timestamp, scoreGiven,eligChannels,payOutMems))
		else:
			with open("data/voicescore/log.txt", "a") as log_file:
				log_file.write("Time: {} \n{} \n{} \n{}".format(timestamp, scoreGiven,eligChannels,"No Members payed out"))

		vcMembers = 0
		ovcMembers = 0
		eligibleChannel = False
		tempEligible = []
		for currServer in self.bot.servers:
			for channel in currServer.channels:
				vcMembers = len(channel.voice_members)
				ovcMembers = vcMembers - 1
				if ovcMembers > 0:
					if channel != afkChannel:
						self.eligibleChannels[currServer.id][channel.id] = True
						tempEligible.append("{}".format(channel))
					else:
						print("{} users now AFK".format(vcMembers))
				else:
					self.eligibleChannels[currServer.id][channel.id] = False
			self.saveChannels()


		self.saveScores()
		self.timeLast = int(time.time())
		self.payoutMembers = []
		return(tempNameList)

	def checkScores(self, server, member):
		currScore = self.scores[server.id][member.id]
		threshold = int(self.settings["ScoreThreshold"])
		if currScore >= threshold:
			currScore -= threshold
			self.payOut(member)
			return currScore
		else:
			return currScore

	def payOut(self, member):
		#payout method with bank access. check coupon cog for help. coupon redeem
		econ = self.bot.get_cog('Economy')
		if econ == None:
			print("Error loading economy cog.")
			return
		basePot = self.settings["CreditsPerScore"] #TODO this needs to be a setting
		if econ.bank.account_exists(member):
			econ.bank.deposit_credits(member, basePot) #TODO make a settings entry
			self.payoutMembers.append(member.name)
		else:
			print("User {} has no account, failed to pay".format(member.name))

	def saveChannels(self):
		dataIO.save_json(self.eligibleChannels_path, self.eligibleChannels)
<commit_msg>Update to track keyerror for unknown channel<commit_after>import discord
import os
from discord.ext import commands
from cogs.utils.dataIO import dataIO
from copy import deepcopy
import time
import asyncio
import datetime


class VoiceScore:

	def __init__(self,bot):
		self.bot=bot
		self.settings_path = "data/voicescore/settings.json"
		self.settings = dataIO.load_json(self.settings_path)
		self.scores_path = "data/voicescore/scores.json"
		self.scores = dataIO.load_json(self.scores_path)
		self.eligibleChannels_path = "data/voicescore/channels.json"
		self.activeVCUsers = {}
		self.eligibleChannels = {}
		self.activeVClist = []
		self.payoutMembers = []
		self.timeLast = int(time.time())

	@commands.command(pass_context=True)
	async def setchannel(self,ctx):
		""" This sets the channel which you send the command to as the text channel for announcements"""
		channel=ctx.message.channel

		self.settings["ChannelID"] = channel.id
		self.settings["ChannelName"] = channel.name
		self.save_settings()
		await self.bot.say("Set this channel for all Voice state Announcements")
		await self._getchannel(ctx)

	@commands.command(pass_context=True)
	async def getchannel(self,ctx):
		"""Returns the set announcement channel. Try using setchannel first."""
		await self._getchannel(ctx)

	@commands.command(pass_context=True)
	async def setpayoutscore(self,ctx, message:int):
		"""Sets the payout for when a user crosses the score threshold"""
		channel=ctx.message.channel

		self.settings["CreditsPerScore"] = message
		self.save_settings()
		await self.bot.say("New Payout set to {}".format(self.settings["CreditsPerScore"]))

	@commands.command(pass_context=True)
	async def getpayoutscore(self,ctx):
		"""Returns the current payout for when a user crosses the score threshold."""
		await self.bot.say("Payout set to {}".format(self.settings["CreditsPerScore"]))

	@commands.command(pass_context=True)
	async def set_tts(self,ctx,message):
		"""Sets whether the bot repeats what you said in Text to Speech or not. Accepts only true or false as the operator."""
		if "true" in message:
			self.settings["TTS"] = True
			await self.bot.say("TTS is now active")
		elif "false" in message:
			self.settings["TTS"] = False
			await self.bot.say("TTS is no longer active")
		else:
			await self.bot.say("Please say either true or false.")
		self.save_settings()

	@commands.command(pass_context = True)
	async def get_all_vcmembers(self,ctx):
		await self.bot.say("***Current users active in Voice Channels:*** \n ```{}```".format(await self.voice_state(ctx.message.author,ctx.message.author)))

	@commands.command(pass_context = True)
	async def get_score(self,ctx):
		member = ctx.message.author
		server = ctx.message.server
		if server.id in self.scores:
			if member.id in self.scores[server.id]:
				output = self.scores[server.id][member.id]
				await self.bot.say("{}, your score is {}".format(member.mention, output))
			else:
				await self.bot.say("{}, you have no score yet! Connect to a voice channel to earn some.".format(member.mention))
		else:
			await self.bot.say("{}, you have no score yet! Connect to a voice channel to earn some.".format(member.mention))

	@commands.command(pass_context=True)
	async def unixtime(self,ctx):
		print("Unix Time: {}".format(time.time()))
		print("DateTime: {}".format(time.time()))
		printtime = datetime.datetime.fromtimestamp(int(time.time()))
		await self.bot.say("Unix Time:{} \nDate Time: {}".format(time.time(),printtime))

	async def _getchannel(self,ctx):
		channelID = self.settings["ChannelID"]
		channelName = self.settings["ChannelName"]

		await self.bot.say("Name: {} \nID: {}".format(channelName,channelID))

	async def voice_state_message_primer(self,message):
		author = message.author
		await asyncio.sleep(5)
		await self.voice_state(author,author)
		return

	async def voice_state(self,userbefore,userafter):
		server = userbefore.server
		sid = server.id
		afkChannel = userbefore.server.afk_channel
		timeNow = int(time.time())
		if sid not in self.activeVCUsers.keys():
			self.activeVCUsers[sid] = {}
		if sid not in self.eligibleChannels.keys():
			self.eligibleChannels[sid] = {}
		if sid not in self.scores.keys():
			self.scores[sid] = {}
		if sid not in self.scores.keys():
			self.scores[sid] = {}

		vcMembers = 0
		ovcMembers = 0
		eligibleChannel = False
		# for loop that checks each channels eligability for score and assings the json true or not.
		# needs to be here for updating.
		# doesnt actually need to save to json. Did that for figurings
		tempEligible = []
		for currServer in self.bot.servers:
			for channel in currServer.channels:
				vcMembers = len(channel.voice_members)
				ovcMembers = vcMembers - 1
				if ovcMembers > 0:
					if channel != afkChannel:
						tempEligible.append("{}".format(channel))


		
		self.saveChannels()
		# for loop to check conditions of eligibility of member. not deafened, not single channel afk,
		# not afk channel. if works, update the active voice client list.
		tempVClist = []
		for member in server.members:
			if member.voice_channel is not None:
				vcID = member.voice.voice_channel.id
				if self._finditem(self.eligibleChannels, vcID):
					if not member.self_deaf and not member.is_afk and not member.bot:
						tempVClist.append(member)

		self.activeVClist = tempVClist
		totalVCmembers = len(self.activeVClist)

		tempNameList = []
		timeBetween = timeNow - self.timeLast
		adjustAmount = int(timeBetween/10)
		adjustAmount = adjustAmount * totalVCmembers
		adjustedScore = timeBetween + adjustAmount

		for member in self.activeVClist:
			if member.id not in self.scores[sid]:
				self.scores[sid][member.id] = 0
			self.scores[sid][member.id] += adjustedScore
			finalScore = self.checkScores(server, member)
			self.scores[sid][member.id] = finalScore
			tempNameList.append(member.name)

		timestamp = datetime.datetime.fromtimestamp(int(time.time()))
		scoreGiven = "\nScore given: {} \nMembers: {}".format(adjustedScore, tempNameList)
		eligChannels = "Eligible Channels: {}".format(tempEligible)

		if len(self.payoutMembers) > 0:
			payOutMems = "Payed out members: {}".format(self.payoutMembers)
			with open("data/voicescore/log.txt", "a") as log_file:
				log_file.write("Time: {} \n{} \n{}".format(timestamp, scoreGiven,eligChannels,payOutMems))
		else:
			with open("data/voicescore/log.txt", "a") as log_file:
				log_file.write("Time: {} \n{} \n{} \n{}".format(timestamp, scoreGiven,eligChannels,"No Members payed out"))

		vcMembers = 0
		ovcMembers = 0
		eligibleChannel = False
		tempEligible = []
		for currServer in self.bot.servers:
			for channel in currServer.channels:
				vcMembers = len(channel.voice_members)
				ovcMembers = vcMembers - 1
				if ovcMembers > 0:
					if channel != afkChannel:
						self.eligibleChannels[currServer.id][channel.id] = True
						tempEligible.append("{}".format(channel))
					else:
						print("{} users now AFK".format(vcMembers))
				else:
					self.eligibleChannels[currServer.id][channel.id] = False
			

		self.saveChannels()
		self.saveScores()
		self.timeLast = int(time.time())
		self.payoutMembers = []
		return(tempNameList)

	def checkScores(self, server, member):
		currScore = self.scores[server.id][member.id]
		threshold = int(self.settings["ScoreThreshold"])
		if currScore >= threshold:
			currScore -= threshold
			self.payOut(member)
			return currScore
		else:
			return currScore

	def payOut(self, member):
		#payout method with bank access. check coupon cog for help. coupon redeem
		econ = self.bot.get_cog('Economy')
		if econ == None:
			print("Error loading economy cog.")
			return
		basePot = self.settings["CreditsPerScore"] #TODO this needs to be a setting
		if econ.bank.account_exists(member):
			econ.bank.deposit_credits(member, basePot) #TODO make a settings entry
			self.payoutMembers.append(member.name)
		else:
			print("User {} has no account, failed to pay".format(member.name))

	def saveChannels(self):
		dataIO.save_json(self.eligibleChannels_path, self.eligibleChannels)

{'fraction_non_alphanumeric': 0.12295491444985637, 'fraction_numerical': 0.0016235793680529536, 'mean_word_length': 4.3561872909699, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5905416', 'n_tokens_mistral': 5794, 'n_tokens_neox': 5124, 'n_words': 1313}