from django.conf import settings from django.contrib.auth.decorators import login_required from django.shortcuts import render, get_object_or_404, redirect from django.urls import reverse from .models import Item, UserProfile from .forms import ItemForm, ProfileForm, SignupForm from . import steam as steam_api from . import hltb as hltb_api def signup(request): if request.method == 'POST': form = SignupForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.is_active = False user.save() return render(request, 'backlogger/signup_pending.html') else: form = SignupForm() return render(request, 'backlogger/signup.html', {'form': form}) SORT_MAP = { 'fav': ['-favorite', 'name'], 'az': ['name'], 'za': ['-name'], 'newest': ['-created_at'], 'oldest': ['created_at'], 'progress': ['-progress_percent'], 'updated': ['-updated_at'], } @login_required def profile(request): user_profile, _ = UserProfile.objects.get_or_create(user=request.user) if request.method == 'POST': form = ProfileForm(request.POST, instance=user_profile) if form.is_valid(): saved = form.save() request.session['theme'] = saved.theme return redirect('backlogger:profile') else: form = ProfileForm(instance=user_profile) request.session['theme'] = user_profile.theme return render(request, 'backlogger/profile.html', {'form': form, 'profile': user_profile}) @login_required def item_list(request): category = request.GET.get('category', '') sort = request.GET.get('sort', 'fav') shelf = request.GET.get('shelf', Item.ACTIVE) if shelf not in (Item.ACTIVE, Item.COMPLETED, Item.ABANDONED, Item.UNENDING): shelf = Item.ACTIVE items = Item.objects.filter(user=request.user, status=shelf) if category: items = items.filter(category=category) items = items.order_by(*SORT_MAP.get(sort, SORT_MAP['fav'])) return render(request, 'backlogger/list.html', { 'items': items, 'category': category, 'sort': sort, 'shelf': shelf, 'categories': Item.CATEGORY_CHOICES, 'debug': settings.DEBUG, }) @login_required def item_add(request): if request.method == 'POST': form = ItemForm(request.POST) if form.is_valid(): item = form.save(commit=False) item.user = request.user item.save() hltb_api.apply_to_item(item) return redirect('backlogger:list') else: form = ItemForm() return render(request, 'backlogger/item_form.html', {'form': form, 'action': 'Add'}) @login_required def item_edit(request, pk): item = get_object_or_404(Item, pk=pk, user=request.user) if request.method == 'POST': form = ItemForm(request.POST, instance=item) if form.is_valid(): updated = form.save() if 'name' in form.changed_data or 'category' in form.changed_data: hltb_api.apply_to_item(updated) return redirect('backlogger:list') else: form = ItemForm(instance=item) return render(request, 'backlogger/item_form.html', {'form': form, 'action': 'Edit', 'item': item}) @login_required def item_set_status(request, pk): if request.method == 'POST': item = get_object_or_404(Item, pk=pk, user=request.user) new_status = request.POST.get('status') if new_status in (Item.ACTIVE, Item.COMPLETED, Item.ABANDONED, Item.UNENDING): item.status = new_status item.save(update_fields=['status', 'updated_at']) next_url = request.POST.get('next') or reverse('backlogger:list') return redirect(next_url) @login_required def item_delete(request, pk): if request.method == 'POST': get_object_or_404(Item, pk=pk, user=request.user).delete() return redirect('backlogger:list') @login_required def steam_login(request): callback = request.build_absolute_uri(reverse('backlogger:steam_callback')) realm = f"{request.scheme}://{request.get_host()}" return redirect(steam_api.build_auth_url(callback, realm)) @login_required def steam_callback(request): steam_id = steam_api.verify_and_get_steam_id(request.GET.dict()) if not steam_id: return render(request, 'backlogger/steam_import.html', {'error': 'Steam verification failed. Please try again.'}) api_key = getattr(settings, 'STEAM_API_KEY', '') if not api_key: return render(request, 'backlogger/steam_import.html', {'error': 'Steam API key is not configured on the server.'}) try: games = steam_api.get_owned_games(api_key, steam_id) except Exception: return render(request, 'backlogger/steam_import.html', {'error': 'Could not fetch your Steam library. Your profile may be set to private.'}) existing = set( Item.objects.filter(user=request.user, category=Item.GAMES) .values_list('name', flat=True) ) game_list = [] for g in games: name = g.get('name', '') hours = round(g.get('playtime_forever', 0) / 60, 1) game_list.append({ 'appid': g.get('appid'), 'name': name, 'hours': hours, 'already_imported': name in existing, }) request.session['steam_games'] = game_list return render(request, 'backlogger/steam_import.html', {'games': game_list}) @login_required def steam_import(request): if request.method != 'POST': return redirect('backlogger:list') games_by_appid = {str(g['appid']): g for g in request.session.get('steam_games', [])} selected = request.POST.getlist('appids') imported = 0 for appid in selected: game = games_by_appid.get(appid) if not game or game['already_imported']: continue hours = game['hours'] progress = min(100.0, hours) if hours > 0 else 0.0 item = Item.objects.create( user=request.user, category=Item.GAMES, name=game['name'], hours_played=hours, progress_percent=progress, steam_appid=game['appid'], ) hltb_api.apply_to_item(item) imported += 1 del request.session['steam_games'] return redirect(f"{reverse('backlogger:list')}?category=games&imported={imported}") @login_required def debug_delete_all(request): if not settings.DEBUG: return redirect('backlogger:list') if request.method == 'POST': Item.objects.filter(user=request.user).delete() return redirect('backlogger:list') @login_required def steam_sync_login(request): callback = request.build_absolute_uri(reverse('backlogger:steam_sync_callback')) realm = f"{request.scheme}://{request.get_host()}" return redirect(steam_api.build_auth_url(callback, realm)) @login_required def steam_sync_callback(request): steam_id = steam_api.verify_and_get_steam_id(request.GET.dict()) if not steam_id: return redirect(f"{reverse('backlogger:list')}?sync_error=1") api_key = getattr(settings, 'STEAM_API_KEY', '') if not api_key: return redirect(f"{reverse('backlogger:list')}?sync_error=1") try: games = steam_api.get_owned_games(api_key, steam_id) except Exception: return redirect(f"{reverse('backlogger:list')}?sync_error=1") hours_by_appid = { g['appid']: round(g.get('playtime_forever', 0) / 60, 1) for g in games } steam_items = Item.objects.filter(user=request.user, steam_appid__isnull=False) synced = 0 for item in steam_items: new_hours = hours_by_appid.get(item.steam_appid) if new_hours is not None and new_hours != item.hours_played: item.hours_played = new_hours item.save(update_fields=['hours_played', 'updated_at']) synced += 1 return redirect(f"{reverse('backlogger:list')}?category=games&synced={synced}")