maybe a fork of sparrowhe's "bluesky circle" webapp, to frontend only?

fix & chore: Docker, deps, filter, fs

+9
.dockerignore
···
+
lib/
+
lib64
+
include/
+
bin/
+
share/
+
pyvenv.cfg
+
static/
+
test.py
+
*.png
-1
.gitignore
···
static/
test.py
*.png
-
config.py
+10
Dockerfile
···
+
FROM python:3.12.7
+
+
WORKDIR /usr/src/app
+
COPY requirements.txt ./
+
RUN pip install --no-cache-dir -r requirements.txt
+
COPY . .
+
+
#CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0" , "app:app" ]
+
CMD ["flask", "run", "--port=8000", "--host=0.0.0.0"]
+
EXPOSE 8000
-1
avatar/parse_friends.py
···
from PIL import Image, ImageOps, ImageDraw
-
import numpy as np
import math
import requests
from io import BytesIO
+3
avatar/routes.py
···
client = at_client_extension.get_client()
handle = request.form.get('handle')
+
# filter invisible characters
+
handle = ''.join(filter(lambda x: x.isprintable(), handle))
+
handle.replace('@', '')
friends_data = parse_friends(client, handle)
center = client.get_profile(handle)
center_avatar_url = center.avatar
+9 -8
avatar/utils.py
···
import requests
from PIL import Image, ImageOps, ImageDraw
from io import BytesIO
-
import numpy as np
import math
import os
+
PI=3.14
def check_cache_img(url):
+
# Check if the cache path not exists
+
if not os.path.join('static', 'avatars'):
+
os.makedirs(os.path.join('static', 'avatars'))
+
# Check if the image is already cached
cache_path = os.path.join('static', 'avatars', os.path.basename(url.split('/')[-1]+'.jpg'))
if os.path.exists(cache_path):
return cache_path
return None
-
def load_image_as_circle(image_url, radius, proxies={
-
'https': 'http://127.0.0.1:7897',
-
'http': 'http://127.0.0.1:7897'
-
}):
+
def load_image_as_circle(image_url, radius, proxies=None):
try:
# Add proxy support in the request
if check_cache_img(image_url):
···
avatar_size = avatar_radius * 2 # Diameter for resizing
# Calculate how many avatars fit in the current circle
-
num_in_current_circle = int(2 * np.pi * radius / (avatar_size)) # Adjusted based on avatar size
-
theta_step = 2 * np.pi / num_in_current_circle # Angle between avatars
-
rotation_offset = layer * (np.pi / 12) # Rotate 15 degrees for each layer
+
num_in_current_circle = int(2 * PI * radius / (avatar_size)) # Adjusted based on avatar size
+
theta_step = 2 * PI / num_in_current_circle # Angle between avatars
+
rotation_offset = layer * (PI / 12) # Rotate 15 degrees for each layer
for i in range(num_in_current_circle):
if friend_idx >= len(sorted_friends):
+11
config.py
···
+
import os
+
+
class Config:
+
"""Configuration class for the Flask app."""
+
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
+
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'static/avatars')
+
+
# BlueSky login credentials
+
BLUESKY_HANDLE = os.getenv('BLUESKY_HANDLE', '')
+
BLUESKY_PASSWORD = os.getenv('BLUESKY_PASSWORD', '')
+
BLUESKY_BASE = os.getenv('BLUESKY_BASE', '')
-11
config.py.example
···
-
import os
-
-
class Config:
-
"""Configuration class for the Flask app."""
-
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
-
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'static/avatars')
-
-
# BlueSky login credentials
-
BLUESKY_HANDLE = ''
-
BLUESKY_PASSWORD = ''
-
BLUESKY_BASE = ''
+2 -1
requirements.txt
···
Flask==2.3.2
Pillow==10.0.0
requests==2.31.0
-
numpy==1.23.5
+
atproto==0.0.54
+
gunicorn==23.0.0