22import secrets
33import uuid
44import requests
5+ import firebase_admin
56from .models import db , SandboxToken , TimelinePin , UserTimeline
67from .utils import get_uid , api_error , pin_valid
78from .settings import config
1011
1112api = Blueprint ('api' , __name__ )
1213
14+ default_app = firebase_admin .initialize_app ()
15+
1316
1417def get_locker_info (user_token ):
1518 if user_token is None :
@@ -28,6 +31,27 @@ def get_locker_info(user_token):
2831 beeline .add_context_field ('app_uuid' , locker_info ['app_uuid' ])
2932 return locker_info ['user_id' ], locker_info ['app_uuid' ], f"uuid:{ locker_info ['app_uuid' ]} "
3033
34+ def send_fcm_message (user_id , data ):
35+ if user_id is None :
36+ raise ValueError
37+
38+ fcm_tokens = db .session .query (FcmToken ).filter_by (user_id = user_id )
39+ tokens = [fcm_token .token for fcm_token in fcm_tokens ]
40+
41+ message = firebase_admin .messaging .Message (
42+ data = data ,
43+ tokens = tokens ,
44+ )
45+
46+ response = firebase_admin .messaging .send_each_for_multicast (message )
47+
48+ if response .failure_count > 0 :
49+ responses = response .responses
50+ for idx , resp in enumerate (responses ):
51+ if not resp .success :
52+ FcmToken .query .filter_by (user_id = user_id , token = tokens [idx ]).delete ()
53+
54+
3155
3256@api .route ('/tokens/sandbox/<app_uuid>' )
3357def get_sandbox_token (app_uuid ):
@@ -68,6 +92,29 @@ def sync():
6892 }
6993 return jsonify (result )
7094
95+ @api .route ('/user/fcm_token/<token>' )
96+ def fcm_token ():
97+ user_id = get_uid ()
98+
99+ if request .method == 'PUT' :
100+ fcm_token_json = request .json
101+
102+ fcm_token = FcmToken .query .filter_by (user_id = user_id , token = token ).one_or_none ()
103+ if fcm_token is None :
104+ fcm_token = FcmToken .from_json (fcm_token_json , token , user_id )
105+ if fcm_token is None :
106+ return api_error (400 )
107+
108+ db .session .add (fcm_token )
109+ db .session .commit ()
110+
111+ elif request .method == 'DELETE' :
112+ fcm_token = FcmToken .query .filter_by (user_id = user_id , token = token ).first_or_404 ()
113+ fcm_token .delete ()
114+
115+ db .session .commit ()
116+ return 'OK'
117+
71118
72119@api .route ('/user/pins/<pin_id>' , methods = ['PUT' , 'DELETE' ])
73120def user_pin (pin_id ):
@@ -96,6 +143,8 @@ def user_pin(pin_id):
96143 db .session .add (pin )
97144 db .session .add (user_timeline )
98145 db .session .commit ()
146+
147+ send_fcm_message (user_id , user_timeline .to_json ())
99148 else : # update pin
100149 try :
101150 pin .update_from_json (pin_json )
@@ -111,6 +160,8 @@ def user_pin(pin_id):
111160 db .session .add (pin )
112161 db .session .add (user_timeline )
113162 db .session .commit ()
163+
164+ send_fcm_message (user_id , user_timeline .to_json ())
114165 except (KeyError , ValueError ):
115166 beeline .add_context_field ('timeline.failure.cause' , 'update_pin' )
116167 return api_error (400 )
@@ -127,6 +178,8 @@ def user_pin(pin_id):
127178 pin = pin )
128179 db .session .add (user_timeline )
129180 db .session .commit ()
181+
182+ send_fcm_message (user_id , user_timeline .to_json ())
130183 return 'OK'
131184
132185
0 commit comments