diff --git a/app/database/models.py b/app/database/models.py index 4466dc76..e79e423b 100644 --- a/app/database/models.py +++ b/app/database/models.py @@ -4,27 +4,13 @@ from datetime import datetime from typing import Any, Dict -from sqlalchemy import ( - DDL, - JSON, - Boolean, - Column, - Date, - DateTime, - Enum, - Float, - ForeignKey, - Index, - Integer, - String, - Time, - UniqueConstraint, - event, -) +from sqlalchemy import (Boolean, Column, Date, DateTime, DDL, Enum, event, + Float, ForeignKey, Index, Integer, JSON, String, Time, + UniqueConstraint) from sqlalchemy.dialects.postgresql import TSVECTOR from sqlalchemy.exc import IntegrityError, SQLAlchemyError -from sqlalchemy.ext.declarative.api import DeclarativeMeta, declarative_base -from sqlalchemy.orm import Session, relationship +from sqlalchemy.ext.declarative.api import declarative_base, DeclarativeMeta +from sqlalchemy.orm import relationship, Session from sqlalchemy.sql.schema import CheckConstraint import app.routers.salary.config as SalaryConfig @@ -191,10 +177,10 @@ class Category(Base): @staticmethod def create( - db_session: Session, - name: str, - color: str, - user_id: int, + db_session: Session, + name: str, + color: str, + user_id: int, ) -> Category: try: category = Category(name=name, color=color, user_id=user_id) diff --git a/app/internal/json_data_loader.py b/app/internal/json_data_loader.py index 779bfa17..93b5c9d1 100644 --- a/app/internal/json_data_loader.py +++ b/app/internal/json_data_loader.py @@ -5,8 +5,13 @@ from loguru import logger from sqlalchemy.orm import Session -from app.database.models import Base, InternationalDays, Joke, Quote, Zodiac -from app.internal import daily_quotes, international_days, jokes, zodiac +from app.config import RESOURCES_DIR +from app.database.models import ( + Base, InternationalDays, Joke, Quote, Zodiac +) +from app.internal import ( + daily_quotes, international_days, jokes, zodiac +) def load_to_database(session: Session) -> None: @@ -23,28 +28,28 @@ def load_to_database(session: Session) -> None: """ _insert_into_database( session, - 'app/resources/zodiac.json', + RESOURCES_DIR / "zodiac.json", Zodiac, zodiac.get_zodiac, ) _insert_into_database( session, - 'app/resources/quotes.json', + RESOURCES_DIR / "quotes.json", Quote, daily_quotes.get_quote, ) _insert_into_database( session, - 'app/resources/international_days.json', + RESOURCES_DIR / "international_days.json", InternationalDays, international_days.get_international_day, ) _insert_into_database( session, - 'app/resources/jokes.json', + RESOURCES_DIR / "jokes.json", Joke, jokes.get_joke, ) diff --git a/app/internal/shabbat.py b/app/internal/shabbat.py new file mode 100644 index 00000000..3f980fee --- /dev/null +++ b/app/internal/shabbat.py @@ -0,0 +1,86 @@ +import json +from datetime import date, datetime +from typing import Any, Dict, List, Optional, Union + +import httpx + +from app.config import RESOURCES_DIR + +SHABBAT_API = 'https://www.hebcal.com/shabbat?cfg=json&geonameid=' + + +def return_zip_code_of_user_location(location_by_ip) -> str: + """Returns zip code from locations JSON file that match user location. + + Args: + location_by_ip: location by ip that create with "geocoder" module. + + Returns: + A zip code string for the user location. + """ + path = RESOURCES_DIR / "locations.json" + with open(path, 'r', encoding="utf8") as json_file: + locations = json.load(json_file) + for location in locations: + if (location["city"] == location_by_ip.city + and location["country"] == location_by_ip.country): + return location["zip_number"] + + +def return_shabbat_times( + shabat_items: Dict[Any, List[Dict[str, str]]] +) -> Dict[str, Union[date, Any]]: + """Returns the shabbat time which match to ip(of the user) location. + Used the content of this is free API: + 'https://www.hebcal.com/shabbat?cfg=json&geonameid=295277'. + + Args: + shabat_items: dictionary of all the details about shabbat according to + specific ip location. + + Returns: + Shabbat start end ending time and user location by ip. + """ + for item in shabat_items: + if "Candle lighting" in item["title"]: + shabbat_entry = item["date"] + if "Havdalah" in item["title"]: + shabbat_exit = item["date"] + + shabbat_entry_date = shabbat_entry.split("T")[0] + shabbat_entry_hour = shabbat_entry.split("T")[1] + shabbat_exit_date = shabbat_exit.split("T")[0] + shabbat_exit_hour = shabbat_exit.split("T")[1] + shabbat_limit = { + "start_hour": shabbat_entry_hour[:5], + "start_date": datetime.strptime(shabbat_entry_date, "%Y-%m-%d").date(), + "end_hour": shabbat_exit_hour[:5], + "end_date": datetime.strptime(shabbat_exit_date, "%Y-%m-%d").date(), + } + return shabbat_limit + + +async def get_shabbat_if_date_friday(calendar_date: date, + location_by_ip, + ) -> Optional[Dict[str, date]]: + """Returns shabbat start end ending time if specific date is friday, + else None. + The function used in the free API: + 'https://www.hebcal.com/shabbat?cfg=json&geonameid=295277'. + + Args: + calendar_date: date. + location_by_ip: location by ip that create with "geocoder" module. + + Returns: + Shabbat start and ending time if specific date + is Saturday and user location by ip, else None + """ + async with httpx.AsyncClient() as client: + zip_code = return_zip_code_of_user_location(location_by_ip) + shabbat_api = SHABBAT_API + zip_code + response = await client.get(shabbat_api) + shabat_items = response.json()['items'] + shabbat_obj = return_shabbat_times(shabat_items) + if calendar_date == shabbat_obj["start_date"]: + return shabbat_obj diff --git a/app/resources/locations.json b/app/resources/locations.json new file mode 100644 index 00000000..ee415682 --- /dev/null +++ b/app/resources/locations.json @@ -0,0 +1,2047 @@ +[ + { + "country":"AD", + "city":"Andorra La Vella", + "zip_number":"3041563" + }, + { + "country":"AE", + "city":"Abu Dhabi", + "zip_number":"292968" + }, + { + "country":"AE", + "city":"Dubai", + "zip_number":"292223" + }, + { + "country":"AF", + "city":"Kabul", + "zip_number":"1138958" + }, + { + "country":"AI", + "city":"The Valley", + "zip_number":"3573374" + }, + { + "country":"AL", + "city":"Tirana", + "zip_number":"3183875" + }, + { + "country":"AM", + "city":"Yerevan", + "zip_number":"616052" + }, + { + "country":"AO", + "city":"Luanda", + "zip_number":"2240449" + }, + { + "country":"AR", + "city":"Buenos Aires", + "zip_number":"3435910" + }, + { + "country":"AR", + "city":"Cordoba", + "zip_number":"3860259" + }, + { + "country":"AR", + "city":"Rosario", + "zip_number":"3838583" + }, + { + "country":"AS", + "city":"Pago Pago", + "zip_number":"5881576" + }, + { + "country":"AT", + "city":"Vienna", + "zip_number":"2761369" + }, + { + "country":"AU", + "city":"Adelaide", + "zip_number":"2078025" + }, + { + "country":"AU", + "city":"Brisbane", + "zip_number":"2174003" + }, + { + "country":"AU", + "city":"Canberra", + "zip_number":"2172517" + }, + { + "country":"AU", + "city":"Gold Coast", + "zip_number":"2165087" + }, + { + "country":"AU", + "city":"Hobart", + "zip_number":"2163355" + }, + { + "country":"AU", + "city":"Melbourne", + "zip_number":"2158177" + }, + { + "country":"AU", + "city":"Perth", + "zip_number":"2063523" + }, + { + "country":"AU", + "city":"Sydney", + "zip_number":"2147714" + }, + { + "country":"AW", + "city":"Oranjestad", + "zip_number":"3577154" + }, + { + "country":"AZ", + "city":"Baku", + "zip_number":"587084" + }, + { + "country":"BA", + "city":"Sarajevo", + "zip_number":"3191281" + }, + { + "country":"BB", + "city":"Bridgetown", + "zip_number":"3374036" + }, + { + "country":"BD", + "city":"Chittagong", + "zip_number":"1205733" + }, + { + "country":"BD", + "city":"Dhaka", + "zip_number":"1185241" + }, + { + "country":"BD", + "city":"Khulna", + "zip_number":"1336135" + }, + { + "country":"BE", + "city":"Brussels", + "zip_number":"2800866" + }, + { + "country":"BF", + "city":"Ouagadougou", + "zip_number":"2357048" + }, + { + "country":"BG", + "city":"Sofia", + "zip_number":"727011" + }, + { + "country":"BH", + "city":"Manama", + "zip_number":"290340" + }, + { + "country":"BI", + "city":"Bujumbura", + "zip_number":"425378" + }, + { + "country":"BJ", + "city":"Porto", + "zip_number":"novo" + }, + { + "country":"BM", + "city":"Hamilton", + "zip_number":"3573197" + }, + { + "country":"BN", + "city":"Bandar Seri Begawan", + "zip_number":"1820906" + }, + { + "country":"BO", + "city":"La Paz", + "zip_number":"3911925" + }, + { + "country":"BO", + "city":"Santa Cruz de la Sierra", + "zip_number":"3904906" + }, + { + "country":"BR", + "city":"Belo Horizonte", + "zip_number":"3470127" + }, + { + "country":"BR", + "city":"Brasilia", + "zip_number":"3469058" + }, + { + "country":"BR", + "city":"Fortaleza", + "zip_number":"3399415" + }, + { + "country":"BR", + "city":"Rio de Janeiro", + "zip_number":"3451190" + }, + { + "country":"BR", + "city":"Salvador", + "zip_number":"3450554" + }, + { + "country":"BR", + "city":"Sao Paulo", + "zip_number":"3448439" + }, + { + "country":"BS", + "city":"Nassau", + "zip_number":"3571824" + }, + { + "country":"BT", + "city":"Thimphu", + "zip_number":"1252416" + }, + { + "country":"BW", + "city":"Gaborone", + "zip_number":"933773" + }, + { + "country":"BY", + "city":"Minsk", + "zip_number":"625144" + }, + { + "country":"BZ", + "city":"Belmopan", + "zip_number":"3582672" + }, + { + "country":"CA", + "city":"Calgary", + "zip_number":"5913490" + }, + { + "country":"CA", + "city":"Edmonton", + "zip_number":"5946768" + }, + { + "country":"CA", + "city":"Halifax", + "zip_number":"6324729" + }, + { + "country":"CA", + "city":"Mississauga", + "zip_number":"6075357" + }, + { + "country":"CA", + "city":"Montreal", + "zip_number":"6077243" + }, + { + "country":"CA", + "city":"Ottawa", + "zip_number":"6094817" + }, + { + "country":"CA", + "city":"Quebec City", + "zip_number":"6325494" + }, + { + "country":"CA", + "city":"Regina", + "zip_number":"6119109" + }, + { + "country":"CA", + "city":"Saskatoon", + "zip_number":"6141256" + }, + { + "country":"CA", + "city":"St. John's", + "zip_number":"05" + }, + { + "country":"CA", + "city":"Toronto", + "zip_number":"6167865" + }, + { + "country":"CA", + "city":"Vancouver", + "zip_number":"6173331" + }, + { + "country":"CA", + "city":"Victoria", + "zip_number":"6174041" + }, + { + "country":"CA", + "city":"Winnipeg", + "zip_number":"6183235" + }, + { + "country":"CD", + "city":"Kinshasa", + "zip_number":"2314302" + }, + { + "country":"CD", + "city":"Lubumbashi", + "zip_number":"922704" + }, + { + "country":"CF", + "city":"Bangui", + "zip_number":"2389853" + }, + { + "country":"CG", + "city":"Brazzaville", + "zip_number":"2260535" + }, + { + "country":"CH", + "city":"Bern", + "zip_number":"2661552" + }, + { + "country":"CH", + "city":"Geneva", + "zip_number":"2660646" + }, + { + "country":"CH", + "city":"Zurich", + "zip_number":"2657896" + }, + { + "country":"CI", + "city":"Abidjan", + "zip_number":"2293538" + }, + { + "country":"CI", + "city":"Yamoussoukro", + "zip_number":"2279755" + }, + { + "country":"CK", + "city":"Avarua", + "zip_number":"4035715" + }, + { + "country":"CL", + "city":"Santiago", + "zip_number":"3871336" + }, + { + "country":"CM", + "city":"Douala", + "zip_number":"2232593" + }, + { + "country":"CM", + "city":"Yaounde", + "zip_number":"2220957" + }, + { + "country":"CN", + "city":"Beijing", + "zip_number":"1816670" + }, + { + "country":"CN", + "city":"Chengdu", + "zip_number":"1815286" + }, + { + "country":"CN", + "city":"Chongqing", + "zip_number":"1814906" + }, + { + "country":"CN", + "city":"Guangzhou", + "zip_number":"1809858" + }, + { + "country":"CN", + "city":"Harbin", + "zip_number":"2037013" + }, + { + "country":"CN", + "city":"Kaifeng", + "zip_number":"1804879" + }, + { + "country":"CN", + "city":"Lanzhou", + "zip_number":"1804430" + }, + { + "country":"CN", + "city":"Nanchong", + "zip_number":"1800146" + }, + { + "country":"CN", + "city":"Nanjing", + "zip_number":"1799962" + }, + { + "country":"CN", + "city":"Puyang", + "zip_number":"1798422" + }, + { + "country":"CN", + "city":"Shanghai", + "zip_number":"1796236" + }, + { + "country":"CN", + "city":"Shenyang", + "zip_number":"2034937" + }, + { + "country":"CN", + "city":"Shenzhen", + "zip_number":"1795565" + }, + { + "country":"CN", + "city":"Shiyan", + "zip_number":"1794903" + }, + { + "country":"CN", + "city":"Tai'an", + "zip_number":"1793724" + }, + { + "country":"CN", + "city":"Tianjin", + "zip_number":"1792947" + }, + { + "country":"CN", + "city":"Wuhan", + "zip_number":"1791247" + }, + { + "country":"CN", + "city":"Xi'an", + "zip_number":"1790630" + }, + { + "country":"CN", + "city":"Yueyang", + "zip_number":"1927639" + }, + { + "country":"CN", + "city":"Zhumadian", + "zip_number":"1783873" + }, + { + "country":"CO", + "city":"Barranquilla", + "zip_number":"3689147" + }, + { + "country":"CO", + "city":"Bogota", + "zip_number":"3688689" + }, + { + "country":"CO", + "city":"Cali", + "zip_number":"3687925" + }, + { + "country":"CO", + "city":"Medellin", + "zip_number":"3674962" + }, + { + "country":"CR", + "city":"San José", + "zip_number":"3621849" + }, + { + "country":"CU", + "city":"Havana", + "zip_number":"3553478" + }, + { + "country":"CV", + "city":"Praia", + "zip_number":"3374333" + }, + { + "country":"CW", + "city":"Willemstad", + "zip_number":"3513090" + }, + { + "country":"CY", + "city":"Nicosia", + "zip_number":"146268" + }, + { + "country":"CZ", + "city":"Prague", + "zip_number":"3067696" + }, + { + "country":"DE", + "city":"Berlin", + "zip_number":"2950159" + }, + { + "country":"DE", + "city":"Hamburg", + "zip_number":"2911298" + }, + { + "country":"DE", + "city":"Munich", + "zip_number":"2867714" + }, + { + "country":"DK", + "city":"Copenhagen", + "zip_number":"2618425" + }, + { + "country":"DM", + "city":"Roseau", + "zip_number":"3575635" + }, + { + "country":"DO", + "city":"Santiago de los Caballeros", + "zip_number":"3492914" + }, + { + "country":"DO", + "city":"Santo Domingo", + "zip_number":"3492908" + }, + { + "country":"DZ", + "city":"Algiers", + "zip_number":"2507480" + }, + { + "country":"EC", + "city":"Guayaquil", + "zip_number":"3657509" + }, + { + "country":"EC", + "city":"Quito", + "zip_number":"3652462" + }, + { + "country":"EE", + "city":"Tallinn", + "zip_number":"588409" + }, + { + "country":"EG", + "city":"Al Jizah", + "zip_number":"360995" + }, + { + "country":"EG", + "city":"Alexandria", + "zip_number":"361058" + }, + { + "country":"EG", + "city":"Cairo", + "zip_number":"360630" + }, + { + "country":"ER", + "city":"Asmara", + "zip_number":"343300" + }, + { + "country":"ES", + "city":"Barcelona", + "zip_number":"3128760" + }, + { + "country":"ES", + "city":"Madrid", + "zip_number":"3117735" + }, + { + "country":"ET", + "city":"Addis Ababa", + "zip_number":"344979" + }, + { + "country":"FI", + "city":"Helsinki", + "zip_number":"658225" + }, + { + "country":"FJ", + "city":"Suva", + "zip_number":"2198148" + }, + { + "country":"FK", + "city":"Stanley", + "zip_number":"3426691" + }, + { + "country":"FO", + "city":"Tórshavn", + "zip_number":"2611396" + }, + { + "country":"FR", + "city":"Marseilles", + "zip_number":"2995469" + }, + { + "country":"FR", + "city":"Paris", + "zip_number":"2988507" + }, + { + "country":"GA", + "city":"Libreville", + "zip_number":"2399697" + }, + { + "country":"GB", + "city":"Belfast", + "zip_number":"2655984" + }, + { + "country":"GB", + "city":"Birmingham", + "zip_number":"2655603" + }, + { + "country":"GB", + "city":"Bristol", + "zip_number":"2654675" + }, + { + "country":"GB", + "city":"Cardiff", + "zip_number":"2653822" + }, + { + "country":"GB", + "city":"Edinburgh", + "zip_number":"2650225" + }, + { + "country":"GB", + "city":"Glasgow", + "zip_number":"2648579" + }, + { + "country":"GB", + "city":"Leeds", + "zip_number":"2644688" + }, + { + "country":"GB", + "city":"Liverpool", + "zip_number":"2644210" + }, + { + "country":"GB", + "city":"London", + "zip_number":"2643743" + }, + { + "country":"GB", + "city":"Manchester", + "zip_number":"2643123" + }, + { + "country":"GB", + "city":"Sheffield", + "zip_number":"2638077" + }, + { + "country":"GE", + "city":"Tbilisi", + "zip_number":"611717" + }, + { + "country":"GH", + "city":"Accra", + "zip_number":"2306104" + }, + { + "country":"GH", + "city":"Kumasi", + "zip_number":"2298890" + }, + { + "country":"GI", + "city":"Gibraltar", + "zip_number":"2411585" + }, + { + "country":"GL", + "city":"Nuuk", + "zip_number":"3421319" + }, + { + "country":"GM", + "city":"Banjul", + "zip_number":"2413876" + }, + { + "country":"GN", + "city":"Camayenne", + "zip_number":"2422488" + }, + { + "country":"GN", + "city":"Conakry", + "zip_number":"2422465" + }, + { + "country":"GQ", + "city":"Malabo", + "zip_number":"2309527" + }, + { + "country":"GR", + "city":"Athens", + "zip_number":"264371" + }, + { + "country":"GT", + "city":"Guatemala City", + "zip_number":"3598132" + }, + { + "country":"GW", + "city":"Bissau", + "zip_number":"2374775" + }, + { + "country":"GY", + "city":"Georgetown", + "zip_number":"3378644" + }, + { + "country":"HK", + "city":"Hong Kong", + "zip_number":"1819729" + }, + { + "country":"HN", + "city":"Tegucigalpa", + "zip_number":"3600949" + }, + { + "country":"HR", + "city":"Zagreb", + "zip_number":"3186886" + }, + { + "country":"HT", + "city":"Port", + "zip_number":"au" + }, + { + "country":"HU", + "city":"Budapest", + "zip_number":"3054643" + }, + { + "country":"ID", + "city":"Bandung", + "zip_number":"1650357" + }, + { + "country":"ID", + "city":"Bekasi", + "zip_number":"1649378" + }, + { + "country":"ID", + "city":"Depok", + "zip_number":"1645518" + }, + { + "country":"ID", + "city":"Jakarta", + "zip_number":"1642911" + }, + { + "country":"ID", + "city":"Makassar", + "zip_number":"1622786" + }, + { + "country":"ID", + "city":"Medan", + "zip_number":"1214520" + }, + { + "country":"ID", + "city":"Palembang", + "zip_number":"1633070" + }, + { + "country":"ID", + "city":"Semarang", + "zip_number":"1627896" + }, + { + "country":"ID", + "city":"South Tangerang", + "zip_number":"8581443" + }, + { + "country":"ID", + "city":"Surabaya", + "zip_number":"1625822" + }, + { + "country":"ID", + "city":"Tangerang", + "zip_number":"1625084" + }, + { + "country":"IE", + "city":"Dublin", + "zip_number":"2964574" + }, + { + "country":"IL", + "city":"Ashdod", + "zip_number":"295629" + }, + { + "country":"IL", + "city":"Ashkelon", + "zip_number":"295620" + }, + { + "country":"IL", + "city":"Bat Yam", + "zip_number":"295548" + }, + { + "country":"IL", + "city":"Be'er Sheva", + "zip_number":"295530" + }, + { + "country":"IL", + "city":"Beit Shemesh", + "zip_number":"295432" + }, + { + "country":"IL", + "city":"Bnei Brak", + "zip_number":"295514" + }, + { + "country":"IL", + "city":"Eilat", + "zip_number":"295277" + }, + { + "country":"IL", + "city":"Hadera", + "zip_number":"294946" + }, + { + "country":"IL", + "city":"Haifa", + "zip_number":"294801" + }, + { + "country":"IL", + "city":"Herzliya", + "zip_number":"294778" + }, + { + "country":"IL", + "city":"Holon", + "zip_number":"294751" + }, + { + "country":"IL", + "city":"Jerusalem", + "zip_number":"281184" + }, + { + "country":"IL", + "city":"Kfar Saba", + "zip_number":"294514" + }, + { + "country":"IL", + "city":"Lod", + "zip_number":"294421" + }, + { + "country":"IL", + "city":"Modiin", + "zip_number":"282926" + }, + { + "country":"IL", + "city":"Nazareth", + "zip_number":"294098" + }, + { + "country":"IL", + "city":"Netanya", + "zip_number":"294071" + }, + { + "country":"IL", + "city":"Petach Tikvah", + "zip_number":"293918" + }, + { + "country":"IL", + "city":"Ra'anana", + "zip_number":"293807" + }, + { + "country":"IL", + "city":"Ramat Gan", + "zip_number":"293788" + }, + { + "country":"IL", + "city":"Ramla", + "zip_number":"293768" + }, + { + "country":"IL", + "city":"Rishon LeZion", + "zip_number":"293703" + }, + { + "country":"IL", + "city":"Tel Aviv", + "zip_number":"293397" + }, + { + "country":"IL", + "city":"Tiberias", + "zip_number":"293322" + }, + { + "country":"IM", + "city":"Douglas", + "zip_number":"3042237" + }, + { + "country":"IN", + "city":"Ahmadabad", + "zip_number":"1279233" + }, + { + "country":"IN", + "city":"Bangalore", + "zip_number":"1277333" + }, + { + "country":"IN", + "city":"Bombay", + "zip_number":"1275339" + }, + { + "country":"IN", + "city":"Calcutta", + "zip_number":"1275004" + }, + { + "country":"IN", + "city":"Chennai", + "zip_number":"1264527" + }, + { + "country":"IN", + "city":"Cochin", + "zip_number":"1273874" + }, + { + "country":"IN", + "city":"Hyderabad", + "zip_number":"1269843" + }, + { + "country":"IN", + "city":"Jaipur", + "zip_number":"1269515" + }, + { + "country":"IN", + "city":"Kanpur", + "zip_number":"1267995" + }, + { + "country":"IN", + "city":"New Delhi", + "zip_number":"1261481" + }, + { + "country":"IN", + "city":"Pune", + "zip_number":"1259229" + }, + { + "country":"IN", + "city":"Surat", + "zip_number":"1255364" + }, + { + "country":"IQ", + "city":"Baghdad", + "zip_number":"98182" + }, + { + "country":"IR", + "city":"Tehran", + "zip_number":"112931" + }, + { + "country":"IS", + "city":"Reykjavík", + "zip_number":"3413829" + }, + { + "country":"IT", + "city":"Milano", + "zip_number":"3173435" + }, + { + "country":"IT", + "city":"Rome", + "zip_number":"3169070" + }, + { + "country":"JM", + "city":"Kingston", + "zip_number":"3489854" + }, + { + "country":"JO", + "city":"Amman", + "zip_number":"250441" + }, + { + "country":"JP", + "city":"Kobe", + "zip_number":"shi" + }, + { + "country":"JP", + "city":"Kyoto", + "zip_number":"1857910" + }, + { + "country":"JP", + "city":"Nagoya", + "zip_number":"shi" + }, + { + "country":"JP", + "city":"Osaka", + "zip_number":"shi" + }, + { + "country":"JP", + "city":"Sapporo", + "zip_number":"2128295" + }, + { + "country":"JP", + "city":"Tokyo", + "zip_number":"1850147" + }, + { + "country":"KE", + "city":"Nairobi", + "zip_number":"184745" + }, + { + "country":"KG", + "city":"Bishkek", + "zip_number":"1528675" + }, + { + "country":"KH", + "city":"Phnom Penh", + "zip_number":"1821306" + }, + { + "country":"KM", + "city":"Moroni", + "zip_number":"921772" + }, + { + "country":"KN", + "city":"Basseterre", + "zip_number":"3575551" + }, + { + "country":"KP", + "city":"Pyongyang", + "zip_number":"1871859" + }, + { + "country":"KR", + "city":"Busan", + "zip_number":"1838524" + }, + { + "country":"KR", + "city":"Seoul", + "zip_number":"1835848" + }, + { + "country":"KW", + "city":"Kuwait", + "zip_number":"285787" + }, + { + "country":"KY", + "city":"George Town", + "zip_number":"3580661" + }, + { + "country":"KZ", + "city":"Almaty", + "zip_number":"1526384" + }, + { + "country":"KZ", + "city":"Astana", + "zip_number":"1526273" + }, + { + "country":"LA", + "city":"Vientiane", + "zip_number":"1651944" + }, + { + "country":"LB", + "city":"Beirut", + "zip_number":"276781" + }, + { + "country":"LC", + "city":"Castries", + "zip_number":"3576812" + }, + { + "country":"LI", + "city":"Vaduz", + "zip_number":"3042030" + }, + { + "country":"LR", + "city":"Monrovia", + "zip_number":"2274895" + }, + { + "country":"LS", + "city":"Maseru", + "zip_number":"932505" + }, + { + "country":"LT", + "city":"Vilnius", + "zip_number":"593116" + }, + { + "country":"LU", + "city":"Luxemburg", + "zip_number":"2960316" + }, + { + "country":"LV", + "city":"Riga", + "zip_number":"456172" + }, + { + "country":"LY", + "city":"Tripoli", + "zip_number":"2210247" + }, + { + "country":"MA", + "city":"Casablanca", + "zip_number":"2553604" + }, + { + "country":"MA", + "city":"Rabat", + "zip_number":"2538475" + }, + { + "country":"MD", + "city":"Chisinau", + "zip_number":"618426" + }, + { + "country":"ME", + "city":"Podgorica", + "zip_number":"3193044" + }, + { + "country":"MG", + "city":"Antananarivo", + "zip_number":"1070940" + }, + { + "country":"MK", + "city":"Skopje", + "zip_number":"785842" + }, + { + "country":"ML", + "city":"Bamako", + "zip_number":"2460596" + }, + { + "country":"MM", + "city":"Mandalay", + "zip_number":"1311874" + }, + { + "country":"MM", + "city":"Rangoon", + "zip_number":"1298824" + }, + { + "country":"MN", + "city":"Ulaanbaatar", + "zip_number":"2028462" + }, + { + "country":"MP", + "city":"Saipan", + "zip_number":"7828758" + }, + { + "country":"MR", + "city":"Nouakchott", + "zip_number":"2377450" + }, + { + "country":"MS", + "city":"Plymouth", + "zip_number":"3578069" + }, + { + "country":"MT", + "city":"Valletta", + "zip_number":"2562305" + }, + { + "country":"MU", + "city":"Port Louis", + "zip_number":"934154" + }, + { + "country":"MW", + "city":"Lilongwe", + "zip_number":"927967" + }, + { + "country":"MX", + "city":"Cancun", + "zip_number":"3531673" + }, + { + "country":"MX", + "city":"Guadalajara", + "zip_number":"4005539" + }, + { + "country":"MX", + "city":"Iztapalapa", + "zip_number":"3526683" + }, + { + "country":"MX", + "city":"Mazatlan", + "zip_number":"3996322" + }, + { + "country":"MX", + "city":"Mexico City", + "zip_number":"3530597" + }, + { + "country":"MX", + "city":"Monterrey", + "zip_number":"3995465" + }, + { + "country":"MX", + "city":"Puerto Vallarta", + "zip_number":"3991328" + }, + { + "country":"MX", + "city":"Tijuana", + "zip_number":"3981609" + }, + { + "country":"MY", + "city":"Kota Bharu", + "zip_number":"1736376" + }, + { + "country":"MY", + "city":"Kuala Lumpur", + "zip_number":"1735161" + }, + { + "country":"MZ", + "city":"Maputo", + "zip_number":"1040652" + }, + { + "country":"NA", + "city":"Windhoek", + "zip_number":"3352136" + }, + { + "country":"NC", + "city":"Nouméa", + "zip_number":"2139521" + }, + { + "country":"NE", + "city":"Niamey", + "zip_number":"2440485" + }, + { + "country":"NG", + "city":"Abuja", + "zip_number":"2352778" + }, + { + "country":"NG", + "city":"Lagos", + "zip_number":"2332459" + }, + { + "country":"NI", + "city":"Managua", + "zip_number":"3617763" + }, + { + "country":"NL", + "city":"Amsterdam", + "zip_number":"2759794" + }, + { + "country":"NO", + "city":"Oslo", + "zip_number":"3143244" + }, + { + "country":"NP", + "city":"Kathmandu", + "zip_number":"1283240" + }, + { + "country":"NU", + "city":"Alofi", + "zip_number":"4036284" + }, + { + "country":"NZ", + "city":"Auckland", + "zip_number":"2193733" + }, + { + "country":"NZ", + "city":"Christchurch", + "zip_number":"2192362" + }, + { + "country":"NZ", + "city":"Wellington", + "zip_number":"2179537" + }, + { + "country":"OM", + "city":"Muscat", + "zip_number":"287286" + }, + { + "country":"PA", + "city":"Panama City", + "zip_number":"3703443" + }, + { + "country":"PE", + "city":"Lima", + "zip_number":"3936456" + }, + { + "country":"PF", + "city":"Papeete", + "zip_number":"4033936" + }, + { + "country":"PG", + "city":"Port Moresby", + "zip_number":"2088122" + }, + { + "country":"PH", + "city":"Manila", + "zip_number":"1701668" + }, + { + "country":"PK", + "city":"Islamabad", + "zip_number":"1176615" + }, + { + "country":"PK", + "city":"Karachi", + "zip_number":"1174872" + }, + { + "country":"PL", + "city":"Warsaw", + "zip_number":"756135" + }, + { + "country":"PR", + "city":"San Juan", + "zip_number":"4568127" + }, + { + "country":"PT", + "city":"Lisbon", + "zip_number":"2267057" + }, + { + "country":"PY", + "city":"Asuncion", + "zip_number":"3439389" + }, + { + "country":"QA", + "city":"Doha", + "zip_number":"290030" + }, + { + "country":"RO", + "city":"Bucharest", + "zip_number":"683506" + }, + { + "country":"RS", + "city":"Belgrade", + "zip_number":"792680" + }, + { + "country":"RU", + "city":"Moscow", + "zip_number":"524901" + }, + { + "country":"RU", + "city":"Novosibirsk", + "zip_number":"1496747" + }, + { + "country":"RU", + "city":"Saint Petersburg", + "zip_number":"498817" + }, + { + "country":"RU", + "city":"Yekaterinburg", + "zip_number":"1486209" + }, + { + "country":"RW", + "city":"Kigali", + "zip_number":"202061" + }, + { + "country":"SA", + "city":"Jeddah", + "zip_number":"105343" + }, + { + "country":"SA", + "city":"Mecca", + "zip_number":"104515" + }, + { + "country":"SA", + "city":"Medina", + "zip_number":"109223" + }, + { + "country":"SA", + "city":"Riyadh", + "zip_number":"108410" + }, + { + "country":"SB", + "city":"Honiara", + "zip_number":"2108502" + }, + { + "country":"SC", + "city":"Victoria", + "zip_number":"241131" + }, + { + "country":"SD", + "city":"Khartoum", + "zip_number":"379252" + }, + { + "country":"SD", + "city":"Omdurman", + "zip_number":"365137" + }, + { + "country":"SE", + "city":"Stockholm", + "zip_number":"2673730" + }, + { + "country":"SG", + "city":"Singapore", + "zip_number":"1880252" + }, + { + "country":"SH", + "city":"Jamestown", + "zip_number":"3370903" + }, + { + "country":"SI", + "city":"Ljubljana", + "zip_number":"3196359" + }, + { + "country":"SK", + "city":"Bratislava", + "zip_number":"3060972" + }, + { + "country":"SL", + "city":"Freetown", + "zip_number":"2408770" + }, + { + "country":"SN", + "city":"Dakar", + "zip_number":"2253354" + }, + { + "country":"SO", + "city":"Mogadishu", + "zip_number":"53654" + }, + { + "country":"SR", + "city":"Paramaribo", + "zip_number":"3383330" + }, + { + "country":"ST", + "city":"São Tomé", + "zip_number":"2410763" + }, + { + "country":"SV", + "city":"San Salvador", + "zip_number":"3583361" + }, + { + "country":"SY", + "city":"Aleppo", + "zip_number":"170063" + }, + { + "country":"SY", + "city":"Damascus", + "zip_number":"170654" + }, + { + "country":"SZ", + "city":"Mbabane", + "zip_number":"934985" + }, + { + "country":"TC", + "city":"Cockburn Town", + "zip_number":"3576994" + }, + { + "country":"TD", + "city":"Ndjamena", + "zip_number":"2427123" + }, + { + "country":"TG", + "city":"Lomé", + "zip_number":"2365267" + }, + { + "country":"TH", + "city":"Bangkok", + "zip_number":"1609350" + }, + { + "country":"TJ", + "city":"Dushanbe", + "zip_number":"1221874" + }, + { + "country":"TM", + "city":"Ashgabat", + "zip_number":"162183" + }, + { + "country":"TN", + "city":"Tunis", + "zip_number":"2464470" + }, + { + "country":"TR", + "city":"Adana", + "zip_number":"325363" + }, + { + "country":"TR", + "city":"Ankara", + "zip_number":"323786" + }, + { + "country":"TR", + "city":"Bursa", + "zip_number":"750269" + }, + { + "country":"TR", + "city":"Istanbul", + "zip_number":"745044" + }, + { + "country":"TR", + "city":"Izmir", + "zip_number":"311046" + }, + { + "country":"TV", + "city":"Funafuti", + "zip_number":"2110394" + }, + { + "country":"TW", + "city":"Kaohsiung", + "zip_number":"1673820" + }, + { + "country":"TW", + "city":"Taipei", + "zip_number":"1668341" + }, + { + "country":"TZ", + "city":"Dar es Salaam", + "zip_number":"160263" + }, + { + "country":"TZ", + "city":"Dodoma", + "zip_number":"160196" + }, + { + "country":"UA", + "city":"Kharkiv", + "zip_number":"706483" + }, + { + "country":"UA", + "city":"Kiev", + "zip_number":"703448" + }, + { + "country":"UG", + "city":"Kampala", + "zip_number":"232422" + }, + { + "country":"US", + "city":"Atlanta", + "zip_number":"GA" + }, + { + "country":"US", + "city":"Austin", + "zip_number":"TX" + }, + { + "country":"US", + "city":"Baltimore", + "zip_number":"MD" + }, + { + "country":"US", + "city":"Boston", + "zip_number":"MA" + }, + { + "country":"US", + "city":"Buffalo", + "zip_number":"NY" + }, + { + "country":"US", + "city":"Chicago", + "zip_number":"IL" + }, + { + "country":"US", + "city":"Cincinnati", + "zip_number":"OH" + }, + { + "country":"US", + "city":"Cleveland", + "zip_number":"OH" + }, + { + "country":"US", + "city":"Columbus", + "zip_number":"OH" + }, + { + "country":"US", + "city":"Dallas", + "zip_number":"TX" + }, + { + "country":"US", + "city":"Denver", + "zip_number":"CO" + }, + { + "country":"US", + "city":"Detroit", + "zip_number":"MI" + }, + { + "country":"US", + "city":"Hartford", + "zip_number":"CT" + }, + { + "country":"US", + "city":"Honolulu", + "zip_number":"HI" + }, + { + "country":"US", + "city":"Houston", + "zip_number":"TX" + }, + { + "country":"US", + "city":"Lakewood", + "zip_number":"NJ" + }, + { + "country":"US", + "city":"Las Vegas", + "zip_number":"NV" + }, + { + "country":"US", + "city":"Livingston", + "zip_number":"NY" + }, + { + "country":"US", + "city":"Los Angeles", + "zip_number":"CA" + }, + { + "country":"US", + "city":"Memphis", + "zip_number":"TN" + }, + { + "country":"US", + "city":"Miami", + "zip_number":"FL" + }, + { + "country":"US", + "city":"Milwaukee", + "zip_number":"WI" + }, + { + "country":"US", + "city":"Monsey", + "zip_number":"NY" + }, + { + "country":"US", + "city":"New Haven", + "zip_number":"CT" + }, + { + "country":"US", + "city":"New York", + "zip_number":"NY" + }, + { + "country":"US", + "city":"Omaha", + "zip_number":"NE" + }, + { + "country":"US", + "city":"Orlando", + "zip_number":"FL" + }, + { + "country":"US", + "city":"Passaic", + "zip_number":"NJ" + }, + { + "country":"US", + "city":"Philadelphia", + "zip_number":"PA" + }, + { + "country":"US", + "city":"Phoenix", + "zip_number":"AZ" + }, + { + "country":"US", + "city":"Pittsburgh", + "zip_number":"PA" + }, + { + "country":"US", + "city":"Portland", + "zip_number":"OR" + }, + { + "country":"US", + "city":"Providence", + "zip_number":"RI" + }, + { + "country":"US", + "city":"Richmond", + "zip_number":"VA" + }, + { + "country":"US", + "city":"Rochester", + "zip_number":"NY" + }, + { + "country":"US", + "city":"Saint Louis", + "zip_number":"MO" + }, + { + "country":"US", + "city":"Saint Paul", + "zip_number":"MN" + }, + { + "country":"US", + "city":"San Diego", + "zip_number":"CA" + }, + { + "country":"US", + "city":"San Francisco", + "zip_number":"CA" + }, + { + "country":"US", + "city":"Seattle", + "zip_number":"WA" + }, + { + "country":"US", + "city":"Silver Spring", + "zip_number":"MD" + }, + { + "country":"US", + "city":"Teaneck", + "zip_number":"NJ" + }, + { + "country":"US", + "city":"Washington", + "zip_number":"DC" + }, + { + "country":"US", + "city":"White Plains", + "zip_number":"NY" + }, + { + "country":"UY", + "city":"Montevideo", + "zip_number":"3441575" + }, + { + "country":"UZ", + "city":"Tashkent", + "zip_number":"1512569" + }, + { + "country":"VC", + "city":"Kingstown", + "zip_number":"3577887" + }, + { + "country":"VE", + "city":"Caracas", + "zip_number":"3646738" + }, + { + "country":"VE", + "city":"Maracaibo", + "zip_number":"3633009" + }, + { + "country":"VE", + "city":"Maracay", + "zip_number":"3632998" + }, + { + "country":"VE", + "city":"Valencia", + "zip_number":"3625549" + }, + { + "country":"VG", + "city":"Road Town", + "zip_number":"3577430" + }, + { + "country":"VN", + "city":"Hanoi", + "zip_number":"1581130" + }, + { + "country":"VN", + "city":"Ho Chi Minh City", + "zip_number":"1566083" + }, + { + "country":"WS", + "city":"Apia", + "zip_number":"4035413" + }, + { + "country":"YE", + "city":"Sanaa", + "zip_number":"71137" + }, + { + "country":"YT", + "city":"Mamoudzou", + "zip_number":"921815" + }, + { + "country":"ZA", + "city":"Cape Town", + "zip_number":"3369157" + }, + { + "country":"ZA", + "city":"Durban", + "zip_number":"1007311" + }, + { + "country":"ZA", + "city":"Johannesburg", + "zip_number":"993800" + }, + { + "country":"ZA", + "city":"Pretoria", + "zip_number":"964137" + }, + { + "country":"ZM", + "city":"Lusaka", + "zip_number":"909137" + }, + { + "country":"ZW", + "city":"Harare", + "zip_number":"890299" + } +] \ No newline at end of file diff --git a/app/routers/dayview.py b/app/routers/dayview.py index 2894eaa2..4f372ac1 100644 --- a/app/routers/dayview.py +++ b/app/routers/dayview.py @@ -2,11 +2,12 @@ from datetime import datetime, timedelta from typing import Dict, Iterator, Optional, Tuple, Union +import geocoder from fastapi import APIRouter, Depends, HTTPException, Request from app.database.models import Event, Task, User from app.dependencies import get_db, templates -from app.internal import international_days, zodiac +from app.internal import international_days, shabbat, zodiac from app.internal.security.dependencies import current_user from app.routers.user import get_all_user_events @@ -211,11 +212,15 @@ async def dayview( current_time_with_attrs = CurrentTimeAttributes(date=day) inter_day = international_days.get_international_day_per_day(session, day) tasks = ( - session.query(Task) - .filter(Task.owner_id == user.user_id) - .filter(Task.date == day.date()) - .order_by(Task.time) + session.query(Task).filter(Task.owner_id == user.user_id).filter( + Task.date == day.date()).order_by(Task.time) ) + location_by_ip = geocoder.ip('me') + if location_by_ip: + shabbat_obj = shabbat.get_shabbat_if_date_friday( + day.date(), + location_by_ip, + ) month = day.strftime("%B").upper() return templates.TemplateResponse( "calendar_day_view.html", @@ -231,5 +236,7 @@ async def dayview( "view": view, "current_time": current_time_with_attrs, "tasks": tasks, + "user_location": location_by_ip, + "shabbat": shabbat_obj, }, ) diff --git a/app/static/dayview.css b/app/static/dayview.css index 3cde2aa8..8f88b223 100644 --- a/app/static/dayview.css +++ b/app/static/dayview.css @@ -286,4 +286,43 @@ body { background-color: var(--primary); color: white; box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); -} \ No newline at end of file +} +.new-location { + position: absolute; + right: 1.2rem; + top: 15rem; + padding-right: var(--space_xs); + padding-left: var(--space_xs); + padding-bottom: var(--space_xxs); + border: solid 0.1px var(--primary); + background-color: var(--surface-variant); + box-shadow: 1px 1px 2px #999; + line-height: 1.2; + height: 2rem; + width: 5.2rem; + align-items: center; + justify-content: center; + font-weight: bold; + font-size: 0.65rem; + color: green; +} + +.shabbat { + position: absolute; + right: 1.2rem; + top: 17rem; + padding-right: var(--space_xs); + padding-left: var(--space_xs); + padding-bottom: var(--space_xxs); + border: solid 0.1px var(--primary); + background-color: var(--surface-variant); + box-shadow: 1px 1px 2px #999; + line-height: 1.2; + height: 6rem; + width: 5.2rem; + align-items: center; + justify-content: center; + font-weight: bold; + font-size: 0.65rem; + color: red; +} diff --git a/app/templates/calendar_day_view.html b/app/templates/calendar_day_view.html index 272e3558..794116b2 100644 --- a/app/templates/calendar_day_view.html +++ b/app/templates/calendar_day_view.html @@ -24,6 +24,18 @@ {% else %} {{day}} / {{month}} {% endif %} + {% if user_location %} +
+ {{user_location}} +
+ {% endif %} + {% if shabbat %} +
+ {{ gettext(" Candle lighting time:") }}
+ {{ gettext(" Shabbat entry: %(enter)s", enter=shabbat['start_hour']) }}
+ {{ gettext(" Shabbat exit: %(exit)s", exit=shabbat['end_hour']) }} +
+ {% endif %}
{% for event in all_day_events %} diff --git a/requirements.txt b/requirements.txt index 9612912e..3b9129d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,6 +33,7 @@ coverage==5.3.1 curio==1.4 databases==0.4.1 dateparser==1.0.0 +django-os-geocoder==0.1.6 distlib==0.3.1 dnspython==2.1.0 email-validator==1.1.2 @@ -46,6 +47,7 @@ fastapi-mail==0.3.3.1 filelock==3.0.12 flake8==3.8.4 frozendict==1.2 +geocoder==1.38.1 geographiclib==1.50 geopy==2.1.0 google-api-core==1.25.0 @@ -159,4 +161,4 @@ word-forms==2.1.0 wsproto==1.0.0 yapf==0.30.0 yarl==1.6.3 -zipp==3.4.0 +zipp==3.4.0 \ No newline at end of file diff --git a/tests/test_shabbat.py b/tests/test_shabbat.py new file mode 100644 index 00000000..c8ad80e9 --- /dev/null +++ b/tests/test_shabbat.py @@ -0,0 +1,65 @@ +import json +from datetime import date + +import geocoder +import pytest + +from app.internal import shabbat + +FAKE_SHABBAT_DATA = { + "items": + [ + {"title": "Fast begins"}, + {"title": "Ta'anit Esther"}, + {"title": "Fast ends"}, + {"title": "Erev Purim"}, + {"title": "Purim"}, + { + "title": "Candle lighting: 17:15", + "date": "2021-02-26T17:15:00+02:00", + "category": "candles", + "title_orig": "Candle lighting", + "hebrew": "הדלקת נרות", + }, + {"title": "Parashat Tetzaveh"}, + { + "title": "Havdalah: 18:11", + "date": "2021-02-27T18:11:00+02:00", + "category": "havdalah", + "title_orig": "Havdalah", + "hebrew": "הבדלה", + }, + ] +} +FRIDAY = date(2021, 2, 26) +BAD_DAY = date(2021, 2, 27) + + +@pytest.mark.asyncio +async def test_return_if_date_is_friday(httpx_mock): + location_by_ip = geocoder.ip('me') + test_data = json.dumps(FAKE_SHABBAT_DATA) + httpx_mock.add_response(method="GET", json=test_data) + result = await shabbat.get_shabbat_if_date_friday(FRIDAY, location_by_ip) + assert result + + +@pytest.mark.asyncio +async def test_return_if_date_is_not_friday(httpx_mock): + location_by_ip = geocoder.ip('me') + test_data = json.dumps(FAKE_SHABBAT_DATA) + httpx_mock.add_response(method="GET", json=test_data) + result = await shabbat.get_shabbat_if_date_friday(BAD_DAY, location_by_ip) + assert result is None + + +def test_return_shabbat_times(): + result = shabbat.return_shabbat_times(FAKE_SHABBAT_DATA) + assert result["start_hour"] == "17:15" + assert result["end_hour"] == "18:11" + + +def test_return_zip_code_of_user_location(): + location_by_ip = geocoder.ip('me') + result = shabbat.return_zip_code_of_user_location(location_by_ip) + assert result