models.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import logging
  2. from uuid import uuid4
  3. from django.conf import settings
  4. from django.contrib.auth import get_user_model
  5. from django.db import models
  6. from django.urls import reverse
  7. from django_extensions.db.models import TimeStampedModel
  8. from scrobbles.mixins import ScrobblableMixin
  9. from vrobbler.apps.scrobbles.utils import get_scrobbles_for_media
  10. logger = logging.getLogger(__name__)
  11. BNULL = {"blank": True, "null": True}
  12. User = get_user_model()
  13. class VideoGamePlatform(TimeStampedModel):
  14. name = models.CharField(max_length=255)
  15. uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
  16. logo = models.ImageField(upload_to="games/platform-logos/", **BNULL)
  17. igdb_id = models.IntegerField(**BNULL)
  18. def __str__(self):
  19. return self.name
  20. def get_absolute_url(self):
  21. return reverse(
  22. "videogames:platform_detail", kwargs={"slug": self.uuid}
  23. )
  24. class VideoGameCollection(TimeStampedModel):
  25. name = models.CharField(max_length=255)
  26. uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
  27. cover = models.ImageField(upload_to="games/series-covers/", **BNULL)
  28. igdb_id = models.IntegerField(**BNULL)
  29. def __str__(self):
  30. return self.name
  31. def get_absolute_url(self):
  32. return reverse(
  33. "videogames:collection_detail", kwargs={"slug": self.uuid}
  34. )
  35. class VideoGame(ScrobblableMixin):
  36. COMPLETION_PERCENT = getattr(settings, "GAME_COMPLETION_PERCENT", 100)
  37. FIELDS_FROM_IGDB = [
  38. "igdb_id",
  39. "alternative_name",
  40. "rating",
  41. "rating_count",
  42. "release_date",
  43. "cover",
  44. "screenshot",
  45. ]
  46. FIELDS_FROM_HLTB = [
  47. "hltb_id",
  48. "release_year",
  49. "main_story_time",
  50. "main_extra_time",
  51. "completionist_time",
  52. "hltb_score",
  53. ]
  54. title = models.CharField(max_length=255)
  55. igdb_id = models.IntegerField(**BNULL)
  56. hltb_id = models.IntegerField(**BNULL)
  57. alternative_name = models.CharField(max_length=255, **BNULL)
  58. uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
  59. cover = models.ImageField(upload_to="games/covers/", **BNULL)
  60. screenshot = models.ImageField(upload_to="games/screenshots/", **BNULL)
  61. hltb_cover = models.ImageField(upload_to="games/hltb_covers/", **BNULL)
  62. rating = models.FloatField(**BNULL)
  63. rating_count = models.IntegerField(**BNULL)
  64. release_date = models.DateTimeField(**BNULL)
  65. release_year = models.IntegerField(**BNULL)
  66. main_story_time = models.IntegerField(**BNULL)
  67. main_extra_time = models.IntegerField(**BNULL)
  68. completionist_time = models.IntegerField(**BNULL)
  69. hltb_score = models.FloatField(**BNULL)
  70. platforms = models.ManyToManyField(VideoGamePlatform)
  71. def __str__(self):
  72. return self.title
  73. def get_absolute_url(self):
  74. return reverse(
  75. "videogames:videogame_detail", kwargs={"slug": self.uuid}
  76. )
  77. def hltb_link(self):
  78. return f"https://howlongtobeat.com/game/{self.hltb_id}"
  79. @property
  80. def seconds_for_completion(self) -> int:
  81. completion_time = self.run_time_ticks
  82. if not completion_time:
  83. # Default to 10 hours, why not
  84. completion_time = 10 * 60 * 60
  85. return int(completion_time * (self.COMPLETION_PERCENT / 100))
  86. def progress_for_user(self, user_id: int) -> int:
  87. """Used to keep track of whether the game is complete or not"""
  88. user = User.objects.get(id=user_id)
  89. last_scrobble = get_scrobbles_for_media(self, user).last()
  90. if not last_scrobble or not last_scrobble.playback_position:
  91. logger.warn("No total minutes in last scrobble, no progress")
  92. return 0
  93. sec_played = last_scrobble.playback_position * 60
  94. return int(sec_played / self.run_time) * 100
  95. def fix_metadata(
  96. self,
  97. force_update: bool = False,
  98. ):
  99. from videogames.utils import (
  100. get_or_create_videogame,
  101. load_game_data_from_igdb,
  102. )
  103. if self.hltb_id and force_update:
  104. get_or_create_videogame(str(self.hltb_id), force_update)
  105. if self.igdb_id:
  106. load_game_data_from_igdb(self.id)
  107. if (not self.run_time_ticks or force_update) and self.main_story_time:
  108. self.run_time_ticks = self.main_story_time * 1000 # miliseconds
  109. self.run_time = self.main_story_time
  110. self.save(update_fields=["run_time_ticks", "run_time"])