Skip to content

Commit

Permalink
Merge pull request #139 from eee555/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
eee555 authored Oct 13, 2024
2 parents 1464ced + fc147a4 commit 52ae41d
Show file tree
Hide file tree
Showing 35 changed files with 1,112 additions and 501 deletions.
Empty file.
6 changes: 6 additions & 0 deletions back_end/saolei/accountlink/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class AccountLinkConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "accountlink"
Empty file.
120 changes: 120 additions & 0 deletions back_end/saolei/accountlink/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
from django.db import models
from userprofile.models import UserProfile

class Platform(models.TextChoices):
MSGAMES = 'a', ('Authoritative Minesweeper')
SAOLEI = 'c', ('扫雷网')
WOM = 'w', ('Minesweeper.Online')

# 用于验证的队列
class AccountLinkQueue(models.Model):
platform = models.CharField(max_length=1, null=False, choices=Platform.choices)
identifier = models.CharField(max_length=128, null=False)
userprofile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
verified = models.BooleanField(default=False)

# 网站编码 website code
# a - Authoritative Minesweeper
# c - China ranking (saolei.wang)
# g - Minesweeper GO
# l - League of Minesweeper
# s - Scoreganizer
# w - World of Minesweeper
# B - Bilibili
# D - Discord
# F - Facebook
# G - GitHub
# R - Reddit
# S - Speedrun.com
# T - Tieba
# W - Weibo
# X - X
# Y - YouTube
# Z - Zhihu

# 扫雷网账号信息
class AccountSaolei(models.Model):
id = models.PositiveIntegerField(primary_key=True)
parent = models.OneToOneField(UserProfile, on_delete=models.CASCADE, related_name='account_saolei')
update_time = models.DateTimeField(auto_now_add=True)

name = models.CharField(max_length=10) # 姓名,10应该够了吧
total_views = models.PositiveIntegerField(null=True) # 综合人气

beg_count = models.PositiveSmallIntegerField(null=True) # 初级录像数量
int_count = models.PositiveSmallIntegerField(null=True) # 中级录像数量
exp_count = models.PositiveSmallIntegerField(null=True) # 高级录像数量

# time纪录,单位毫秒
b_t_ms = models.PositiveIntegerField(null=True)
i_t_ms = models.PositiveIntegerField(null=True)
e_t_ms = models.PositiveIntegerField(null=True)
s_t_ms = models.PositiveIntegerField(null=True)

# bvs纪录,单位0.01。大概不会有人bvs超过300吧?大概吧?
b_b_cent = models.PositiveSmallIntegerField(null=True)
i_b_cent = models.PositiveSmallIntegerField(null=True)
e_b_cent = models.PositiveSmallIntegerField(null=True)
s_b_cent = models.PositiveSmallIntegerField(null=True)

class AccountMinesweeperGames(models.Model):
id = models.PositiveIntegerField(primary_key=True)
parent = models.OneToOneField(UserProfile, on_delete=models.CASCADE, related_name='account_msgames')
update_time = models.DateTimeField(auto_now_add=True)

name = models.CharField(max_length=128)
local_name = models.CharField(max_length=128)
# country = models.CharField() # country和state应该是二合一的枚举类型
# state = models.CharField()
joined = models.DateField(null=True)
# mouse_brand = models.CharField(max_length=128) # 枚举
# mouse_type = models.CharField(max_length=128) # 枚举
# mouse_model = models.CharField() # 用户自己随便填的,需要审查

class AccountWorldOfMinesweeper(models.Model):
id = models.PositiveIntegerField(primary_key=True)
parent = models.OneToOneField(UserProfile, on_delete=models.CASCADE, related_name='account_wom')
update_time = models.DateTimeField(auto_now_add=True)

# name 有的用户名过不了审
# country 有争议
trophy = models.PositiveSmallIntegerField(null=True)

experience = models.PositiveIntegerField(null=True)
honour = models.PositiveIntegerField(null=True)

minecoin = models.PositiveIntegerField(null=True)
gem = models.PositiveIntegerField(null=True)
coin = models.PositiveIntegerField(null=True)
arena_ticket = models.PositiveIntegerField(null=True)
equipment = models.PositiveIntegerField(null=True)
part = models.PositiveIntegerField(null=True)

arena_point = models.PositiveSmallIntegerField(null=True) # 最高80
max_difficulty = models.PositiveIntegerField(null=True)
win = models.PositiveIntegerField(null=True)
last_season = models.PositiveSmallIntegerField(null=True)

b_t_ms = models.PositiveIntegerField(null=True)
i_t_ms = models.PositiveIntegerField(null=True)
e_t_ms = models.PositiveIntegerField(null=True)
s_t_ms = models.PositiveIntegerField(null=True)

b_ioe = models.FloatField(null=True)
i_ioe = models.FloatField(null=True)
e_ioe = models.FloatField(null=True)
s_ioe = models.FloatField(null=True)

b_mastery = models.PositiveSmallIntegerField(null=True)
i_mastery = models.PositiveSmallIntegerField(null=True)
e_mastery = models.PositiveSmallIntegerField(null=True)

b_winstreak = models.PositiveSmallIntegerField(null=True)
i_winstreak = models.PositiveSmallIntegerField(null=True)
e_winstreak = models.PositiveSmallIntegerField(null=True)

# 主页只显示一个
# b_endurance = models.TimeField()
# i_endurance = models.TimeField()
# e_endurance = models.TimeField()
11 changes: 11 additions & 0 deletions back_end/saolei/accountlink/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.urls import path

from . import views
app_name = 'accountlink'
urlpatterns = [
path('add/', views.add_link),
path('delete/', views.delete_link),
path('get/', views.get_link),
path('verify/', views.verify_link),
path('unverify/', views.unverify_link),
]
54 changes: 54 additions & 0 deletions back_end/saolei/accountlink/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from .models import AccountSaolei, AccountMinesweeperGames, AccountWorldOfMinesweeper, Platform
from datetime import datetime
from userprofile.models import UserProfile

def update_account(platform: Platform, id, user: UserProfile | None):
if platform == Platform.SAOLEI:
update_saolei_account(id, user)
elif platform == Platform.MSGAMES:
update_msgames_account(id, user)
elif platform == Platform.WOM:
update_wom_account(id, user)
else:
ValueError()

def delete_account(user: UserProfile, platform: Platform):
if platform == Platform.SAOLEI:
user.account_saolei.delete()
elif platform == Platform.MSGAMES:
user.account_msgames.delete()
elif platform == Platform.WOM:
user.account_wom.delete()
else:
ValueError()

def update_saolei_account(id, user: UserProfile | None):
account = AccountSaolei.objects.filter(id=id).first()
if not account:
account = AccountSaolei.objects.create(id=id, parent=user)
elif user:
account.parent=user
account.update_time = datetime.now()
# 给account的各attribute赋值
account.save()

def update_msgames_account(id, user: UserProfile | None):
account = AccountMinesweeperGames.objects.filter(id=id).first()
if not account:
account = AccountMinesweeperGames.objects.create(id=id, parent=user)
elif user:
account.parent=user
account.update_time = datetime.now()
# 给account的各attribute赋值
account.save()

def update_wom_account(id, user: UserProfile | None):
print(user)
account = AccountWorldOfMinesweeper.objects.filter(id=id).first()
if not account:
account = AccountWorldOfMinesweeper.objects.create(id=id, parent=user)
elif user:
account.parent=user
account.update_time = datetime.now()
# 给account的各attribute赋值
account.save()
96 changes: 96 additions & 0 deletions back_end/saolei/accountlink/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from .models import AccountLinkQueue
from .utils import update_account, delete_account
from userprofile.models import UserProfile
from django.http import HttpResponseForbidden, HttpResponseBadRequest, JsonResponse, HttpResponse, HttpResponseNotFound
from utils.response import HttpResponseConflict
from django.views.decorators.http import require_GET, require_POST
from django_ratelimit.decorators import ratelimit
from userprofile.decorators import login_required_error, staff_required

private_platforms = [""] # 私人账号平台

# 为自己绑定账号,需要指定平台和ID
@ratelimit(key='user', rate='10/d')
@require_POST
@login_required_error
def add_link(request):
user = UserProfile.objects.filter(id=request.user.id).first()
platform = request.POST.get('platform')
if platform == None:
return HttpResponseBadRequest()
accountlink = AccountLinkQueue.objects.filter(platform=platform, userprofile=user).first()
if accountlink:
return HttpResponseConflict() # 每个平台只能绑一个账号
accountlink = AccountLinkQueue.objects.create(platform=platform, identifier=request.POST.get('identifier'), userprofile=user)
return HttpResponse()

# 解绑自己的账号,只需要指定平台
@require_POST
@login_required_error
def delete_link(request):
user = UserProfile.objects.filter(id=request.user.id).first()
platform = request.POST.get('platform')
if platform == None:
return HttpResponseBadRequest()
accountlink = AccountLinkQueue.objects.filter(platform=platform, userprofile=user).first()
if accountlink:
if accountlink.verified:
delete_account(user, platform)
accountlink.delete()
return HttpResponse()
return HttpResponseNotFound()

@require_GET
def get_link(request):
userid = request.GET.get("id")
user = UserProfile.objects.filter(id=userid).first()
if request.user.is_staff or user == request.user: # 管理员或用户本人可以获得全部数据
accountlink = AccountLinkQueue.objects.filter(userprofile=user).values("platform","identifier","verified")
else: # 其他人不能获得未绑定账号与私人账号数据
accountlink = AccountLinkQueue.objects.filter(userprofile=user,verified=True).exclude(platform__in=private_platforms).values("platform","identifier")
return JsonResponse(list(accountlink), safe=False)

@require_POST
@staff_required
def verify_link(request):
userid = request.POST.get("id")
user = UserProfile.objects.filter(id=userid).first()
if user == None:
return HttpResponseNotFound()
platform = request.POST.get('platform')
if platform == None:
return HttpResponseBadRequest()
identifier = request.POST.get('identifier')
if identifier == None:
return HttpResponseBadRequest()
collision = AccountLinkQueue.objects.filter(platform=platform,identifier=identifier,verified=True).first()
if collision: # 该平台该ID已被绑定
if collision.userprofile == user:
return HttpResponse()
else:
return HttpResponseConflict()
accountlink = AccountLinkQueue.objects.filter(platform=platform,identifier=identifier).first()
if not accountlink:
return HttpResponseNotFound()
update_account(platform, identifier, user)
accountlink.verified = True
accountlink.save()
return HttpResponse()

@require_POST
@staff_required
def unverify_link(request):
userid = request.GET.get("id")
user = UserProfile.objects.filter(id=userid).first()
if not user:
return HttpResponseNotFound()
platform = request.POST.get('platform')
identifier = request.POST.get('identifier')
accountlink = AccountLinkQueue.objects.filter(userprofile=user,platform=platform,identifier=identifier).first()
if not accountlink:
return HttpResponseNotFound()
delete_account(user, platform)
accountlink.verified = False
accountlink.save()
return HttpResponse()

Loading

0 comments on commit 52ae41d

Please sign in to comment.