major logic changes. improve performance. simplify code.
This commit is contained in:
31
PICable.py
31
PICable.py
@@ -10,6 +10,7 @@ LIMIT_STARS = 200
|
|||||||
LIMIT_NLOC = 100000
|
LIMIT_NLOC = 100000
|
||||||
MARGIN = 0.1
|
MARGIN = 0.1
|
||||||
CLONE_DIR = "~/temp/PICable"
|
CLONE_DIR = "~/temp/PICable"
|
||||||
|
EXCLUDED_LANGUAGES = ["CSV", "diff", "INI", "JSON", "Markdown", "reStructuredText", "SVG", "Text", "YAML"]
|
||||||
|
|
||||||
|
|
||||||
def get_stars_info(owner, repository, request_headers):
|
def get_stars_info(owner, repository, request_headers):
|
||||||
@@ -47,28 +48,29 @@ def get_commits_last_30_days(owner, repository, request_headers):
|
|||||||
|
|
||||||
|
|
||||||
def get_lines_of_code(owner, repository):
|
def get_lines_of_code(owner, repository):
|
||||||
repo_url = f"https://github.com/{owner}/{repository}.git"
|
repository_url = f"https://github.com/{owner}/{repository}.git"
|
||||||
repository_clone_dir = os.path.expanduser(f"{CLONE_DIR}/{repository}")
|
parent_dir = os.path.expanduser(f"{CLONE_DIR}/{owner}")
|
||||||
|
repository_clone_dir = os.path.expanduser(f"{parent_dir}/{repository}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["git", "clone", repo_url, repository_clone_dir],
|
["git", "clone", "--depth", "1", repository_url, repository_clone_dir],
|
||||||
check=True,
|
check=True,
|
||||||
stdout=sys.stdout,
|
stdout=sys.stdout,
|
||||||
stderr=sys.stderr,
|
stderr=sys.stderr,
|
||||||
)
|
)
|
||||||
|
result = subprocess.run(
|
||||||
|
["cloc", f"--exclude-lang={','.join(EXCLUDED_LANGUAGES)}", repository_clone_dir],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
number_of_lines_of_code = int(result.stdout.split("\n")[-3].split()[-1])
|
||||||
except Exception:
|
except Exception:
|
||||||
return -1
|
return -1
|
||||||
|
finally:
|
||||||
result = subprocess.run(["sloccount", repository_clone_dir], capture_output=True, text=True, check=True)
|
subprocess.run(["rm", "-rf", parent_dir], check=True)
|
||||||
for line in result.stdout.splitlines():
|
return number_of_lines_of_code
|
||||||
if "Total Physical Source Lines of Code (SLOC)" in line:
|
|
||||||
loc = int(line.split()[8].replace(",", ""))
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
loc = 0
|
|
||||||
subprocess.run(["rm", "-rf", repository_clone_dir], check=True)
|
|
||||||
return loc
|
|
||||||
|
|
||||||
|
|
||||||
def is_valid_repository(owner, repository, request_headers):
|
def is_valid_repository(owner, repository, request_headers):
|
||||||
@@ -80,7 +82,7 @@ def is_valid_repository(owner, repository, request_headers):
|
|||||||
def PICable(owner, repository, token):
|
def PICable(owner, repository, token):
|
||||||
margin_percentage = round(MARGIN * 100)
|
margin_percentage = round(MARGIN * 100)
|
||||||
request_headers = {"Authorization": f"token {token}"}
|
request_headers = {"Authorization": f"token {token}"}
|
||||||
picable_report = ""
|
picable_report = f"Analysis complete for the repository {owner}/{repository}.\n\n"
|
||||||
repository_url = f"https://www.github.com/{owner}/{repository}"
|
repository_url = f"https://www.github.com/{owner}/{repository}"
|
||||||
|
|
||||||
if not is_valid_repository(owner, repository, request_headers):
|
if not is_valid_repository(owner, repository, request_headers):
|
||||||
@@ -134,4 +136,5 @@ def PICable(owner, repository, token):
|
|||||||
else:
|
else:
|
||||||
picable_report += f"The repository {repository_url} is almost PICable. :warning:\nThere is at least one requirement which is below the requirement, but by less than {margin_percentage}%. Consult with a professor before proceeding.\n"
|
picable_report += f"The repository {repository_url} is almost PICable. :warning:\nThere is at least one requirement which is below the requirement, but by less than {margin_percentage}%. Consult with a professor before proceeding.\n"
|
||||||
|
|
||||||
|
print("Analysis complete.")
|
||||||
return picable_report
|
return picable_report
|
||||||
|
|||||||
47
main.py
47
main.py
@@ -16,15 +16,7 @@ intents = discord.Intents.default()
|
|||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
client = commands.Bot(command_prefix="/", intents=intents)
|
client = commands.Bot(command_prefix="/", intents=intents)
|
||||||
|
|
||||||
|
current_repositories = set()
|
||||||
async def reply_message_async(interaction: discord.Interaction, owner: str, repo: str):
|
|
||||||
try:
|
|
||||||
result = await asyncio.to_thread(PICable.PICable, owner, repo, github_token)
|
|
||||||
await interaction.followup.send(result)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error processing PICable check: {e}")
|
|
||||||
await interaction.followup.send("An error occurred while processing your request. Please try again later.")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
@client.event
|
@client.event
|
||||||
@@ -38,10 +30,43 @@ async def on_ready():
|
|||||||
print(f"Failed to sync commands: {e}")
|
print(f"Failed to sync commands: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
@client.tree.command(name="ping", description="Check the bot's latency.")
|
||||||
|
async def ping(interaction: discord.Interaction):
|
||||||
|
latency = client.latency * 1000
|
||||||
|
await interaction.response.send_message(f"Pong! Latency: {latency:.2f} ms")
|
||||||
|
|
||||||
|
|
||||||
@client.tree.command(name="picable", description="Check if a Github repository is eligible for PIC.")
|
@client.tree.command(name="picable", description="Check if a Github repository is eligible for PIC.")
|
||||||
@discord.app_commands.describe(owner="The owner of the repository", repository="The name of the repository")
|
@discord.app_commands.describe(owner="The owner of the repository", repository="The name of the repository")
|
||||||
async def picable(interaction: discord.Interaction, owner: str, repository: str):
|
async def picable(interaction: discord.Interaction, owner: str, repository: str):
|
||||||
await interaction.response.defer(ephemeral=False, thinking=True)
|
await interaction.response.defer(thinking=True)
|
||||||
asyncio.create_task(reply_message_async(interaction, owner, repository))
|
|
||||||
|
repository_full_name = f"{owner}/{repository}"
|
||||||
|
if repository_full_name in current_repositories:
|
||||||
|
await interaction.followup.send(
|
||||||
|
f"The repository {repository_full_name} is already being analyzed. Please wait for the current analysis to complete. :warning:"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
current_repositories.add(repository_full_name)
|
||||||
|
try:
|
||||||
|
result_future = asyncio.get_running_loop().run_in_executor(
|
||||||
|
None, PICable.PICable, owner, repository, github_token
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
result = await asyncio.wait_for(asyncio.shield(result_future), timeout=600)
|
||||||
|
await interaction.followup.send(result)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
await interaction.followup.send(
|
||||||
|
f"The analysis for {repository_full_name} is still taking place. The results will be posted here once the analysis is complete. :clock4:"
|
||||||
|
)
|
||||||
|
result = await result_future
|
||||||
|
await interaction.channel.send(result)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing PICable check: {e}")
|
||||||
|
await interaction.channel.send("An error occurred while processing your request. Please try again later.")
|
||||||
|
finally:
|
||||||
|
current_repositories.remove(repository_full_name)
|
||||||
|
|
||||||
|
|
||||||
client.run(discord_token)
|
client.run(discord_token)
|
||||||
|
|||||||
Reference in New Issue
Block a user