mirror of
https://github.com/boostorg/website-v2.git
synced 2026-01-19 04:42:17 +00:00
@@ -15,6 +15,7 @@
|
||||
- [`sync_mailinglist_stats`](#sync_mailinglist_stats)
|
||||
- [`update_library_version_dependencies`](#update_library_version_dependencies)
|
||||
- [`release_tasks`](#release_tasks)
|
||||
- [`refresh_users_github_photos`](#refresh_users_github_photos)
|
||||
|
||||
## `boost_setup`
|
||||
|
||||
@@ -323,3 +324,35 @@ For this to work `SLACK_BOT_API` must be set in the `.env` file.
|
||||
```bash
|
||||
./manage.py link_contributors_to_users
|
||||
```
|
||||
|
||||
## `refresh_users_github_photos`
|
||||
|
||||
**Purpose**: Refresh GitHub profile photos for all users who have a GitHub username. This command fetches the latest profile photo from GitHub for each user and updates their local profile image. This is useful for local dev/testing, isn't used for production where a periodic celery task is used.
|
||||
|
||||
**Example**
|
||||
|
||||
```bash
|
||||
./manage.py refresh_users_github_photos
|
||||
```
|
||||
|
||||
**Options**
|
||||
|
||||
| Options | Format | Description |
|
||||
|--------------|--------|----------------------------------------------------------------------------------------------|
|
||||
| `--dry-run` | bool | Show which users would be updated without actually updating them. Useful for testing. |
|
||||
|
||||
**Usage Examples**
|
||||
|
||||
Refresh photos for all users with GitHub usernames:
|
||||
```bash
|
||||
./manage.py refresh_users_github_photos
|
||||
```
|
||||
|
||||
Preview which users would be updated:
|
||||
```bash
|
||||
./manage.py refresh_users_github_photos --dry-run
|
||||
```
|
||||
**Process**
|
||||
|
||||
- Calls the `refresh_users_github_photos()` Celery task which queues photo updates for all users with GitHub usernames
|
||||
- With `--dry-run`, displays information about which users would be updated without making any changes
|
||||
|
||||
@@ -140,10 +140,11 @@ class UserProfilePhotoForm(forms.ModelForm):
|
||||
old_image = self.instance.image
|
||||
# Save the new image
|
||||
user = super().save(commit=False)
|
||||
|
||||
if old_image:
|
||||
if not old_image:
|
||||
# reset image on image delete checked
|
||||
user.image_uploaded = False
|
||||
elif self.cleaned_data["image"] != old_image:
|
||||
# Delete the old image file if there's a new image being uploaded
|
||||
if self.cleaned_data["image"] != old_image:
|
||||
old_image.delete(save=False)
|
||||
|
||||
if self.cleaned_data.get("image"):
|
||||
@@ -155,6 +156,7 @@ class UserProfilePhotoForm(forms.ModelForm):
|
||||
|
||||
new_image.name = f"{user.profile_image_filename_root}.{file_extension}"
|
||||
user.image = new_image
|
||||
user.image_uploaded = True
|
||||
|
||||
if commit:
|
||||
user.save()
|
||||
|
||||
39
users/management/commands/refresh_users_github_photos.py
Normal file
39
users/management/commands/refresh_users_github_photos.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import djclick as click
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from users.tasks import refresh_users_github_photos
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option(
|
||||
"--dry-run",
|
||||
is_flag=True,
|
||||
help="Show which users would be updated without actually updating them",
|
||||
default=False,
|
||||
)
|
||||
def command(dry_run):
|
||||
"""Refresh GitHub photos for all users who have a GitHub username.
|
||||
|
||||
This command fetches the latest profile photo from GitHub for each user
|
||||
and updates their local profile image. This is useful for keeping user
|
||||
avatars up-to-date as users change their GitHub profile photos.
|
||||
|
||||
When run without --dry-run, this calls the refresh_users_github_photos()
|
||||
Celery task which queues photo updates for all users with GitHub usernames.
|
||||
|
||||
With --dry-run, displays information about which users would be updated
|
||||
without making any changes.
|
||||
"""
|
||||
users = User.objects.exclude(github_username="")
|
||||
user_count = users.count()
|
||||
|
||||
if dry_run:
|
||||
click.secho(f"Refreshing {user_count} users, Github users:", fg="yellow")
|
||||
for user in users:
|
||||
click.echo(f" - User {user.pk}: {user.github_username}")
|
||||
else:
|
||||
click.secho(f"Refreshing photos, {user_count} users", fg="green")
|
||||
refresh_users_github_photos()
|
||||
click.secho(f"Triggered photo refresh task, {user_count} users", fg="green")
|
||||
21
users/migrations/0019_user_image_uploaded.py
Normal file
21
users/migrations/0019_user_image_uploaded.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-31 22:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("users", "0018_user_is_commit_author_name_overridden"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="image_uploaded",
|
||||
field=models.BooleanField(
|
||||
default=False,
|
||||
help_text="Indicates if the user manually uploaded an image, prevents import overwrites",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -230,6 +230,10 @@ class User(BaseUser):
|
||||
format="JPEG",
|
||||
options={"quality": 90},
|
||||
)
|
||||
image_uploaded = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Indicates if the user manually uploaded an image, prevents import overwrites",
|
||||
)
|
||||
claimed = models.BooleanField(
|
||||
_("claimed"),
|
||||
default=True,
|
||||
|
||||
@@ -31,7 +31,7 @@ def import_social_profile_data(sender, instance, created, **kwargs):
|
||||
elif instance.provider == GOOGLE:
|
||||
avatar_url = instance.extra_data.get("picture")
|
||||
|
||||
if avatar_url:
|
||||
if avatar_url and not instance.user.image_uploaded:
|
||||
instance.user.save_image_from_provider(avatar_url)
|
||||
|
||||
instance.user.display_name = instance.extra_data.get("name")
|
||||
|
||||
@@ -4,6 +4,7 @@ import structlog
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.mail import send_mail
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
@@ -47,10 +48,11 @@ def update_user_github_photo(user_pk):
|
||||
@app.task
|
||||
def refresh_users_github_photos():
|
||||
"""
|
||||
Refreshes the GitHub photos for all users who have a GitHub username.
|
||||
Refreshes the GitHub photos for all users who have a GitHub username and haven't
|
||||
uploaded an image manually.
|
||||
This is intended to be run periodically to ensure user photos are up-to-date.
|
||||
"""
|
||||
users = User.objects.exclude(github_username="")
|
||||
users = User.objects.exclude(Q(github_username="") | Q(image_uploaded=True))
|
||||
for user in users:
|
||||
try:
|
||||
logger.info(f"updating {user.pk=}")
|
||||
|
||||
Reference in New Issue
Block a user