fix
This commit is contained in:
commit
3b9e293083
0
__init__.py
Normal file
0
__init__.py
Normal file
0
config/__init__.py
Normal file
0
config/__init__.py
Normal file
34
config/config.py
Normal file
34
config/config.py
Normal file
@ -0,0 +1,34 @@
|
||||
from pydantic import BaseSettings
|
||||
from typing import Optional
|
||||
import os
|
||||
|
||||
from pydantic.fields import T
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
app_name: str = "Kingsome API"
|
||||
admin_email: str = "pengtao@kingsome.cn"
|
||||
items_per_user: int = 50
|
||||
is_debug: bool = True
|
||||
|
||||
MONGODB_URL = "mongodb://admin:kingsome@localhost"
|
||||
platform_url = "https://switch.jumpvg.com/jump/platform/order/v2?needCount=1&needFilter=1&version=3"
|
||||
all_game_url = "https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset={offset}&platForm={platformid}&systemList=&type=4&version=3"
|
||||
game_info_url = "https://switch.jumpvg.com/jump/game/detail?clickFrom=-1&id={gameid}&path=find_discount_gamedetail_switch&platform={platformid}&version=3"
|
||||
game_price_url = "https://switch.jumpvg.com/jump/price/getAllPriceByGame?id={gameid}&platform={platformid}"
|
||||
game_history_price_url = "https://switch.jumpvg.com/switch/getDiscount?appid={gameid}&platform={platformid}&zone=all"
|
||||
|
||||
x_token: str = "abc"
|
||||
|
||||
root_path_in_servers: Optional[bool] = False
|
||||
root_path: str = '/api/v1'
|
||||
|
||||
origins: list = [
|
||||
"http://*.kingsome.cn",
|
||||
"https://*.kingsome.cn",
|
||||
"http://localhost",
|
||||
"http://localhost:8080",
|
||||
]
|
||||
|
||||
|
||||
settings = Settings()
|
19
dependencies.py
Normal file
19
dependencies.py
Normal file
@ -0,0 +1,19 @@
|
||||
from fastapi import Header, HTTPException
|
||||
from pydantic.fields import T
|
||||
from starlette.requests import Request
|
||||
import pdb
|
||||
from config.config import settings
|
||||
|
||||
|
||||
async def get_token_header(request: Request, x_token: str = Header(...)):
|
||||
dd = settings.x_token
|
||||
if x_token == settings.x_token or x_token == dd:
|
||||
return True
|
||||
else:
|
||||
raise HTTPException(status_code=400, detail="X-Token header invalid")
|
||||
|
||||
|
||||
async def get_query_token(token: str):
|
||||
if token != "jessica":
|
||||
raise HTTPException(status_code=400,
|
||||
detail="No Jessica token provided")
|
0
interface/__init__.py
Normal file
0
interface/__init__.py
Normal file
31
interface/route.py
Normal file
31
interface/route.py
Normal file
@ -0,0 +1,31 @@
|
||||
from fastapi import APIRouter, BackgroundTasks, UploadFile, File, Form
|
||||
from typing import List
|
||||
from pydantic import BaseModel
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
from config.config import settings
|
||||
from scripts.sync_data import get_jump_data
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/sync_data")
|
||||
async def get_lists(request: Request) -> bool:
|
||||
db = request.app.state.mongo
|
||||
await get_jump_data(db)
|
||||
return True
|
||||
|
||||
|
||||
@router.get("/get_list")
|
||||
async def get_lists(request: Request, keys: str) -> JSONResponse:
|
||||
return {"url": keys}
|
||||
|
||||
|
||||
@router.get("/get_allprice")
|
||||
async def get_allprice(request: Request, keys: str) -> JSONResponse:
|
||||
return {"url": keys}
|
||||
|
||||
|
||||
@router.get("/get_gameinfo")
|
||||
async def get_gameinfo(request: Request, id: int) -> JSONResponse:
|
||||
return {"url": 'keys'}
|
BIN
jobs.sqlite
Normal file
BIN
jobs.sqlite
Normal file
Binary file not shown.
74
main.py
Normal file
74
main.py
Normal file
@ -0,0 +1,74 @@
|
||||
# uvicorn main:app --host=127.0.0.1 --port=8030 --reload
|
||||
from config.config import settings
|
||||
from fastapi import Depends, FastAPI, BackgroundTasks, Request
|
||||
from dependencies import get_token_header
|
||||
from interface import route as interface_route
|
||||
from scripts.common.mongodb import get_mongo
|
||||
from typing import Optional
|
||||
from scripts.logger import logger
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
# from apscheduler.events import EVENT_JOB_EXECUTED
|
||||
# from jobs.jobs import Schedule, job_execute
|
||||
tags_metadata = [
|
||||
# {
|
||||
# "name": "common",
|
||||
# "description": "Operations with users. The **login** logic is also here.",
|
||||
# },
|
||||
{
|
||||
"name": "common",
|
||||
"description": "Manage items. So _fancy_ they have their own docs.",
|
||||
"externalDocs": {
|
||||
"description": "Items external docs",
|
||||
"url": "https://fastapi.tiangolo.com/",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def create_app():
|
||||
application = FastAPI(dependencies=[Depends(get_token_header)],
|
||||
openapi_tags=tags_metadata)
|
||||
application.include_router(interface_route.router, prefix="/interface")
|
||||
return application
|
||||
|
||||
|
||||
app = create_app()
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.origins,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
app.state.mongo = await get_mongo()
|
||||
# Schedule.start()
|
||||
# Schedule.add_listener(job_execute, EVENT_JOB_EXECUTED)
|
||||
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
app.state.mongo.close()
|
||||
await app.state.mongo.wait_close()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root(request: Request):
|
||||
# db = request.app.state.mongo
|
||||
# keys = await db.get("online_devices")
|
||||
logger.info("starting!")
|
||||
|
||||
return {"message": "kajsk"}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import uvicorn
|
||||
uvicorn.run(app='main:app',
|
||||
host="0.0.0.0",
|
||||
port=8030,
|
||||
reload=True,
|
||||
debug=True)
|
89
readme.md
Normal file
89
readme.md
Normal file
@ -0,0 +1,89 @@
|
||||
### 项目简介:
|
||||
|
||||
从jump接口获得游戏列表及历史价格,信息,写入mongodb,提供接口返回数据
|
||||
|
||||
new project with fastapi
|
||||
|
||||
https://fastapi.tiangolo.com/zh/tutorial/bigger-applications/
|
||||
|
||||
采用异步方式实现,考虑并发性能
|
||||
|
||||
### 功能
|
||||
|
||||
获得平台信息:包含区域->国家
|
||||
|
||||
platform_url="https://switch.jumpvg.com/jump/platform/order/v2?needCount=1&needFilter=1&version=3"
|
||||
|
||||
获得游戏列表
|
||||
|
||||
https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=1&platForm=1&systemList=&type=4&version=3
|
||||
|
||||
获得游戏信息:
|
||||
|
||||
id=**oldGameId**
|
||||
|
||||
https://switch.jumpvg.com/jump/game/detail?clickFrom=-1&id=33113&path=find_discount_gamedetail_switch&platform=1&version=3
|
||||
|
||||
获得全区游戏价格:
|
||||
|
||||
https://switch.jumpvg.com/jump/price/getAllPriceByGame?id=20160&platform=1
|
||||
|
||||
获得历史价格:
|
||||
|
||||
https://switch.jumpvg.com/switch/getDiscount?appid=20160&platform=1&zone=all
|
||||
|
||||
获得史低信息:
|
||||
|
||||
程序判断 实时价格vs历史价格
|
||||
|
||||
|
||||
|
||||
> https://switch.jumpvg.com/jump/platform/order/v2?needCount=1&needFilter=1&version=3
|
||||
>
|
||||
> **platformAlias**
|
||||
>
|
||||
> 游戏列表
|
||||
> termsId 18:史低 17:全部 16:精选
|
||||
> https://switch.jumpvg.com/jump/discount/find4Discount/5/v2?offset=0&platform=1&session=1637580994841&size=10&termsId=18&version=3
|
||||
>
|
||||
>
|
||||
>
|
||||
> 游戏详情
|
||||
> https://switch.jumpvg.com/jump/game/detail?clickFrom=-1&id=20160&path=find_discount_gamedetail_switch&platform=1&version=3
|
||||
> 所有商店价格
|
||||
> https://switch.jumpvg.com/jump/price/getAllPriceByGame?id=20160&platform=1
|
||||
> 历史价格
|
||||
> 全区:all 港区:HK 欧区:UK 日区:JP 美区:US
|
||||
> https://switch.jumpvg.com/switch/getDiscount?appid=20160&platform=1&zone=all
|
||||
>
|
||||
> 查询游戏
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=%E6%8A%98%E6%89%A3%3B%E5%8C%85%E5%90%AB%E8%AF%95%E7%8E%A9&limit=10&offset=0&platForm=1&systemList=&type=5&version=3
|
||||
>
|
||||
> featureList 折扣 试玩等标签
|
||||
> categoryList 是 多个中文标签(urlencode) 以 %3B分割
|
||||
> limit 最大30, 一般10个
|
||||
>
|
||||
> switch 最新发布
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=0&platForm=1&systemList=&type=4&version=3
|
||||
> 正在流行
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=0&platForm=1&systemList=&type=3&version=3
|
||||
> 即将推出
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=0&platForm=1&systemList=&type=1&version=3
|
||||
> 热门新游
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=0&platForm=1&systemList=&type=2&version=3
|
||||
> 好评游戏
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=0&platForm=1&systemList=&type=6&version=3
|
||||
> 高分
|
||||
> https://switch.jumpvg.com/jump/findGame/list?categoryList=&featureList=&limit=10&offset=0&platForm=1&systemList=&type=5&version=3
|
||||
>
|
||||
>
|
||||
> 搜索游戏
|
||||
> 综合1 游戏3 评测2 用户4
|
||||
> platform: switch 1 steam 4 xbox 8 ps4 51
|
||||
> https://switch.jumpvg.com/jump/searchGame/list?limit=10&offset=0&searchName=%E6%9A%97%E9%BB%91&type=1&version=3
|
||||
> https://switch.jumpvg.com/jump/searchGame/list?limit=10&offset=0&searchName=%E6%9A%97%E9%BB%91&type=2&version=3
|
||||
> https://switch.jumpvg.com/jump/searchGame/list?limit=10&offset=0&platForm=&searchName=%E6%9A%97%E9%BB%91&type=3&version=3
|
||||
> https://switch.jumpvg.com/jump/searchGame/list?limit=10&offset=0&searchName=%E6%9A%97%E9%BB%91&type=4&version=3
|
||||
>
|
||||
>
|
||||
|
9
requirements.txt
Normal file
9
requirements.txt
Normal file
@ -0,0 +1,9 @@
|
||||
fastapi==0.65.2
|
||||
fastapi-mail==0.3.7
|
||||
GitPython==3.1.18
|
||||
pydantic==1.8.2
|
||||
uvicorn==0.15.0
|
||||
oss2==2.15.0
|
||||
motor==2.3.0
|
||||
mypy-extensions==0.4.3
|
||||
pymongo==3.11.1
|
0
scripts/__init__.py
Normal file
0
scripts/__init__.py
Normal file
0
scripts/common/__init__.py
Normal file
0
scripts/common/__init__.py
Normal file
88
scripts/common/mongodb.py
Normal file
88
scripts/common/mongodb.py
Normal file
@ -0,0 +1,88 @@
|
||||
# sample as https://github.com/mongodb-developer/mongodb-with-fastapi/blob/master/app.py
|
||||
import os
|
||||
from fastapi import FastAPI, Body, HTTPException, status
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from pydantic import BaseModel, Field, EmailStr
|
||||
from bson import ObjectId
|
||||
from typing import Optional, List
|
||||
import motor.motor_asyncio
|
||||
from pydantic.types import Json
|
||||
from config.config import settings
|
||||
|
||||
|
||||
async def get_mongo():
|
||||
client = motor.motor_asyncio.AsyncIOMotorClient(settings.MONGODB_URL)
|
||||
db = client.jump
|
||||
return db
|
||||
|
||||
|
||||
class PyObjectId(ObjectId):
|
||||
@classmethod
|
||||
def __get_validators__(cls):
|
||||
yield cls.validate
|
||||
|
||||
@classmethod
|
||||
def validate(cls, v):
|
||||
if not ObjectId.is_valid(v):
|
||||
raise ValueError("Invalid objectid")
|
||||
return ObjectId(v)
|
||||
|
||||
@classmethod
|
||||
def __modify_schema__(cls, field_schema):
|
||||
field_schema.update(type="string")
|
||||
|
||||
|
||||
class PlatformModel(BaseModel):
|
||||
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
|
||||
moduleId: int = Field(...)
|
||||
platformAlias: str = Field(...)
|
||||
iconRes: str = Field(...)
|
||||
gameNum: int = Field(...)
|
||||
filter: list = []
|
||||
countryFilter: bool
|
||||
|
||||
class Config:
|
||||
allow_population_by_field_name = True
|
||||
arbitrary_types_allowed = True
|
||||
json_encoders = {ObjectId: str}
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"moduleId":
|
||||
4,
|
||||
"platformAlias":
|
||||
'Steam',
|
||||
"iconRes":
|
||||
'http://switch-cdn.vgjump.com/869270335915032576',
|
||||
"gameNum":
|
||||
759,
|
||||
"filter": [{
|
||||
'termsId': 26,
|
||||
'terms': '精选'
|
||||
}, {
|
||||
'termsId': 27,
|
||||
'terms': '全部'
|
||||
}],
|
||||
"countryFilter":
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class UpdateStudentModel(BaseModel):
|
||||
name: Optional[str]
|
||||
email: Optional[EmailStr]
|
||||
course: Optional[str]
|
||||
gpa: Optional[float]
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
json_encoders = {ObjectId: str}
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"name": "Jane Doe",
|
||||
"email": "jdoe@example.com",
|
||||
"course": "Experiments, Science, and Fashion in Nanophotonics",
|
||||
"gpa": "3.0",
|
||||
}
|
||||
}
|
20
scripts/logger.py
Normal file
20
scripts/logger.py
Normal file
@ -0,0 +1,20 @@
|
||||
import os
|
||||
import time
|
||||
from loguru import logger
|
||||
|
||||
basedir = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# print(f"log basedir{basedir}") # /xxx/python_code/FastAdmin/backend/app
|
||||
# 定位到log日志文件
|
||||
log_path = os.path.join(basedir, 'logs')
|
||||
|
||||
if not os.path.exists(log_path):
|
||||
os.mkdir(log_path)
|
||||
|
||||
log_path_error = os.path.join(
|
||||
log_path, f'{time.strftime("%Y-%m-%d")}_error.log')
|
||||
|
||||
# 日志简单配置
|
||||
# 具体其他配置 可自行参考 https://github.com/Delgan/loguru
|
||||
logger.add(log_path_error, rotation="12:00", retention="5 days", enqueue=True)
|
64
scripts/sync_data.py
Normal file
64
scripts/sync_data.py
Normal file
@ -0,0 +1,64 @@
|
||||
import json
|
||||
from pydantic.fields import T
|
||||
from config.config import settings
|
||||
import requests
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from scripts.logger import logger
|
||||
|
||||
|
||||
async def get_jump_data(db) -> bool:
|
||||
platform_info = get_platform()
|
||||
platforms = platform_info.get('data')
|
||||
for platform in platforms:
|
||||
platformAlias = platform.get('platformAlias')
|
||||
existing_platform = await db["platform"].find_one(
|
||||
{"platformAlias": platformAlias})
|
||||
if not existing_platform:
|
||||
platform = jsonable_encoder(a)
|
||||
new_platform = await db["platform"].insert_one(platform)
|
||||
created_platform = await db["platform"].find_one(
|
||||
{"_id": new_platform.inserted_id})
|
||||
logger.info(f"insert platform {created_platform}")
|
||||
else:
|
||||
logger.info(f"key found with {existing_platform}")
|
||||
|
||||
# all_game = get_all_game()
|
||||
# #gameids = all_game['data']
|
||||
# print(all_game)
|
||||
return True
|
||||
# for gameid in gameids:
|
||||
# game_info = get_game_info(gameid)
|
||||
|
||||
|
||||
def get_platform() -> json:
|
||||
info = get_url_data(settings.platform_url)
|
||||
return info
|
||||
|
||||
|
||||
def get_all_game() -> json:
|
||||
info = get_url_data(settings.all_game_url)
|
||||
print(info)
|
||||
return None
|
||||
|
||||
|
||||
def get_game_info(gameid: int) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
def get_game_price(gameid: int) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
def get_history_price(gameid) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
def get_url_data(url: str, data=None) -> json:
|
||||
requests.adapters.DEFAULT_RETRIES = 5
|
||||
s = requests.session()
|
||||
s.keep_alive = False
|
||||
headers = {'Connection': 'close'}
|
||||
res = s.get(url=url, params=data, timeout=10, headers=headers).json()
|
||||
return res
|
30
test.py
Normal file
30
test.py
Normal file
@ -0,0 +1,30 @@
|
||||
from fastapi.testclient import TestClient
|
||||
from ops.common.common import EmailSchema
|
||||
from main import app
|
||||
import time
|
||||
import pdb
|
||||
import json
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_read_main():
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"message": "Hello Bigger Applications!"}
|
||||
|
||||
|
||||
def test_post_mail():
|
||||
data = {"email": ['pengtao@kingsome.cn'], "body": 'test message!',
|
||||
"subject": 'ttt {}'.format(time.time())}
|
||||
response = client.post("/common/email", headers={"X-Token": "fake-super-scret-token", "accept": "application/json", "Content-Type": "application/json"},
|
||||
data=json.dumps(data),
|
||||
)
|
||||
# data=EmailSchema(**data).json()
|
||||
print(response)
|
||||
# pdb.set_trace()
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"message": "email has been sent"}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_post_mail()
|
Loading…
x
Reference in New Issue
Block a user