Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: button load to dropbox #17

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .git-blame-ignore-revs

This file was deleted.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,6 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
.terraform/
tfplan
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"git-blame.gitWebUrl": ""
}
Empty file removed cv_images/.gitkeep
Empty file.
Empty file removed cv_output/.gitkeep
Empty file.
Empty file removed cv_pages/.gitkeep
Empty file.
3 changes: 3 additions & 0 deletions cvbia/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"git-blame.gitWebUrl": ""
}
20 changes: 20 additions & 0 deletions cvbia/Dockerfile.slackbot
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM --platform=linux/amd64 python:3.10

WORKDIR /src

COPY requirements.txt /src

RUN pip install --upgrade -r requirements.txt

COPY src ./

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=30s \
CMD curl -f http://localhost:8000/health/ || exit 1

# todo: files need to be deleted (migrate to temp files)
# RUN groupadd -r api && useradd --no-log-init -r -g api api
# USER api

CMD ["python", "slack_bot.py"]
16 changes: 16 additions & 0 deletions cvbia/Dockerfile.streamlit
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM --platform=linux/amd64 python:3.10

WORKDIR /src

COPY requirements.txt /src
RUN pip install --upgrade -r requirements.txt

COPY src ./

RUN mkdir ~/.streamlit
RUN cp config.toml ~/.streamlit/config.toml

EXPOSE 80

ENTRYPOINT ["streamlit", "run"]
CMD ["streamlit_app.py"]
22 changes: 22 additions & 0 deletions cvbia/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
docker/cvbia/login:
az acr login -n cvbia

apps/cvbia_streamlit/build:
docker build -f Dockerfile.streamlit -t cvbia_streamlit:latest .

apps/cvbia_streamlit/push:
docker tag cvbia:latest cvbia.azurecr.io/cvbia_streamlit:latest
docker push cvbia.azurecr.io/cvbia_streamlit:latest

apps/cvbia_streamlit/run:
docker run -p 80:80 cvbia:latest

apps/cvbia_slackbot/build:
docker build -f Dockerfile.slackbot -t cvbia_slackbot:latest .

apps/cvbia_slackbot/push:
docker tag cvbia_slackbot:latest cvbia.azurecr.io/cvbia_slackbot:latest
docker push cvbia.azurecr.io/cvbia_slackbot:latest

apps/cvbia_slackbot/run:
docker run -p 80:80 cvbia_slackbot:latest
11 changes: 6 additions & 5 deletions requirements.txt → cvbia/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
black
dropbox>=11.36.0,<=12.0.0
pypdf
python-pptx
PyMuPDF>=1.22.0
pyyaml
reportlab<4.0.0
slack_bolt
streamlit
streamlit-cropper
pre-commit
pypdf
PyMuPDF>=1.22.0
python-pptx
tqdm
uvicorn
File renamed without changes
File renamed without changes
36 changes: 36 additions & 0 deletions cvbia/src/clients/dropbox_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os

import dropbox
import yaml

BASE_PATH = "/home/Team/testing cvbia"
DROPBOX_REFRESH_TOKEN = os.environ["DROPBOX_REFRESH_TOKEN"]
DROPBOX_APP_KEY = os.environ["DROPBOX_APP_KEY"]

def convert_email_to_file_name(email):
email = email.split("@")[0].replace(".", "_").lower()
return f"{BASE_PATH}/{email}"


class TransferData:
def upload_file_yaml(self, content, file_to):
"""upload a file to Dropbox using API v2"""
with dropbox.Dropbox(oauth2_refresh_token=DROPBOX_REFRESH_TOKEN, app_key=DROPBOX_APP_KEY) as dbx:
dbx.files_upload(
bytes(content, "utf-8"), file_to, mode=dropbox.files.WriteMode.overwrite
)

def upload_file(self, file_from, file_to):
"""upload a file to Dropbox using API v2"""
with dropbox.Dropbox(oauth2_refresh_token=DROPBOX_REFRESH_TOKEN, app_key=DROPBOX_APP_KEY) as dbx:
with open(file_from, "rb") as f:
dbx.files_upload(
f.read(), file_to, mode=dropbox.files.WriteMode.overwrite
)

def download_file(self, email):
with dropbox.Dropbox(oauth2_refresh_token=DROPBOX_REFRESH_TOKEN, app_key=DROPBOX_APP_KEY) as dbx:
file_path = convert_email_to_file_name(email=email)
_, f = dbx.files_download(f"{file_path}.yaml")
yaml_content = yaml.safe_load(f.content)
return yaml_content
137 changes: 137 additions & 0 deletions cvbia/src/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Below are all the sections and options you can have in ~/.streamlit/config.toml.

[global]

# By default, Streamlit checks if the Python watchdog module is available and, if not, prints a warning asking for you to install it. The watchdog module is not required, but highly recommended. It improves Streamlit's ability to detect changes to files in your filesystem.
# If you'd like to turn off this warning, set this to True.
# Default: false
disableWatchdogWarning = false

# Configure the ability to share apps to the cloud.
# Should be set to one of these values: - "off" : turn off sharing. - "s3" : share to S3, based on the settings under the [s3] section of this config file.
# Default: "off"
sharingMode = "off"

# If True, will show a warning when you run a Streamlit-enabled script via "python my_script.py".
# Default: true
showWarningOnDirectExecution = true

# Level of logging: 'error', 'warning', 'info', or 'debug'.
# Default: 'info'
# logLevel = "debug"


[client]

# Whether to enable st.cache.
# Default: true
caching = true

# If false, makes your Streamlit script not draw to a Streamlit app.
# Default: true
displayEnabled = true


[runner]

# Allows you to type a variable or string by itself in a single line of Python code to write it to the app.
# Default: true
magicEnabled = true

# Install a Python tracer to allow you to stop or pause your script at any point and introspect it. As a side-effect, this slows down your script's execution.
# Default: false
installTracer = false

# Sets the MPLBACKEND environment variable to Agg inside Streamlit to prevent Python crashing.
# Default: true
fixMatplotlib = true


[server]

# List of folders that should not be watched for changes. Relative paths will be taken as relative to the current working directory.
# Example: ['/home/user1/env', 'relative/path/to/folder']
# Default: []
folderWatchBlacklist = ['']



# If false, will attempt to open a browser window on start.
# Default: false unless (1) we are on a Linux box where DISPLAY is unset, or (2) server.liveSave is set.
headless = true

# Immediately share the app in such a way that enables live monitoring, and post-run analysis.
# Default: false
liveSave = false

# Automatically rerun script when the file is modified on disk.
# Default: false
runOnSave = false

# The port where the server will listen for client and browser connections.
# Default: 8501
port = 80

# Enables support for Cross-Origin Request Sharing, for added security.
# Default: true
enableCORS = false


[browser]

# Internet address of the server server that the browser should connect to. Can be IP address or DNS name.
# Default: 'localhost'
serverAddress = "0.0.0.0"

# Whether to send usage statistics to Streamlit.
# Default: true
gatherUsageStats = true

# Port that the browser should use to connect to the server when in liveSave mode.
# Default: whatever value is set in server.port.
serverPort = 80

[s3]

# Name of the AWS S3 bucket to save apps.
# Default: (unset)
# bucket =

# URL root for external view of Streamlit apps.
# Default: (unset)
# url =

# Access key to write to the S3 bucket.
# Leave unset if you want to use an AWS profile.
# Default: (unset)
# accessKeyId =

# Secret access key to write to the S3 bucket.
# Leave unset if you want to use an AWS profile.
# Default: (unset)
#secretAccessKey =

# Make the shared app visible only to users who have been granted view permission. If you are interested in this option, contact us at [email protected].
# Default: false
# requireLoginToView = false

# The "subdirectory" within the S3 bucket where to save apps.
# S3 calls paths "keys" which is why the keyPrefix is like a subdirectory. Use "" to mean the root directory.
# Default: ""
keyPrefix = ""

# AWS region where the bucket is located, e.g. "us-west-2".
# Default: (unset)
# region =

# AWS credentials profile to use.
# Leave unset to use your default profile.
# Default: (unset)
# profile =


[logger]

# Level of logging: 'error', 'warning', 'info', or 'debug'.
# Default: 'info'
level = "debug"
File renamed without changes.
Binary file added cvbia/src/cv_output/cv.pdf
Binary file not shown.
Binary file added cvbia/src/cv_output/cv.pptx
Binary file not shown.
Binary file added cvbia/src/cv_pages/cv1.pdf
Binary file not shown.
Binary file added cvbia/src/cv_pages/cv2.pdf
Binary file not shown.
Binary file added cvbia/src/cv_pages/cv3.pdf
Binary file not shown.
File renamed without changes.
126 changes: 126 additions & 0 deletions cvbia/src/helpers/draw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import io
import itertools
import textwrap

from PIL import Image, ImageDraw
from reportlab.lib.pagesizes import A4
from reportlab.lib.utils import ImageReader
from reportlab.pdfbase.pdfmetrics import stringWidth


def write(
c: object,
x: int,
y: int,
text: str,
width: int = 60,
font: str = "regular",
punto: int = 12,
color: str = "dark_grey",
spacing: int = 12,
url: str = None,
):
"""
Writes given text input with specified arguments.

Arguments:
c: canvas object
x: x coordinate on the page
y: y coordinate on the page
text: text input to be written, must be a string
font: regular, bold
punto: font size
color: white, trans_white, purple, dark_grey, light_grey
spacing: line spacing, only used for mutliple line inputs
url: URL to be written, starts with the URL domain, i.e. no "https://www."
"""
# SET FONT
c.setFont(font, punto)

# SET COLOR
if color == "white":
c.setFillColorRGB(0.95, 0.95, 0.95, 1)
elif color == "trans_white":
c.setFillColorRGB(0.95, 0.95, 0.95, 0.8)
elif color == "purple":
c.setFillColorRGB(108 / 255, 29 / 255, 96 / 255, 1)
elif color == "dark_grey":
c.setFillColorRGB(0.5, 0.5, 0.5, 1)
elif color == "light_grey":
c.setFillColorRGB(0.3, 0.3, 0.3, 1)
else:
raise Exception(
f"{color} is not available. Try: white, trans_white, purple, dark_grey, light_grey"
)

# DRAW STRING: for loop is used to manage multiple line inputs
if text:
for line in list(
itertools.chain.from_iterable(
[textwrap.wrap(x, width=width) for x in text.splitlines()]
)
):
c.drawString(x, y, f"{line}")
if url is not None:
c.linkURL(
"https://www." + url,
rect=(
x,
y,
x + (0.66 * stringWidth(text, font, punto + 4)),
y + punto,
),
relative=0,
thickness=0,
)
y -= spacing

return y


def draw_background(c, image=None, path="backgrounds/background1.jpg"):
"""
Fills the background of document.
"""
if image:
bg_image = image
c.drawImage(bg_image, 0, 0, width=A4[1], height=A4[0])
elif path:
bg_image = path
c.drawImage(bg_image, 0, 0, width=A4[1], height=A4[0])

return None


def draw_picture(c, image=None, path: str = "images/tom_cruise.jpg"):
"""
Crops and draws the circular photo of the person on CV.
"""
if image:
im = Image.open(io.BytesIO(image))
bigsize = (im.size[0] * 3, im.size[1] * 3)
mask = Image.new("L", bigsize, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + bigsize, fill=255)
mask = mask.resize(im.size, Image.LANCZOS)
im.putalpha(mask)
img_byte_arr = io.BytesIO()
im.save(img_byte_arr, format="PNG")
img_byte_arr = img_byte_arr.getvalue()
pp_image = ImageReader(io.BytesIO(img_byte_arr))
c.drawImage(pp_image, 20, 455, width=100, height=100, mask="auto")
elif path:
im = Image.open(path)
bigsize = (im.size[0] * 3, im.size[1] * 3)
mask = Image.new("L", bigsize, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + bigsize, fill=255)
mask = mask.resize(im.size, Image.LANCZOS)
im.putalpha(mask)
img_byte_arr = io.BytesIO()
im.save(img_byte_arr, format="PNG")
img_byte_arr = img_byte_arr.getvalue()
pp_image = ImageReader(io.BytesIO(img_byte_arr))
c.drawImage(pp_image, 20, 455, width=100, height=100, mask="auto")

return None
Loading