Skip to content

Commit

Permalink
Merge branch 'hackclub:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Meghna6969 authored Nov 24, 2024
2 parents bf9835b + 8ff80c8 commit fb99481
Show file tree
Hide file tree
Showing 180 changed files with 14,964 additions and 1,188 deletions.
21 changes: 15 additions & 6 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
Write a short description about your art piece, such as what your artwork represents and your experience drawing it!

Next, make sure you go through **each item** in the following checklist. Delete this line after!

- [ ] I have read the steps to [getting a blot](https://github.com/hackclub/blot/blob/main/docs/GET_A_BLOT.md)
- [ ] I have read all the [submission requirements](https://blot.hackclub.com/submitting) and follow them
- [ ] I am submitting art that...
- [ ] is algorithmically generated (will change each time the program is run)
- [ ] is drawable on a blot (fits in the work area & doesn't overlap too much)
- [ ] is original (not copied from somewhere else)
- [ ] is algorithmically generated (will meaningfully change each time the program is run)
- [ ] is your own work that is not copied from somewhere else
- [ ] is drawable through the editor(does not use outside tools)
- [ ] doesn't call `Math.random()` (See the documentation on [randomness](https://github.com/hackclub/blot/blob/main/public/TOOLKIT.md#randomness))
- [ ] is drawable on a physical machine (doesn't have lines overlap more than 5 times)
- [ ] is drawable on Blot itself (doesn't have lines overlap more than 5 times)
- [ ] Doesn't overlap lines more than 5 times
- [ ] Fits in the working area of 125x125mm
- [ ] Doesn't rely on colour to look good

If you used based your art on something else, used a tutorial, or remixed it from something else, please link it here:

- [ ] Optional, if you used a tutorial or based your art on something else, please include the link here:
- [ ] Optional, if you remixed this from something else, mention it here:
Lastly, link a picture of your art piece here:
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
pull-requests: write
repository-projects: write
issues: write

`
steps:
- name: Checkout repository
uses: actions/checkout@v2
Expand All @@ -41,7 +41,7 @@ jobs:
done
echo "RESULTS_FILE=.github/workflows/logs/artwork_check_results.txt" >> $GITHUB_ENV
cat .github/workflows/logs/artwork_check_results.txt
- name: Comment on pull request
uses: actions/github-script@v6
with:
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
submission:
- changed-files:
- any-glob-to-any-file: art/**
63 changes: 63 additions & 0 deletions .github/scripts/extract_percentages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from bs4 import BeautifulSoup
import os
import sys

def extract_similarity_percentage(html_file, type):
try:
with open(html_file, 'r', encoding='utf-8') as file:
soup = BeautifulSoup(file, 'html.parser')
file_name_tag = soup.select_one(f"#{type}left > div > h4")
if file_name_tag:
percentage_text = file_name_tag.find("span", class_="text-secondary small").text.strip("()%")
return int(percentage_text)
else:
return None
except Exception as e:
print(f"Error processing file {html_file}: {e}")
return None

def process_html_files(directory, threshold=50, noise_threshold=20):
print("Processing HTML files for plagiarism results...")
high_plagiarism_detected = False
high_plagiarism_files = []
for filename in os.listdir(directory):
if filename.endswith(".html"):
file_path = os.path.join(directory, filename)
percentage = extract_similarity_percentage(file_path,"structure")
percentage_text = extract_similarity_percentage(file_path,"text")
if percentage is not None and percentage >= threshold:
print(f"High plagiarism detected - {filename.replace('.html', '')}: {percentage}%, {percentage_text}%")
high_plagiarism_files.append(f"{filename.replace('.html', '')}: \n- Structure: {percentage}% \n- Text: {percentage_text}%")
high_plagiarism_detected = True
elif percentage is not None and percentage < noise_threshold: # Avoid huge action artifacts
print(f"Removing plagiarism report with {filename.replace('.html', '')}: {percentage}%,{percentage_text}% score as noise")
os.remove(file_path)
return high_plagiarism_detected, high_plagiarism_files

def write_to_markdown(file_path, lines):
with open(file_path, 'w') as md_file:
for line in lines:
md_file.write(line + '\n')
print(f"Markdown file written to {file_path}")

def main():
if len(sys.argv) != 2:
print("Incorrect number of arguments provided.")
print("Usage: python extract_percentages.py <saved_dir_path>")
sys.exit(1)

saved_dir_path = sys.argv[1]
high_plagiarism_detected, high_plagiarism_files = process_html_files(saved_dir_path)

markdown_lines = ["# Plagiarism Report"]
if high_plagiarism_detected:
print("High plagiarism percentages detected.")
markdown_lines.append("## Art overlap report:")
markdown_lines.extend(high_plagiarism_files)
write_to_markdown("plagiarism-report.md", markdown_lines)
sys.exit(1)
else:
print("No high plagiarism percentages detected.")
print("Plagiarism report generation completed.")
if __name__ == "__main__":
main()
82 changes: 82 additions & 0 deletions .github/scripts/plagiarism_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import sys
import subprocess
import os
import glob
import shutil

def run_compare50(single_file, directory, output_dir, saved_dir_base):
try:
if not os.path.exists(saved_dir_base):
os.makedirs(saved_dir_base)
print("Created base directory for saved files.")

all_js_files = glob.glob(os.path.join(directory, "**/index.js"))
total_files = len(all_js_files)
current_file_number = 0

for file in all_js_files:
current_file_number += 1
if os.path.abspath(file) == os.path.abspath(single_file):
print(f"Skipping comparison for the same file: {file}")
continue

print(f"Processing file {current_file_number} of {total_files}: {file}")
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
print(f"Cleaned existing output directory: {output_dir}")

command = [
"compare50",
f'"{single_file}"',
f'"{file}"',
"--output", f'"{output_dir}"',
"--max-file-size", str(1024 * 1024 * 100),
"--passes", "structure text"
]

command_str = ' '.join(command)
print(f"Running command: {command_str}")
subprocess.run(command_str, shell=True, check=True)
print("Compare50 command executed successfully.")

match_file = os.path.join(output_dir, "match_1.html")

if os.path.exists(match_file):
new_filename = os.path.basename(os.path.normpath(os.path.dirname(file))) + '.html'
saved_file_path = os.path.join(saved_dir_base, new_filename)
print(f"Match found. Moving {match_file} to {saved_file_path}")
shutil.move(match_file, saved_file_path)
else:
print(f"No match found for file: {file}")

except subprocess.CalledProcessError as e:
print(f"Error in running Compare50: {e}")
except Exception as e:
print(f"An error occurred: {e}")

def main():
if len(sys.argv) != 5:
print("Incorrect number of arguments provided.")
print("Usage: python plagiarism_check.py <single_file> <directory> <output_dir> <saved_dir_base>")
sys.exit(1)

single_file = sys.argv[1]
directory = sys.argv[2]
output_dir = sys.argv[3]
saved_dir_base = sys.argv[4]

print(f"Starting plagiarism check with the following arguments:")
print(f"Single file: {single_file}")
print(f"Directory: {directory}")
print(f"Output directory: {output_dir}")
print(f"Saved directory base: {saved_dir_base}")

# print(f"Listing all JavaScript files in directory '{directory}':")
# for f in glob.glob(os.path.join(directory, "**/index.js")):
# print(f)

run_compare50(single_file, directory, output_dir, saved_dir_base)
print("Plagiarism check completed.")

if __name__ == "__main__":
main()
88 changes: 88 additions & 0 deletions .github/workflows/check_plagiarism.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Plagiarism Checker

permissions:
contents: read
issues: write
pull-requests: write

on:
pull_request:
paths:
- "art/**/*.js"

jobs:
plagiarism-check:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install Compare50 && beautifulsoup4
run: pip install compare50 beautifulsoup4

- name: Get list of changed files
id: changed-files
run: |
echo "Pull Request Base SHA: ${{ github.event.pull_request.base.sha }}"
echo "Pull Request Head SHA: ${{ github.event.pull_request.head.sha }}"
git diff --name-only --diff-filter=AM --find-renames --find-copies ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} | grep 'art/.*\.js$' | xargs
js_files=$(git diff --name-only --diff-filter=AM --find-renames --find-copies ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} | grep 'art/.*\.js$' | xargs)
echo "FILES=$js_files" >> $GITHUB_ENV
- name: Run Plagiarism Detection Script
if: env.FILES != ''
run: python .github/scripts/plagiarism_check.py "${{ env.FILES }}" art output_dir saved_dir

- name: Extract and Display Similarity Percentages
run: python .github/scripts/extract_percentages.py saved_dir/
id: extract-percentages

- name: Upload Compare50 Results as Artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: compare50-results
path: saved_dir/

- name: Save PR number to file
if: always()
run: echo ${{ github.event.pull_request.number }} > pr_number.txt

- name: Upload Plagiarism Report as Artifact
if: always() && steps.extract-percentages.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: plagiarism-report
path: plagiarism-report.md

- name: Check for High Plagiarism Percentages
if: always() && steps.extract-percentages.outcome == 'failure'
run: echo "Plagiarism percentage over threshold detected."

- name: Post Markdown as Comment
if: always() && steps.extract-percentages.outcome == 'failure'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
console.log("Reading pr number...")
const prNumber = fs.readFileSync('./pr_number.txt', 'utf8').trim();
console.log("Reading report...")
const markdownContent = fs.readFileSync('./plagiarism-report.md', 'utf8');
console.log("Posting the Markdown content as a comment...");
const commentResponse = await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: markdownContent
});
console.log(`Comment posted successfully: ${commentResponse.data.html_url}`);
13 changes: 13 additions & 0 deletions .github/workflows/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: "Label Art submissions"

on:
- pull_request_target

jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
86 changes: 86 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import express from 'express';

import signUpEmail from "../backend/api/signUpEmail.js";
import checkSignIn from "../backend/api/checkSignIn.js";
import saveFile from "../backend/api/saveFile.js";
import getUser from "../backend/api/getUser.js";
import submitCode from "../backend/api/submitCode.js";
import getFiles from "../backend/api/getFiles.js";
import createShareLink from "../backend/api/createShareLink.js";
import logout from "../backend/api/logout.js";
import deleteFile from "../backend/api/deleteFile.js";

import { supabase } from "../backend/api/supabase.js";

import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import path from 'path';

const app = express();

app.use(express.json());

app.post('/signUpEmail', signUpEmail);
app.post('/check-signed-in', checkSignIn);
app.post('/get-files', getFiles);
app.post('/save-file', saveFile);
app.post('/delete-file', deleteFile);
app.post('/logout', logout);
app.post('/get-user', getUser);
app.post('/submit-code', submitCode);
app.post('/create-share-link', createShareLink);
app.get('/read-share-link', async (req, res) => {
const { id } = req.query;

try {

console.log("check in database");
// check if email is in database
let { data: file, error: fileError } = await supabase
.from('share_link')
.select('*')
.eq('id', id)
.single();

if (fileError && fileError.message !== 'No rows found') {
res.send("no share link here");
return;
}

res.send(file.content);
} catch (error) {
res.status(500).send({ error: error.message });
}
});
app.get('/assembly', (req, res) => {
res.redirect('https://github.com/hackclub/blot/blob/main/docs/assembly/ASSEMBLY.md');
});
app.get('/welcome-qr-code', (req, res) => {
res.redirect('/assembly');
});

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

app.use(express.static(join(__dirname, '../dist')));

app.use((req, res, next) => {
let pathName = req.path;

if (pathName === "/") pathName = "/index";

if (req.path.indexOf('.') === -1) {
const file = path.join(__dirname, '../dist', `${pathName}.html`);
res.sendFile(file, (err) => {
if (err) next();
});
} else {
next();
}
});

app.use((req, res, next) => {
const file = path.join(__dirname, '../dist', `404.html`);
res.status(404).sendFile(file);
});
export default app;
Loading

0 comments on commit fb99481

Please sign in to comment.