IGDB
This commit is contained in:
parent
4adb204ea1
commit
0f03dfa785
10 changed files with 112 additions and 12 deletions
|
@ -293,6 +293,10 @@ TMDB_API4_KEY = "deadbeef.deadbeef.deadbeef"
|
|||
# Google Books API Key
|
||||
GOOGLE_API_KEY = 'deadbeef-deadbeef-deadbeef'
|
||||
|
||||
# IGDB
|
||||
IGDB_CLIENT_ID = 'deadbeef'
|
||||
IGDB_ACCESS_TOKEN = 'deadbeef'
|
||||
|
||||
# Thumbnail setting
|
||||
# It is possible to optimize the image size even more: https://easy-thumbnails.readthedocs.io/en/latest/ref/optimize/
|
||||
THUMBNAIL_ALIASES = {
|
||||
|
|
|
@ -28,6 +28,7 @@ class SourceSiteEnum(models.TextChoices):
|
|||
TMDB = "tmdb", _("The Movie Database")
|
||||
GOOGLEBOOKS = "googlebooks", _("Google Books")
|
||||
BANDCAMP = "bandcamp", _("BandCamp")
|
||||
IGDB = "igdb", _("IGDB")
|
||||
|
||||
|
||||
class Entity(models.Model):
|
||||
|
|
|
@ -232,6 +232,7 @@ from common.scrapers.google import GoogleBooksScraper
|
|||
from common.scrapers.tmdb import TmdbMovieScraper
|
||||
from common.scrapers.steam import SteamGameScraper
|
||||
from common.scrapers.imdb import ImdbMovieScraper
|
||||
from common.scrapers.igdb import IgdbGameScraper
|
||||
from common.scrapers.spotify import SpotifyAlbumScraper, SpotifyTrackScraper
|
||||
from common.scrapers.douban import DoubanAlbumScraper, DoubanBookScraper, DoubanGameScraper, DoubanMovieScraper
|
||||
from common.scrapers.bangumi import BangumiScraper
|
||||
|
|
78
common/scrapers/igdb.py
Normal file
78
common/scrapers/igdb.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
import requests
|
||||
import re
|
||||
from common.models import SourceSiteEnum
|
||||
from games.models import Game
|
||||
from games.forms import GameForm
|
||||
from django.conf import settings
|
||||
from common.scraper import *
|
||||
from igdb.wrapper import IGDBWrapper
|
||||
import json
|
||||
import datetime
|
||||
|
||||
|
||||
wrapper = IGDBWrapper(settings.IGDB_CLIENT_ID, settings.IGDB_ACCESS_TOKEN)
|
||||
|
||||
|
||||
class IgdbGameScraper(AbstractScraper):
|
||||
site_name = SourceSiteEnum.IGDB.value
|
||||
host = 'https://www.igdb.com/'
|
||||
data_class = Game
|
||||
form_class = GameForm
|
||||
regex = re.compile(r"https://www\.igdb\.com/games/([a-zA-Z0-9\-_]+)")
|
||||
|
||||
def scrape(self, url):
|
||||
m = self.regex.match(url)
|
||||
if m:
|
||||
effective_url = m[0]
|
||||
else:
|
||||
raise ValueError("not valid url")
|
||||
effective_url = m[0]
|
||||
slug = m[1]
|
||||
fields = '*, cover.url, genres.name, platforms.name, involved_companies.*, involved_companies.company.name'
|
||||
r = json.loads(wrapper.api_request('games', f'fields {fields}; where url = "{effective_url}";'))[0]
|
||||
raw_img, ext = self.download_image('https:' + r['cover']['url'].replace('t_thumb', 't_cover_big'), url)
|
||||
developer = None
|
||||
publisher = None
|
||||
release_date = None
|
||||
genre = None
|
||||
platform = None
|
||||
if 'involved_companies' in r:
|
||||
developer = next(iter([c['company']['name'] for c in r['involved_companies'] if c['developer'] == True]), None)
|
||||
publisher = next(iter([c['company']['name'] for c in r['involved_companies'] if c['publisher'] == True]), None)
|
||||
if 'platforms' in r:
|
||||
platform = [p['name'] for p in r['platforms']]
|
||||
if 'first_release_date' in r:
|
||||
release_date = datetime.datetime.fromtimestamp(r['first_release_date'], datetime.timezone.utc)
|
||||
if 'genres' in r:
|
||||
genre = [g['name'] for g in r['genres']]
|
||||
other_info = {'igdb_id': r['id']}
|
||||
websites = json.loads(wrapper.api_request('websites', f'fields *; where game.url = "{effective_url}";'))
|
||||
for website in websites:
|
||||
if website['category'] == 1:
|
||||
other_info['official_site'] = website['url']
|
||||
elif website['category'] == 13:
|
||||
other_info['steam_url'] = website['url']
|
||||
data = {
|
||||
'title': r['name'],
|
||||
'other_title': None,
|
||||
'developer': developer,
|
||||
'publisher': publisher,
|
||||
'release_date': release_date,
|
||||
'genre': genre,
|
||||
'platform': platform,
|
||||
'brief': r['storyline'],
|
||||
'other_info': other_info,
|
||||
'source_site': self.site_name,
|
||||
'source_url': self.get_effective_url(url),
|
||||
}
|
||||
|
||||
self.raw_data, self.raw_img, self.img_ext = data, raw_img, ext
|
||||
return data, raw_img
|
||||
|
||||
@classmethod
|
||||
def get_effective_url(cls, raw_url):
|
||||
m = cls.regex.match(raw_url)
|
||||
if raw_url:
|
||||
return m[0]
|
||||
else:
|
||||
return None
|
|
@ -1146,6 +1146,13 @@ select::placeholder {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.source-label.source-label__igdb {
|
||||
background-color: #323A44;
|
||||
color: #DFE1E2;
|
||||
border: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.source-label.source-label__steam {
|
||||
background: linear-gradient(30deg, #1387b8, #111d2e);
|
||||
color: white;
|
||||
|
|
2
common/static/css/boofilsic.min.css
vendored
2
common/static/css/boofilsic.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -7,6 +7,8 @@ $spotify-color-primary: #1ed760
|
|||
$spotify-color-secondary: black
|
||||
$imdb-color-primary: #F5C518
|
||||
$imdb-color-secondary: #121212
|
||||
$igdb-color-primary: #323A44
|
||||
$igdb-color-secondary: #DFE1E2
|
||||
$steam-color-primary: #1387b8
|
||||
$steam-color-secondary: #111d2e
|
||||
$bangumi-color-primary: #F09199
|
||||
|
@ -56,6 +58,11 @@ $bandcamp-color-secondary: white
|
|||
color: $imdb-color-secondary
|
||||
border: none
|
||||
font-weight: bold
|
||||
&.source-label__igdb
|
||||
background-color: $igdb-color-primary
|
||||
color: $igdb-color-secondary
|
||||
border: none
|
||||
font-weight: bold
|
||||
&.source-label__steam
|
||||
background: linear-gradient(30deg, $steam-color-primary, $steam-color-secondary)
|
||||
color: white
|
||||
|
|
|
@ -60,7 +60,7 @@ class Game(Entity):
|
|||
)
|
||||
|
||||
genre = postgres.ArrayField(
|
||||
models.CharField(blank=True, default='', max_length=50),
|
||||
models.CharField(blank=True, default='', max_length=200),
|
||||
null=True,
|
||||
blank=True,
|
||||
default=list,
|
||||
|
@ -68,7 +68,7 @@ class Game(Entity):
|
|||
)
|
||||
|
||||
platform = postgres.ArrayField(
|
||||
models.CharField(blank=True, default='', max_length=50),
|
||||
models.CharField(blank=True, default='', max_length=200),
|
||||
null=True,
|
||||
blank=True,
|
||||
default=list,
|
||||
|
|
|
@ -111,7 +111,15 @@
|
|||
{% trans '发行日期:' %}{{ game.release_date }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
{% if game.other_info %}
|
||||
{% for k, v in game.other_info.items %}
|
||||
<div>
|
||||
{{ k }}:{{ v | urlize }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
|
||||
|
@ -123,14 +131,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if game.other_info %}
|
||||
{% for k, v in game.other_info.items %}
|
||||
<div>
|
||||
{{ k }}:{{ v | urlize }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{% if game.last_editor %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'users:home' game.last_editor.mastodon_username %}">{{ game.last_editor | default:"" }}</a></div>
|
||||
|
|
|
@ -22,3 +22,4 @@ typesense
|
|||
markdownify
|
||||
sentry-sdk
|
||||
gitpython
|
||||
igdb-api-v4
|
||||
|
|
Loading…
Add table
Reference in a new issue