API amendments

This commit is contained in:
havlong
2023-01-13 12:12:49 +03:00
parent 65a78ebc1b
commit 3f8974f7e4
3 changed files with 41 additions and 27 deletions

View File

@@ -4,7 +4,11 @@ from typing import Optional, Any, Dict
from oauthlib.oauth2 import BackendApplicationClient from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session from requests_oauthlib import OAuth2Session
vue_apps_url: str = 'https://apps-vue.ru' from .models import PongModel, PostModel
oauth_url: str = 'https://sso.arbina.com/oauth'
vue_client_url: str = 'https://vue-client-api.arbina.com'
vue_interact_url: str = 'https://vue-app-interaction-api.arbina.com'
class ClientAPI: class ClientAPI:
@@ -12,12 +16,16 @@ class ClientAPI:
client_secret: str client_secret: str
token: Optional[Any] token: Optional[Any]
session: OAuth2Session session: OAuth2Session
endpoints: Dict[str, str] = {'access': '/auth', 'refresh': '/refresh', 'ping': '/ping'} endpoints: Dict[str, str] = {'create': '/api/pages/{page_id}/posts', 'remove': '/api/posts/{post_id}',
'ping': f'{vue_interact_url}/api/app/interactions/ping', 'token': f'{oauth_url}/token'}
def build_url(self, endpoint: str) -> str: def build_url(self, endpoint: str) -> str:
return f'{self.vue_apps_url}{self.endpoints[endpoint]}' if self.endpoints[endpoint].startswith('/'):
return f'{self.vue_apps_url}{self.endpoints[endpoint]}'
else:
return self.endpoints[endpoint]
def __init__(self, client_id: str, client_secret: str, vue_url: str = vue_apps_url): def __init__(self, client_id: str, client_secret: str, vue_url: str = vue_client_url):
""" """
Constructor of Vue Apps Client API Constructor of Vue Apps Client API
@@ -32,7 +40,7 @@ class ClientAPI:
self.client_secret = client_secret self.client_secret = client_secret
oauth = OAuth2Session(client=BackendApplicationClient(client_id=self.client_id)) oauth = OAuth2Session(client=BackendApplicationClient(client_id=self.client_id))
client_token = oauth.fetch_token(token_url=self.build_url('access'), client_id=self.client_id, client_token = oauth.fetch_token(token_url=self.build_url('token'), client_id=self.client_id,
client_secret=self.client_secret) client_secret=self.client_secret)
self.token = client_token self.token = client_token
@@ -49,7 +57,7 @@ class ClientAPI:
auto_refresh_info = {'client_id': self.client_id, 'client_secret': self.client_secret} auto_refresh_info = {'client_id': self.client_id, 'client_secret': self.client_secret}
self.session = OAuth2Session(token=self.token, client_id=self.client_id, self.session = OAuth2Session(token=self.token, client_id=self.client_id,
auto_refresh_url=self.build_url('refresh'), auto_refresh_url=self.build_url('token'),
auto_refresh_kwargs=auto_refresh_info, token_updater=save_token) auto_refresh_kwargs=auto_refresh_info, token_updater=save_token)
def acquire_token(self) -> Optional[Any]: def acquire_token(self) -> Optional[Any]:
@@ -59,6 +67,16 @@ class ClientAPI:
""" """
return self.session.access_token return self.session.access_token
def ping_server(self) -> Optional[PongModel]:
query_url = self.build_url('ping')
response = self.session.get(query_url)
if response.status_code != 200:
return None
model = response.json()
return PongModel(ping_ttl_seconds=model['ping_ttl_seconds'])
def refresh_token(self) -> bool: def refresh_token(self) -> bool:
""" """
Forces token to be refreshed and sends requests to /ping Forces token to be refreshed and sends requests to /ping
@@ -66,5 +84,9 @@ class ClientAPI:
""" """
self.token['expires_at'] = time() - 10 self.token['expires_at'] = time() - 10
self.session.token = self.token self.session.token = self.token
response = self.session.get(self.build_url('ping')) pong = self.ping_server()
return response.status_code == 200 return pong is not None
def create_post(self, post: PostModel) -> bool:
url = self.build_url('/create').format(page_id=post.page_uin)
return True

View File

@@ -1,15 +1,12 @@
from typing import Optional
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
class PingModel(BaseModel):
nickname: str = Field(title='Nickname', description="Vue App's nickname to use at service")
class PongModel(BaseModel): class PongModel(BaseModel):
message: str = Field(default='pong', title='Message', description='Message answered on pings') ping_ttl_seconds: int = Field(default='pong', title='Time To Live', description='Time To Live of the ping')
token: Optional[str] = Field(default=None, title='Token', description='Token for API to check')
class PostModel(BaseModel):
page_uin: str = Field(title='Page Author', description='ID of page that published the post')
class AutoModel(BaseModel): class AutoModel(BaseModel):

View File

@@ -3,7 +3,7 @@ from typing import Dict, List
from fastapi import FastAPI, Request, HTTPException, status from fastapi import FastAPI, Request, HTTPException, status
from .client import ClientAPI from .client import ClientAPI
from .models import AutoModel, InteractionModel, MentionModel, PageModel, PongModel, SuggestionsModel from .models import AutoModel, InteractionModel, MentionModel, PageModel, SuggestionsModel
from .server_utils.intents import Intent, PageApp, InlineQuery, PageMentions, Interactions from .server_utils.intents import Intent, PageApp, InlineQuery, PageMentions, Interactions
from .server_utils.security import SecurityHelper from .server_utils.security import SecurityHelper
@@ -31,24 +31,19 @@ def VueApp(client_api: ClientAPI,
if not security_helper.is_valid(timestamped_body=timestamp + body_to_verify, signature=signature): if not security_helper.is_valid(timestamped_body=timestamp + body_to_verify, signature=signature):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Verification of signature failed') raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Verification of signature failed')
@app.post(path='/ping', response_model=PongModel)
async def handle_ping(request: Request) -> PongModel:
await check_request(request)
return PongModel(message='pong', token=client_api.get_token())
if PageApp.intent_name in named_intents and isinstance(named_intents[PageApp.intent_name], PageApp): if PageApp.intent_name in named_intents and isinstance(named_intents[PageApp.intent_name], PageApp):
page_app_intent: PageApp = named_intents[PageApp.intent_name] page_app_intent: PageApp = named_intents[PageApp.intent_name]
start_handler = page_app_intent.added_page_handler start_handler = page_app_intent.added_page_handler
stop_handler = page_app_intent.removed_page_handler stop_handler = page_app_intent.removed_page_handler
@app.post(path='/start', status_code=status.HTTP_201_CREATED) @app.post(path='/interactions/pages/add', status_code=status.HTTP_202_ACCEPTED)
async def handle_integration(request: Request, model: PageModel): async def handle_integration(request: Request, model: PageModel):
await check_request(request) await check_request(request)
acknowledged = start_handler(model) acknowledged = start_handler(model)
if not acknowledged: if not acknowledged:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
@app.post(path='/stop', status_code=status.HTTP_204_NO_CONTENT) @app.post(path='/interactions/pages/remove', status_code=status.HTTP_202_ACCEPTED)
async def handle_disconnect(request: Request, model: PageModel): async def handle_disconnect(request: Request, model: PageModel):
await check_request(request) await check_request(request)
acknowledged = stop_handler(model) acknowledged = stop_handler(model)
@@ -59,7 +54,7 @@ def VueApp(client_api: ClientAPI,
inline_query_intent: InlineQuery = named_intents[InlineQuery.intent_name] inline_query_intent: InlineQuery = named_intents[InlineQuery.intent_name]
auto_handler = inline_query_intent.query_handler auto_handler = inline_query_intent.query_handler
@app.post(path='/auto', response_model=SuggestionsModel) @app.post(path='/interactions/inline-query', response_model=SuggestionsModel)
async def handle_autocomplete(request: Request, model: AutoModel) -> SuggestionsModel: async def handle_autocomplete(request: Request, model: AutoModel) -> SuggestionsModel:
await check_request(request) await check_request(request)
return auto_handler(model) return auto_handler(model)
@@ -68,7 +63,7 @@ def VueApp(client_api: ClientAPI,
page_mentions_intent: PageMentions = named_intents[PageMentions.intent_name] page_mentions_intent: PageMentions = named_intents[PageMentions.intent_name]
mentions_handler = page_mentions_intent.query_handler mentions_handler = page_mentions_intent.query_handler
@app.post(path='/mention', status_code=status.HTTP_202_ACCEPTED) @app.post(path='/interactions/pages/mention', status_code=status.HTTP_202_ACCEPTED)
async def handle_mentions(request: Request, model: MentionModel): async def handle_mentions(request: Request, model: MentionModel):
await check_request(request) await check_request(request)
acknowledged = mentions_handler(model) acknowledged = mentions_handler(model)
@@ -79,7 +74,7 @@ def VueApp(client_api: ClientAPI,
interactions_intent: Interactions = named_intents[Interactions.intent_name] interactions_intent: Interactions = named_intents[Interactions.intent_name]
interactions_handler = interactions_intent.query_handler interactions_handler = interactions_intent.query_handler
@app.post(path='/interact', status_code=status.HTTP_202_ACCEPTED) @app.post(path='/interactions/posts/interact', status_code=status.HTTP_202_ACCEPTED)
async def handle_interactions(request: Request, model: InteractionModel): async def handle_interactions(request: Request, model: InteractionModel):
await check_request(request) await check_request(request)
acknowledged = interactions_handler(model) acknowledged = interactions_handler(model)