Skip to content

Feature/gamesreleasedtoday #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions app/internal/game_releases_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from __future__ import annotations

from typing import List, TYPE_CHECKING

if TYPE_CHECKING:
from app.routers.calendar_grid import Week, Day

from datetime import datetime

from collections import defaultdict

import requests


def add_game_events_to_weeks(
weeks: List["Week"],
is_active: bool = True,
) -> List["Week"]:
if not is_active:
return weeks
first_week: Week = weeks[0]
last_week: Week = weeks[-1]
first_day: Day = first_week.days[0]
last_day: Day = last_week.days[-1]
first_day_str = datetime.strptime(first_day.set_id(), "%d-%B-%Y")
last_day_str = datetime.strptime(last_day.set_id(), "%d-%B-%Y")
games_by_dates = get_games_data_separated_by_days(
start_date=first_day_str.strftime("%Y-%m-%d"),
end_date=last_day_str.strftime("%Y-%m-%d"),
)
formatted_games = get_formatted_games_in_days(games_by_dates)
for week in weeks:
for day in week.days:
if day.set_id() in formatted_games.keys():
day.dailyevents.append(
(
f"GR!- {(formatted_games[day.set_id()][0])[:10]}",
(formatted_games[day.set_id()][0]),
),
)

return weeks


def get_games_data_separated_by_days(
start_date: datetime,
end_date: datetime,
) -> defaultdict[List]:
API = "https://api.rawg.io/api/games"

current_day_games = requests.get(
f"{API}?dates={start_date},{end_date}",
)

current_day_games = current_day_games.json()["results"]
games_data = defaultdict(list)
for result in current_day_games:
current = {}
current["name"] = result["name"]
current["platforms"] = []
for platform in result["platforms"]:
current["platforms"].append(platform["platform"]["name"])
ybd_release_date = translate_ymd_date_to_dby(result["released"])
games_data[ybd_release_date].append(current)
return games_data


def get_formatted_games_in_days(
separated_games_dict: defaultdict[List],
with_platforms: bool = False,
) -> defaultdict[List]:
formatted_games = defaultdict(list)

for date, game_data in separated_games_dict.items():
for game in game_data:
formatted_game_str = ""
formatted_game_str += game["name"]
if with_platforms:
formatted_game_str += "-Platforms-<br>"
for platform in game["platforms"]:
formatted_game_str += f"{platform},"
formatted_games[date].append(formatted_game_str)
return formatted_games


def translate_ymd_date_to_dby(ymd_str: str) -> str:
ymd_time = datetime.strptime(ymd_str, "%Y-%m-%d")
return ymd_time.strftime("%d-%B-%Y")


def translate_dby_date_to_ymd(dby_str: str) -> str:
dby_time = datetime.strptime(dby_str, "%d-%B-%Y")
return dby_time.strftime("%Y-%m-%d")
2 changes: 2 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def create_tables(engine, psql_environment):
export,
four_o_four,
friendview,
game_release_dates_service,
google_connect,
joke,
login,
Expand Down Expand Up @@ -133,6 +134,7 @@ async def swagger_ui_redirect():
weekview.router,
weight.router,
whatsapp.router,
game_release_dates_service.router,
]

for router in routers_to_include:
Expand Down
16 changes: 9 additions & 7 deletions app/routers/calendar.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from http import HTTPStatus

from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
from starlette.responses import Response
from fastapi.responses import HTMLResponse, Response

from app.dependencies import templates
from app.routers import calendar_grid as cg
Expand All @@ -11,7 +10,7 @@
prefix="/calendar/month",
tags=["calendar"],
responses={404: {"description": "Not found"}},
include_in_schema=False
include_in_schema=False,
)


Expand All @@ -25,18 +24,21 @@ async def calendar(request: Request) -> Response:
"request": request,
"day": day,
"week_days": cg.Week.DAYS_OF_THE_WEEK,
"weeks_block": cg.get_month_block(day)
}
"weeks_block": cg.get_month_block(day),
},
)


@router.get("/add/{date}")
async def update_calendar(
request: Request, date: str, days: int
request: Request,
date: str,
days: int,
) -> HTMLResponse:
last_day = cg.Day.convert_str_to_date(date)
next_weeks = cg.create_weeks(cg.get_n_days(last_day, days))
template = templates.get_template(
'partials/calendar/monthly_view/add_week.html')
"partials/calendar/monthly_view/add_week.html",
)
content = template.render(weeks_block=next_weeks)
return HTMLResponse(content=content, status_code=HTTPStatus.OK)
7 changes: 6 additions & 1 deletion app/routers/calendar_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import pytz

from app.internal.game_releases_utils import add_game_events_to_weeks

MONTH_BLOCK: int = 6

locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
Expand Down Expand Up @@ -177,7 +179,10 @@ def create_weeks(
"""Return lists of Weeks objects."""
ndays: List[Day] = list(days)
num_days: int = len(ndays)
return [Week(ndays[i : i + length]) for i in range(0, num_days, length)]
weeks = [Week(ndays[i : i + length]) for i in range(0, num_days, length)]

weeks = add_game_events_to_weeks(weeks, is_active=False)
return weeks


def get_month_block(day: Day, n: int = MONTH_BLOCK) -> List[Week]:
Expand Down
170 changes: 170 additions & 0 deletions app/routers/game_release_dates_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import datetime

from fastapi import APIRouter, Depends, Request
from fastapi.responses import RedirectResponse, Response
from sqlalchemy.orm import Session
from starlette.status import HTTP_302_FOUND

import requests
from app.database.models import UserSettings
from app.dependencies import get_db, templates
from app.internal.security.dependencies import current_user
from app.internal.security.schema import CurrentUser
from app.internal.utils import create_model

from typing import Dict, List


router = APIRouter(
prefix="/game-releases",
tags=["game-releases"],
responses={404: {"description": "Not found"}},
)


def is_user_signed_up_for_game_releases(
session: Session,
current_user_id: int,
) -> bool:
is_signed_up = (
session.query(UserSettings)
.filter(UserSettings.user_id == current_user_id)
.filter(UserSettings.video_game_releases.is_(True))
.first()
)

if is_signed_up:
return True
return False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return is_signed_up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_signed_up is an instance not a bool when it exists



# @router.post("/add-games-to-calendar")
# async def add_games_to_calendar(request: Request, session=Depends(get_db)):
# current_user = get_current_user(session)
# data = await request.form()
# create_event(
# session,
# title=game["name"],
# start=game["release_date"],
# end=game["release_date"],
# owner_id=current_user.id,
# )
# print(game_data)


@router.post("/get_releases_by_dates")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a post request. /{date}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need it to be awaited

async def fetch_released_games(
request: Request,
session=Depends(get_db),
) -> Response:
data = await request.form()

from_date = data["from-date"]
to_date = data["to-date"]

games = get_games_data(from_date, to_date)

return templates.TemplateResponse(
"partials/calendar/feature_settings/games_list.html",
{"request": request, "games": games},
)


@router.get("/get_game_releases_next_month")
def get_game_releases_month(request: Request) -> List:
today = datetime.datetime.today()
delta = datetime.timedelta(days=30)
today_str = today.strftime("%Y-%m-%d")
in_month_str = (today + delta).strftime("%Y-%m-%d")

games = get_games_data(today_str, in_month_str)

return games


# @router.post
# TODO
# add game to calendar
# @router.post
# remove game from calendar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feature should be shipped with these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently I decided not to add the releases to DB (in case the game release updates it would be worse than not knowing the date at all) and only update real time from the API.



def get_games_data(start_date: datetime, end_date: datetime) -> List[Dict]:
API = "https://api.rawg.io/api/games"

current_day_games = requests.get(
f"{API}?dates={start_date},{end_date}",
)
Comment on lines +56 to +60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause great load on our server, especially with high amount of users. Use JS instead.

current_day_games = current_day_games.json()["results"]
games_data = []
for result in current_day_games:
current = {}
current["name"] = result["name"]
current["slug"] = result["slug"]
current["platforms"] = []
for platform in result["platforms"]:
current["platforms"].append(platform["platform"]["name"])
current["release_date"] = result["released"]
games_data.append(current)

return games_data


@router.post("/subscribe")
async def subscribe_game_release_service(
request: Request,
session: Session = Depends(get_db),
user: CurrentUser = Depends(current_user),
) -> Response:
if is_user_signed_up_for_game_releases(session, user.user_id):
return RedirectResponse("/profile", status_code=HTTP_302_FOUND)
else:
games_setting_true = {UserSettings.video_game_releases: True}
games_setting_true_for_model = {
"user_id": user.user_id,
"video_game_releases": True,
}
current_user_settings = session.query(UserSettings).filter(
UserSettings.user_id == user.user_id,
)
if current_user_settings:
# TODO:
# If all users are created with a UserSettings entry -
# unnecessary check
current_user_settings.update(games_setting_true)
session.commit()
else:
create_model(session, UserSettings, **games_setting_true_for_model)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use merge?

Copy link
Contributor Author

@Liad-n Liad-n Feb 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So i did now but I can't really figure it out, it keeps creating new rows(I think it goes by primary key which is just an incremental id.
Didn't find a way to only update it without duplication other than update.
for now changed it back to update.

return RedirectResponse("/profile", status_code=HTTP_302_FOUND)


@router.post("/unsubscribe")
async def unsubscribe_game_release_service(
request: Request,
session: Session = Depends(get_db),
user: CurrentUser = Depends(current_user),
) -> RedirectResponse:
current_user_id = user.user_id

if not is_user_signed_up_for_game_releases(session, current_user_id):
return RedirectResponse("/profile", status_code=HTTP_302_FOUND)
else:
games_setting_false = {UserSettings.video_game_releases: False}
games_setting_false_for_model = {
"user_id": current_user_id,
"video_game_releases": False,
}
current_user_settings = session.query(UserSettings).filter(
UserSettings.user_id == current_user_id,
)
if current_user_settings:
# TODO:
# If all users are created with a UserSettings entry -
# unnecessary check
current_user_settings.update(games_setting_false)
session.commit()
else:
create_model(
session, UserSettings, **games_setting_false_for_model
)
return RedirectResponse("/profile", status_code=HTTP_302_FOUND)
17 changes: 17 additions & 0 deletions app/static/js/game_releases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
get_games_btn = document.getElementById("get-games");
get_games_btn.addEventListener("click", function (e) {
let formData = new FormData();
formData.append("from-date", document.getElementById("from-date").value);
formData.append("to-date", document.getElementById("to-date").value);
let clickedElem = e.target.id;
fetch("/game-releases/get_releases_by_dates", {
method: "post",
body: formData,
})
.then(function (response) {
return response.text();
})
.then(function (body) {
document.querySelector("#content-div").innerHTML = body;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

innerText maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
I'm not sure it would work here, wouldn't I be lacking formatting?

});
});
1 change: 1 addition & 0 deletions app/templates/partials/calendar/calendar_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{% endblock content %}
</div>
</div>
{% include 'partials/calendar/feature_settings/game_release_modal.html' %}
<!-- Scripts -->
<script src="{{ url_for('static', path='/js/grid_scripts.js') }}"></script>
<script src="{{ url_for('static', path='/js/grid_navigation.js') }}"></script>
Expand Down
Loading