|
|
|
|
@ -1,47 +1,86 @@
|
|
|
|
|
import requests
|
|
|
|
|
import requests # 用于发送HTTP请求,验证图片URL有效性
|
|
|
|
|
from django.core.management.base import BaseCommand
|
|
|
|
|
from django.templatetags.static import static
|
|
|
|
|
from django.templatetags.static import static # 生成静态文件URL
|
|
|
|
|
|
|
|
|
|
from djangoblog.utils import save_user_avatar
|
|
|
|
|
from oauth.models import OAuthUser
|
|
|
|
|
from oauth.oauthmanager import get_manager_by_type
|
|
|
|
|
# 导入项目工具和模型:用户头像保存、OAuth用户模型、OAuth管理工具
|
|
|
|
|
from djangoblog.utils import save_user_avatar # 保存用户头像到本地的工具函数
|
|
|
|
|
from oauth.models import OAuthUser # OAuth关联用户模型(存储第三方登录用户信息)
|
|
|
|
|
from oauth.oauthmanager import get_manager_by_type # 根据 OAuth 类型获取对应管理器
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Command(BaseCommand):
|
|
|
|
|
"""
|
|
|
|
|
Django自定义管理命令:同步用户头像
|
|
|
|
|
用于检查并更新OAuth用户的头像URL,确保头像可访问(无效则重新获取或使用默认头像)
|
|
|
|
|
"""
|
|
|
|
|
# 命令的帮助信息(执行python manage.py help sync_user_avatar时显示)
|
|
|
|
|
help = 'sync user avatar'
|
|
|
|
|
|
|
|
|
|
def test_picture(self, url):
|
|
|
|
|
"""
|
|
|
|
|
验证图片URL是否有效(可访问且返回200状态码)
|
|
|
|
|
:param url: 头像图片的URL
|
|
|
|
|
:return: 有效则返回True,否则返回False
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# 发送GET请求,超时2秒,检查状态码是否为200
|
|
|
|
|
if requests.get(url, timeout=2).status_code == 200:
|
|
|
|
|
return True
|
|
|
|
|
except:
|
|
|
|
|
# 任何异常(超时、连接错误等)均视为无效
|
|
|
|
|
pass
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def handle(self, *args, **options):
|
|
|
|
|
"""
|
|
|
|
|
命令核心执行逻辑
|
|
|
|
|
遍历所有OAuth用户,检查并同步头像URL
|
|
|
|
|
"""
|
|
|
|
|
# 获取项目静态文件的基础URL(用于判断头像是否为本地静态文件)
|
|
|
|
|
static_url = static("../")
|
|
|
|
|
|
|
|
|
|
# 获取所有OAuth用户
|
|
|
|
|
users = OAuthUser.objects.all()
|
|
|
|
|
self.stdout.write(f'开始同步{len(users)}个用户头像')
|
|
|
|
|
|
|
|
|
|
# 遍历每个用户处理头像
|
|
|
|
|
for u in users:
|
|
|
|
|
self.stdout.write(f'开始同步:{u.nickname}')
|
|
|
|
|
url = u.picture
|
|
|
|
|
if url:
|
|
|
|
|
self.stdout.write(f'开始同步:{u.nickname}') # 输出当前处理的用户名
|
|
|
|
|
url = u.picture # 获取用户当前的头像URL
|
|
|
|
|
|
|
|
|
|
if url: # 如果用户已有头像URL
|
|
|
|
|
# 情况1:头像URL是本地静态文件(以static_url开头)
|
|
|
|
|
if url.startswith(static_url):
|
|
|
|
|
# 验证本地头像是否有效
|
|
|
|
|
if self.test_picture(url):
|
|
|
|
|
continue
|
|
|
|
|
self.stdout.write(f' 头像有效,跳过:{url}')
|
|
|
|
|
continue # 有效则跳过处理
|
|
|
|
|
else:
|
|
|
|
|
if u.metadata:
|
|
|
|
|
# 本地头像无效,尝试重新获取
|
|
|
|
|
self.stdout.write(f' 本地头像无效,尝试重新获取')
|
|
|
|
|
if u.metadata: # 如果存在第三方平台返回的元数据(可能包含头像信息)
|
|
|
|
|
# 根据OAuth类型(如qq、weibo)获取对应的管理器
|
|
|
|
|
manage = get_manager_by_type(u.type)
|
|
|
|
|
# 从元数据中提取最新头像URL
|
|
|
|
|
url = manage.get_picture(u.metadata)
|
|
|
|
|
# 保存头像到本地并返回新的URL
|
|
|
|
|
url = save_user_avatar(url)
|
|
|
|
|
else:
|
|
|
|
|
# 无元数据,使用默认头像
|
|
|
|
|
url = static('blog/img/avatar.png')
|
|
|
|
|
else:
|
|
|
|
|
# 情况2:头像URL是第三方链接(非本地文件),保存到本地
|
|
|
|
|
self.stdout.write(f' 第三方头像,保存到本地')
|
|
|
|
|
url = save_user_avatar(url)
|
|
|
|
|
else:
|
|
|
|
|
# 情况3:用户无头像URL,使用默认头像
|
|
|
|
|
self.stdout.write(f' 无头像,使用默认头像')
|
|
|
|
|
url = static('blog/img/avatar.png')
|
|
|
|
|
|
|
|
|
|
# 更新用户头像并保存
|
|
|
|
|
if url:
|
|
|
|
|
self.stdout.write(
|
|
|
|
|
f'结束同步:{u.nickname}.url:{url}')
|
|
|
|
|
self.stdout.write(f' 结束同步:{u.nickname}.url:{url}')
|
|
|
|
|
u.picture = url
|
|
|
|
|
u.save()
|
|
|
|
|
self.stdout.write('结束同步')
|
|
|
|
|
u.save() # 保存更新后的头像URL
|
|
|
|
|
|
|
|
|
|
self.stdout.write('所有用户头像同步完成')
|