Code4GovTech / server

0 stars 4 forks source link

Github App Tech Refactor #74

Closed sasi2312 closed 1 month ago

sasi2312 commented 2 months ago

Complete PR of App tech ticket

  1. Once deployed in prod..pls add webhook secret in webhooks
  2. Add that secret key in .env file named "WEBHOOK_SECRET"
KDwevedi commented 2 months ago

@sasi2312 Can you add a list of changes you're pushing in this PR?

Like so ^

sasi2312 commented 2 months ago

These are the changes made on this PR, @KDwevedi

sasi2312 commented 1 month ago

@KDwevedi for above point,I mentioned my thought below

sasi2312 commented 1 month ago
KDwevedi commented 1 month ago

Actually the db adapter part is designed as per singleton pattern ... It returns single(same) instance for every call.Its not slow down any database related part

You're correct.

the singleton pattern is only 1.25 times slower here:

import time

# Using a singleton class
class MySingletonClass:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(MySingletonClass, cls).__new__(cls, *args, **kwargs)
        return cls._instance

    def my_method(self):
        pass

# Timing the singleton class method calls
singleton_instance = MySingletonClass()
start = time.time()
for _ in range(1000000):
    singleton_instance.my_method()
end = time.time()
print(f"Singleton class method call time: {end - start} seconds")

# Using a module
def my_function():
    pass

# Timing the module function calls
start = time.time()
for _ in range(1000000):
    my_function()
end = time.time()
print(f"Module function call time: {end - start} seconds")
Singleton class method call time: 0.05184793472290039 seconds
Module function call time: 0.039575815200805664 seconds

While the class initialisation is 2-3x slower:

import time

# Using a class
class MyClass:
    def my_method(self):
        pass

start = time.time()
for _ in range(1000000):
    instance = MyClass()
    instance.my_method()
end = time.time()
print(f"Class method call time: {end - start} seconds")

# Using a module
def my_function():
    pass

start = time.time()
for _ in range(1000000):
    my_function()
end = time.time()
print(f"Module function call time: {end - start} seconds")
Class method call time: 0.11432194709777832 seconds
Module function call time: 0.04015994071960449 seconds

I still feel like the singleton pattern is an unnecessary overhead, but @VedantKhairnar can decide if we want to migrate to a module.

Let's leave this be.

KDwevedi commented 1 month ago

Can u please give me the context of above statement

The latest community badges are Bronze, Silver, Gold, Ruby, and Diamond according to the leaderboard

The templates for the Bronze, Silver, and Gold badges are stored in the github_profile_assets bucket in supabase storage.

The badges for Ruby, and Diamond can be made by copying the Gold or Silver or Bronze slide here (I've given edit access to sasikumar.s@cogniverselabs.com) and using the Ruby and Diamond png files.

In the new logic for generating github profile images you should

Python script to generate the badges for reference:

def generateQR(border_size=1, ghUsername=''):
    qr = segno.make_qr(f"https://github-app.c4gt.samagra.io/verify/{ghUsername}")
    buffer = BytesIO()
    # Save the QR code to a buffer, adjusting the border size here
    qr.save(buffer, kind='png', scale=1, border=border_size)
    qrBytes = buffer.getvalue()
    return qrBytes

profileData = client.table("github_profile_data").select("*").execute()
count = 0

for data in profileData.data:
    if data["dpg_points"]+data["classroom_points"]<10:
        continue

    #SET DATA
    milestone = data["milestone"]
    prsRaised = data["prs_raised"]
    prsReviewed = data["prs_reviewed"]
    prsMerged = data["prs_merged"]
    dpgPoints = data["dpg_points"]+data["classroom_points"]
    githubUsername = data["github_username"]

    githubLogoBytes = client.storage.from_('github_profile_assets').download("GHLogoSS.png")
    githubLogo_np = np.frombuffer(githubLogoBytes, np.uint8)
    githubLogo = cv2.imdecode(githubLogo_np, cv2.IMREAD_COLOR)

    qrBytes = generateQR(1, githubUsername)
    qr_np = np.frombuffer(qrBytes, np.uint8)
    qr =  cv2.imdecode(qr_np, cv2.IMREAD_COLOR)

    textDimensions = cv2.getTextSize(githubUsername, cv2.FONT_HERSHEY_DUPLEX, 1.5, 2)
    usernameWidth = textDimensions[0][0]
    xCenter = 550

    #GET TEMPLATES
    if milestone == 1:
        badgeName = 'Bronze'
    elif milestone == 2:
        badgeName = 'Silver'
    elif milestone == 3:
        badgeName = 'Gold'
    else:
        # Extend this logic for ruby and diamond
        print("WEIRD MILESTONE",milestone)

    displayTemplateName = f'Github Profile Template {badgeName} Display.png'
    verifiedTemplateName = f'Github Profile Template {badgeName} Verified.png'

    displayTemplateBytes = client.storage.from_('github_profile_assets').download(displayTemplateName)
    displayTemplate_np = np.frombuffer(displayTemplateBytes, np.uint8)
    displayTemplate = cv2.imdecode(displayTemplate_np, cv2.IMREAD_COLOR)

    width, height = displayTemplate.shape[:2]

    MILESTONES_COUNT_COORDINATES = (800, height - 673)
    PRS_RAISED_COORDINATES = (800, height - 608)
    PRS_REVIEWED_COORDINATES = (800, height - 546)
    PRS_MERGED_COORDINATES = (800, height - 483)
    DPG_POINTS_COORDINATES = (800, height - 418)
    QR_COORDINATES = (855, height - 620)
    GITHUB_USERNAME = (xCenter - usernameWidth//2, height - 792)
    GITHUB_LOGO_COORDINATES = (GITHUB_USERNAME[0] - 90, height - 850)

    ghScaleFactor = 0.08
    newGHSize = (int(displayTemplate.shape[1] * ghScaleFactor), int(displayTemplate.shape[1] * ghScaleFactor))
    ghResized = cv2.resize(githubLogo, newGHSize, interpolation=cv2.INTER_AREA)
    displayTemplate[GITHUB_LOGO_COORDINATES[1]:GITHUB_LOGO_COORDINATES[1]+ghResized.shape[0], GITHUB_LOGO_COORDINATES[0]:GITHUB_LOGO_COORDINATES[0]+ghResized.shape[1]] = ghResized

    scaleFactor = 0.107
    newSize = (int(displayTemplate.shape[1] * scaleFactor), int(displayTemplate.shape[1] * scaleFactor))
    qrResized = cv2.resize(qr, newSize, interpolation=cv2.INTER_AREA)
    displayTemplate[QR_COORDINATES[1]:QR_COORDINATES[1]+qrResized.shape[0], QR_COORDINATES[0]:QR_COORDINATES[0]+qrResized.shape[1]] = qrResized

    font = cv2.FONT_HERSHEY_SIMPLEX
    font_size = 1.0
    color = (255, 255, 255)
    thickness = 2

    cv2.putText(displayTemplate, str(milestone), MILESTONES_COUNT_COORDINATES, font, font_size, color, thickness)
    cv2.putText(displayTemplate, str(prsRaised), PRS_RAISED_COORDINATES, font, font_size, color, thickness)
    cv2.putText(displayTemplate, str(prsReviewed), PRS_REVIEWED_COORDINATES, font, font_size, color, thickness)
    cv2.putText(displayTemplate, str(prsMerged), PRS_MERGED_COORDINATES, font, font_size, color, thickness)
    cv2.putText(displayTemplate, str(dpgPoints), DPG_POINTS_COORDINATES, font, font_size, color, thickness)
    cv2.putText(displayTemplate, f"@{githubUsername}", GITHUB_USERNAME, cv2.FONT_HERSHEY_DUPLEX, 1.5, (216,216,216), thickness)

    verifiedTemplateBytes = client.storage.from_('github_profile_assets').download(verifiedTemplateName)
    verifiedTemplate_np = np.frombuffer(verifiedTemplateBytes, np.uint8)
    verifiedTemplate = cv2.imdecode(verifiedTemplate_np, cv2.IMREAD_COLOR)

    width, height = verifiedTemplate.shape[:2]

    MILESTONES_COUNT_COORDINATES = (800, height - 673)
    PRS_RAISED_COORDINATES = (800, height - 608)
    PRS_REVIEWED_COORDINATES = (800, height - 546)
    PRS_MERGED_COORDINATES = (800, height - 483)
    DPG_POINTS_COORDINATES = (800, height - 418)
    QR_COORDINATES = (855, height - 620)
    GITHUB_USERNAME = (xCenter - usernameWidth//2, height - 792)
    GITHUB_LOGO_COORDINATES = (GITHUB_USERNAME[0] - 90, height - 850)

    ghScaleFactor = 0.08
    newGHSize = (int(verifiedTemplate.shape[1] * ghScaleFactor), int(verifiedTemplate.shape[1] * ghScaleFactor))
    ghResized = cv2.resize(githubLogo, newGHSize, interpolation=cv2.INTER_AREA)
    verifiedTemplate[GITHUB_LOGO_COORDINATES[1]:GITHUB_LOGO_COORDINATES[1]+ghResized.shape[0], GITHUB_LOGO_COORDINATES[0]:GITHUB_LOGO_COORDINATES[0]+ghResized.shape[1]] = ghResized

    scaleFactor = 0.107
    newSize = (int(verifiedTemplate.shape[1] * scaleFactor), int(verifiedTemplate.shape[1] * scaleFactor))
    qrResized = cv2.resize(qr, newSize, interpolation=cv2.INTER_AREA)
    verifiedTemplate[QR_COORDINATES[1]:QR_COORDINATES[1]+qrResized.shape[0], QR_COORDINATES[0]:QR_COORDINATES[0]+qrResized.shape[1]] = qrResized

    font = cv2.FONT_HERSHEY_SIMPLEX
    font_size = 1.0
    color = (255, 255, 255)
    thickness = 2

    cv2.putText(verifiedTemplate, str(milestone), MILESTONES_COUNT_COORDINATES, font, font_size, color, thickness)
    cv2.putText(verifiedTemplate, str(prsRaised), PRS_RAISED_COORDINATES, font, font_size, color, thickness)
    cv2.putText(verifiedTemplate, str(prsReviewed), PRS_REVIEWED_COORDINATES, font, font_size, color, thickness)
    cv2.putText(verifiedTemplate, str(prsMerged), PRS_MERGED_COORDINATES, font, font_size, color, thickness)
    cv2.putText(verifiedTemplate, str(dpgPoints), DPG_POINTS_COORDINATES, font, font_size, color, thickness)
    cv2.putText(verifiedTemplate, f"@{githubUsername}", GITHUB_USERNAME, cv2.FONT_HERSHEY_DUPLEX, 1.5, (216,216,216), thickness)

    display = cv2.imencode(".jpg", displayTemplate)[1].tobytes()
    verified = cv2.imencode(".jpg", verifiedTemplate)[1].tobytes()
    displayFilename = f'{data["discord_id"]}-c4gt-contributions.jpeg'
    verifiedFileName = f'{githubUsername}-c4gt-contributions.jpeg'
    try:
        client.storage.from_("c4gt-github-profile").remove(displayFilename)
        client.storage.from_("c4gt-github-profile").remove(verifiedFileName)
    except Exception:
        pass

    # self.supabase.client.storage.from_(self.storageBucket).remove(displayFilename)
    client.storage.from_("c4gt-github-profile").upload(displayFilename, display, {"content-type": "image/jpeg"})
    client.storage.from_("c4gt-github-profile").upload(verifiedFileName, verified, {"content-type": "image/jpeg"})
KDwevedi commented 1 month ago

Also @sasi2312, I don't see any commits post review, I hope the rest of the feedback on extraneous pass statements and more robust error handling can be incorporated.