Beispiel #1
0
def notify_user(user, data_message=None):
    from pyfcm import FCMNotification
    push_service = FCMNotification(
        api_key="AAAA19KbT04:APA91bFroH6rGfC-eywj49abV2OZMyVj-St1v7eOhwSADPKG0Fon8tfwVxMRYlcIYOkHf8xEqnqlpbIuqU7W3oF9" +
                "LhxiDjLlKw4BoXaIknY75t1rBDZTP5OzY6iYz_MJF2FGAadmoqT_")

    registration_id = user.prof.token
    if registration_id is not None:
        push_service.single_device_data_message(registration_id=registration_id,
                                                data_message=data_message)
Beispiel #2
0
def send_fcm_notification(title="", body="", data=None, users=None):
    """
    sends fcm notification to a single or multiple user device
    :param title: title of the notification message
    :param body: body of the notification
    :param data: any data to be sent
    :param users: list of user ids
    :return: True/False
    """
    if users:
        push_service = FCMNotification(api_key=settings.FCM_API_KEY)
        try:
            if data:
                if isinstance(users, list):
                    registration_ids = [
                        devices.registration_id
                        for devices in UserDevice.objects.filter(
                            used_id__in=users)
                    ]
                    push_service.multiple_devices_data_message(
                        registration_ids=registration_ids, data_message=data)
                else:
                    registration_id = UserDevice.objects.get(
                        user_id=users).registration_id
                    push_service.single_device_data_message(
                        registration_id=registration_id, data_message=data)
            else:
                if isinstance(users, list):
                    registration_ids = [
                        devices.registration_id
                        for devices in UserDevice.objects.filter(
                            user_id__in=users)
                    ]
                    push_service.notify_multiple_devices(
                        registration_ids=registration_ids,
                        message_title=title,
                        message_body=body)
                else:
                    registration_id = UserDevice.objects.get(
                        user_id=users).registration_id
                    push_service.notify_single_device(
                        registration_id=registration_id,
                        message_title=title,
                        message_body=body)
            return True
        except:
            return False
    else:
        return False
Beispiel #3
0
def push_notify_annoc(token, mt, text):
    global mykey
    push_service = FCMNotification(api_key=mykey)

    data_message = {"mod": "1", "title": mt, "text": text}

    result = push_service.single_device_data_message(registration_id=token,
                                                     data_message=data_message)
Beispiel #4
0
 def sendDataMessage(self,
                     device_id="",
                     message_body=None,
                     api_key=os.getenv('firebase_landslide_serverkey')):
     push_service = FCMNotification(api_key=api_key)
     registration_id = device_id
     datamsg = {"data": message_body}
     if registration_id == "" or registration_id is None:
         return 0
     else:
         result = push_service.single_device_data_message(
             registration_id=registration_id, data_message=datamsg)
         return result['success']
Beispiel #5
0
def send_notify_single(device_id, title, message, action, payload):
    push_service = FCMNotification(api_key=API_KEY)
    registration_id = device_id
    data_message = {
        "title": title,
        "message": message,
        "action": action,
        "payload": payload
    }
    # To a single device
    result = push_service.single_device_data_message(
        registration_id=registration_id, data_message=data_message)

    print(result)
    return result
Beispiel #6
0
class SMS:
    def __init__(self):
        self.client = FCMNotification(settings.FIREBASE_TOKEN)

    def wait_for_status_change(self, schedule) -> bool:
        start_time = datetime.now()
        timeout = settings.SMS_TIMEOUT
        status_changed = False

        while not status_changed:
            schedule.refresh_from_db()
            if schedule.notification_status != 0:
                status_changed = True
            if (datetime.now() - start_time).total_seconds() >= timeout:
                schedule.notification_status = 3
                schedule.save()
                raise SMSTimeoutError('Tempo excedido')
            sleep(1)

        return True

    def send_message(self, schedule_id):
        from app.schedule.models import Schedule
        schedule = Schedule.objects.get(pk=schedule_id)
        phone = f'+55{schedule.patient.phone}'
        try:
            self.client.single_device_data_message(
                schedule.dentist.device_token,
                data_message={
                    'sendTo': phone,
                    'content': schedule.get_message(),
                    'scheduleId': schedule.id
                })
            return True
        except:
            return False
Beispiel #7
0
def push_notify_to_one(registration_id, mt, mb, code, userID, roomType):
    global mykey
    push_service = FCMNotification(api_key=mykey)

    data_message = {
        "mod": "0",
        "msgTitle": mt,
        "msgText": mb,
        "code": code,
        "userID": userID,
        "roomType": roomType
    }

    result = push_service.single_device_data_message(
        registration_id=registration_id, data_message=data_message)
Beispiel #8
0
def fcm_send_single_device_data_message(registration_id,
                                        condition=None,
                                        collapse_key=None,
                                        delay_while_idle=False,
                                        time_to_live=None,
                                        restricted_package_name=None,
                                        low_priority=False,
                                        dry_run=False,
                                        data_message=None,
                                        content_available=None,
                                        api_key=None,
                                        timeout=5,
                                        json_encoder=None):
    """
    Send push message to a single device
    All arguments correspond to that defined in pyfcm/fcm.py.

    Args:
        registration_id (str): FCM device registration IDs.
        data_message (dict): Data message payload to send alone or with the
            notification message

    Keyword Args:
        collapse_key (str, optional): Identifier for a group of messages
            that can be collapsed so that only the last message gets sent
            when delivery can be resumed. Defaults to ``None``.
        delay_while_idle (bool, optional): If ``True`` indicates that the
            message should not be sent until the device becomes active.
        time_to_live (int, optional): How long (in seconds) the message
            should be kept in FCM storage if the device is offline. The
            maximum time to live supported is 4 weeks. Defaults to ``None``
            which uses the FCM default of 4 weeks.
        low_priority (boolean, optional): Whether to send notification with
            the low priority flag. Defaults to ``False``.
        restricted_package_name (str, optional): Package name of the
            application where the registration IDs must match in order to
            receive the message. Defaults to ``None``.
        dry_run (bool, optional): If ``True`` no message will be sent but
            request will be tested.
        timeout (int, optional): set time limit for the request
    Returns:
        :dict:`multicast_id(long), success(int), failure(int),
            canonical_ids(int), results(list)`:
        Response from FCM server.

    Raises:
        AuthenticationError: If :attr:`api_key` is not set or provided or there
            is an error authenticating the sender.
        FCMServerError: Internal server error or timeout error on Firebase cloud
            messaging server
        InvalidDataError: Invalid data provided
        InternalPackageError: Mostly from changes in the response of FCM,
            contact the project owner to resolve the issue
    """
    push_service = FCMNotification(
        api_key=SETTINGS.get("FCM_SERVER_KEY") if api_key is None else api_key,
        json_encoder=json_encoder,
    )
    return push_service.single_device_data_message(
        registration_id=registration_id,
        condition=condition,
        collapse_key=collapse_key,
        delay_while_idle=delay_while_idle,
        time_to_live=time_to_live,
        restricted_package_name=restricted_package_name,
        low_priority=low_priority,
        dry_run=dry_run,
        data_message=data_message,
        content_available=content_available,
        timeout=timeout)
Beispiel #9
0
# FCM Notification을 위한 모듈. 원랜 firebase 측으로 HTTP request를 전송해야 하지만
# 어떤 개발자가 이게 불편하다고 느꼈는지 pyfcm을 만들어 두었다

fcm = FCMNotification(api_key='')
# FCM 서버 키를 통해 객체를 만들자

# 클라이언트 하나에 보내기, 여러 곳에 보내기, topic subscriber에 보내기가 대표적인 메소드다
fcm.notify_single_device(registration_id='',
                         message_title='제목이야',
                         message_body='body다')

fcm.notify_multiple_devices(registration_ids=['', ''],
                            message_title='제-목',
                            message_body='배고파')
# 여러 클라이언트에 보내는 메소드. registration_ids 파라미터로 리스트 형태의 클라이언트 키들을 전달한다

fcm.notify_topic_subscribers(topic_name='',
                             message_title='제-목',
                             message_body='body!')
# 특정 topic을 subscribe하고 있는 디바이스에 보내기

# fcm 푸쉬 메시지는 data message를 전송할 수 있다. 일반적으로 JSON이며 pyfcm 측에서는 data_message 인자로 딕셔너리를 전달하면 알아서 직렬화 처리해준다

data = {'key1': 123, 'key2': 1234}
fcm.notify_single_device(registration_id='', data_message=data)
# notify_*** 메소드에도 data_message 파라미터가 있지만, pyfcm 측에서 data messaging을 위한 메소드를 만들어 두었다

fcm.single_device_data_message(registration_id='', data_message=data)
fcm.multiple_devices_data_message(registration_ids=['', '', ''],
                                  data_message=data)
class Helpers:
    def __init__(self, flask_app):
        self.logger = flask_app.logger
        apikey = "AAAAgOfyS6s:APA91bH0GGnd4Xvw_pWMDpGmsQrR79CU8_bOmDj2QsHyrpua89dwV_UUAcJNRELByd_uikq4Hd5oI-ik6uWoW9i4w3qgtdqqg8TYKwwhAg-HllaBKoIdAy9yF1tvIGaAUvXGLtdIzTqF"  # api key from FCM for the app
        self.push_service = FCMNotification(api_key=apikey)
        self.STATUS_YES = 'Y'
        self.STATUS_NO = 'N'
        self.all_days = [
            'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
            'Sunday'
        ]
        self.config = json.load(open(CONFIG_PATH))
        self.client_id = self.get_config('basic', 'client_id')

    def get_config(self, *args):
        ret = self.config
        for i in range(len(args)):
            ret = ret[args[i]]
        return ret

    def build_url(self, addr, *args):
        '''
    
        :param addr: Address
        :param args: list of components in the url. Will be appended with '/'
        :return:   returns the formatted url
        '''
        comp = ''

        for i in range(len(args) - 1):
            comp += args[i] + '/'
        comp += args[len(args) - 1]

        url = urllib.parse.urljoin("http://" + addr, comp)
        logger.debug('Built url : ', url)
        return url

    def get_request(self, url, data=None):
        '''
    
        :param url: url to send the get request
        :param params: params to append to the query
        :return: response from the server
        '''
        response = None

        try:
            self.logger.debug('GET request : %s', url)
            params = json.dumps(data)
            self.logger.debug(str(params))
            response = requests.get(url, params=params)

        except Exception as e:
            print(e)

        return response

    def query_installs(self, request, cur_session):
        '''
        
        queries Install table according to all ids supplied
        in request object
        :param request: current request context
        :param cur_session: current database session object
        :returns: List of matching entries if present, None otherwise
        '''
        u_id = self.read_user_id(request.args.get('u_id', None))
        i_id = request.args.get('i_id', None)
        p_id = request.args.get('p_id', None)

        return self.get_all_installs(cur_session, u_id, i_id, p_id)

    def get_all_installs(self, cur_session, u_id=None, i_id=None, p_id=None):
        if i_id is None and p_id is None and u_id is None:
            return None

        if i_id is not None:
            cur_installs = cur_session.query(Install).filter(
                Install.install_id == i_id).all()
        elif u_id is not None:
            cur_installs = cur_session.query(Install).filter(
                Install.user_id == u_id).all()
        else:
            cur_installs = cur_session.query(Install).filter(
                Install.push_id == p_id).all()

        if len(cur_installs) == 0:
            return None
        return cur_installs

    def get_all_medications(self,
                            cur_session,
                            m_id=None,
                            m_name=None,
                            u_id=None,
                            d_id=None):
        if m_id is None and u_id is None and d_id is None and m_name is None:
            return None

        if m_id is not None:
            cur_meds = cur_session.query(Medication).filter(
                Medication.med_id == m_id).all()
        elif u_id is not None:
            cur_meds = cur_session.query(Medication).filter(
                Medication.user_id == u_id).all()
        elif m_name is not None:
            cur_meds = cur_session.query(Medication).filter(
                Medication.med_name == m_name).all()
        else:
            cur_meds = cur_session.query(Medication).filter(
                Medication.dosage_id == d_id).all()

        if len(cur_meds) == 0:
            return None
        return cur_meds

    def keygen(self, cur_session, cur_table, table_attr):
        key = np.random.randint(0, 2**31)
        prev_entry = cur_session.query(cur_table).filter(
            table_attr == key).first()
        if prev_entry is not None:
            return self.keygen(cur_session, cur_table, table_attr)
        return key

    def stringify(self, lst):
        ret = ''
        for s in lst:
            if len(s) == 0:
                continue
            ret += ',' + s
        return ret[1:]

    def send_push_notification(self, reg_id_list, data_message=None):
        '''
        : param reg_id_list: list of registration ids
        : param data_message: optional payload with custom key-value pairs
        : returns: Sends out push notification to multiple devices.response data from pyFCM 
        '''
        if len(reg_id_list) == 0:
            self.logger.debug(
                'No registration ids to send push notification to')
            return
        if len(reg_id_list) == 1:
            self.logger.debug('Making call to FCM for single Data Message...')
            try:
                result = self.push_service.single_device_data_message(
                    registration_id=reg_id_list[0], data_message=data_message)
            except Exception as e:
                self.logger.debug(e)
                return None
        else:
            self.logger.debug(
                'Making call to FCM for multiple Data Messages...')
            try:
                result = self.push_service.multiple_devices_data_message(
                    registration_ids=reg_id_list, data_message=data_message)
            except Exception as e:
                self.logger.debug(e)
                return None

        return result

    # Is there a better way to do this?
    def get_clean_data_array(self, shape):

        #        ret = np.empty(shape, dtype=object)
        # This has problems : https://stackoverflow.com/questions/33983053/how-to-create-a-numpy-array-of-lists
        #        ret.fill([])
        '''
        IMPORTANT! The first element (index 0) will be None. Use lists starting from 1
        '''

        linear_size = 1
        for s in shape:
            linear_size *= s
        ret = np.empty((linear_size, ), dtype=object)
        for i, v in enumerate(ret):
            ret[i] = list([])
        # finally, reshape the matrix
        ret = ret.reshape(shape)
        return ret

    def read_user_id(self, u_id):
        if u_id is None or u_id == '':
            return ''

        algorithm = sha2()
        algorithm.update(u_id.encode())
        return algorithm.hexdigest().upper()

    def validate_intakes(self, med, dose, cur_session):
        # Oh boy...
        validation_date = parser.parse(med.validation_date)
        start_date = validation_date + timedelta(days=1)
        med.validation_date = (datetime.now() - timedelta(days=1)).isoformat()

        intakes = cur_session.query(Intake).filter(
            Intake.med_id == med.med_id).filter(
                Intake.planned_date > validation_date).all()
        ideal_intake_dates = self.get_ideal_intake_dates(dose, start_date)
        intake_dates_present = set(
            [parser.parse(x.planned_date) for x in intakes])
        missed_intake_dates = [
            x for x in ideal_intake_dates if x not in intake_dates_present
        ]

        missed_intakes = [
            Intake(med_id=med.med_id,
                   planned_date=x.isoformat(),
                   intake_status=3) for x in missed_intake_dates
        ]

        cur_session.add_all(missed_intakes)
        cur_session.commit()

    def get_ideal_intake_dates(self, dose, start_date):
        ideal_intakes = []

        def get_prev_dosage_date(days, cur_date):
            cur_day_idx = cur_date.weekday()
            prev_day_idx = -1
            for i in range(len(days) - 1, -1, -1):
                if days[i] < cur_day_idx:
                    prev_day_idx = i
                    break
            prev_day_delta = (cur_day_idx - days[prev_day_idx] + 7) % 7
            td = timedelta(days=prev_day_delta)
            return cur_date - td

        dosage_days = [self.all_days.index(x) for x in dose.get_days()]

        ideal_times = [
            get_prev_dosage_date(dosage_days, parser.parse(tim))
            for tim in dose.get_times()
        ]
        ideal_times.reverse()
        while ideal_times[0].date() >= start_date.date():
            ideal_intakes.extend(ideal_times)
            ideal_times = [
                get_prev_dosage_date(dosage_days, tim) for tim in ideal_times
            ]

        return reversed(ideal_intakes)

    def get_intake_status(self, planned_date, actual_date):
        p_date = parser.parse(planned_date)
        a_date = parser.parse(actual_date)

        delta = time.mktime(a_date.utctimetuple()) - time.mktime(
            p_date.utctimetuple())
        four_hours = 1000 * 60 * 60 * 4

        if delta < 0:
            return 1
        elif delta > four_hours:
            return 2

        return 0
Beispiel #11
0
def FCMSend(reg_id, data):
    server_key = 'AAAAbJRUy5U:APA91bHXw43Jlye_Cthdd_dXVnLLYE9oKNjFt-z8BpYeEPFIVCcP2P_tnsdTY8VooqJEL5rREMk0UWJ1B4W5Xy-dbaLKc88C_g88VAnYjjEjviDOOts7AJ0Lgp_lC_PTlQNh2_5qfwJJ'
    push_service = FCMNotification(api_key=server_key)

    return push_service.single_device_data_message(registration_id=reg_id, data_message=data)
Beispiel #12
0
class APICall:
    def __init__(self, app, request, requiredParams=[]):
        self._uid = None
        self._config = {}
        self.params = {}
        self._app = app
        self._request = request
        self._readConfigFile()
        self._enableLogging()
        self._pushService = FCMNotification(
            api_key=
            "AAAAJcqwb2M:APA91bFixpCKO1fE6kObLma1upi1RBPWHNMufAFhz2CzycG2oqfELoh7vLZ8ceGCpYxiDuClCnsD9eJp1BgMkl2FI97996JC4vAqZMuO_HF7VHBEYFIPUuhvlRQ2KuKlMsrSYwgdjZ1Y"
        )
        self._userColumns = [
            "deviceNotificationToken", "phoneNumber", "name", "email",
            "birthYear", "gender", "relationshipStatus", "thumbnail"
        ]
        self._maxFriends = 20
        if not self._getRequestParams(requiredParams):
            abort(400)
        if not self._connectDB():
            abort(500)
        self._checkAuth()

    def __del__(self):
        self._closeDB()

    def _readConfigFile(self):
        global _g_configFile
        try:
            with open(_g_configFile) as inpf:
                self._config = json.load(inpf)
        except Exception as e:
            self._app.logger.error(
                "Caught exception reading the config file '{}':  {}".format(
                    _g_configFile, e))
            abort(500)
        if ("logging" not in self._config or "database" not in self._config):
            self._app.logger.error(
                "Config file '{}' missing required section.".format(
                    _g_configFile))
            abort(500)

    def _enableLogging(self):
        if (("started" in self._config["logging"]
             and self._config["logging"]["started"]) or self._app.debug):
            return
        handler = FileHandler(self._config["logging"]["logfile"])
        handler.setFormatter(
            Formatter(
                '%(asctime)s %(levelname)s line=%(lineno)d - %(message)s'))
        handler.setLevel(self._config["logging"]["level"])
        self._app.logger.addHandler(handler)
        self._config["logging"]["started"] = True

    def _getRequestParams(self, requiredParams):
        requestParams = self._request.values if len(
            self._request.values) > 0 else self._request.get_json()
        for param in requiredParams:
            if param not in requestParams:
                return False
        for param in requestParams:
            self.params[param] = requestParams[param]
        return True

    def _encodeAuthToken(self):
        assert (self._uid)
        payload = {
            'iat':
            datetime.datetime.utcnow(),
            'exp':
            datetime.datetime.utcnow() + datetime.timedelta(
                days=self._config.get("auth-token-expiration-days", 365.25)),
            'sub':
            self._uid
        }
        return jwt.encode(payload,
                          self._config['token-key'],
                          algorithm='HS256')

    def _decodeAuthToken(self):
        authHeader = self._request.headers.get('Authorization')
        if not authHeader:
            abort(403)
        try:
            return jwt.decode(authHeader.split()[1],
                              self._config['token-key'])['sub']
        except jwt.ExpiredSignatureError:
            abort(401
                  )  # TODO:  response should use WWW-Authenticate header field
        except jwt.InvalidTokenError:
            abort(403)

    def _checkAuth(self):
        if "Authorization" not in self._request.headers:
            if self._request.path != "/userInfo":
                abort(401)
            # TAI:  check app key here?
            return
        self._uid = self._decodeAuthToken()
        if not self._uid or not (isinstance(self._uid, int)
                                 or self._uid.isdigit()):
            abort(401)

    def _connectDB(self):
        if "optionalSocket" in self._config["database"]:
            self._db = MySQLdb.connect(self._config["database"]["server"], \
                                       self._config["database"]["user"], \
                                       self._config["database"]["password"], \
                                       self._config["database"]["name"], \
                                       unix_socket=self._config["database"]["optionalSocket"])
        else:
            self._db = MySQLdb.connect(self._config["database"]["server"], \
                                       self._config["database"]["user"], \
                                       self._config["database"]["password"], \
                                       self._config["database"]["name"])
        return self._db is not None

    def _closeDB(self):
        if self._db:
            self._db.close()
            self._db = None

    def _pushNotification(self, deviceToken, payload):
        return self._pushService.single_device_data_message(
            registration_id=deviceToken, data_message=payload)

    def apihandler(fn):
        @wraps(fn)
        def decorated(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            except HTTPException as he:
                raise
            except Exception as e:
                args[0]._app.logger.error(
                    "Caught unexpected exception in api handler:  {}".format(
                        e))
                abort(500)
            finally:
                args[0]._closeDB()

        return decorated

    def _uidFromPhoneNum(self, phoneNum):
        cursor = self._db.cursor()
        cursor.execute("SELECT userId FROM User WHERE phoneNumber = %s",
                       (phoneNum, ))
        ur = cursor.fetchone()
        return ur[0] if ur else None

    @apihandler
    def getUserInfo(self):
        cursor = self._db.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute(
            "SELECT phoneNumber, name, email, birthYear, gender, relationshipStatus, thumbnail FROM User WHERE userId = %s",
            (self._uid, ))
        user = cursor.fetchone()
        if not user:
            abort(500)
        return make_response(jsonify(user), 200)

    @apihandler
    def setUserInfo(self):
        queryParams = []
        if self._uid:
            sql = "UPDATE User SET "
            for paramKey, paramVal in self.params.items():
                if paramKey in self._userColumns:
                    if queryParams:
                        sql += ", "
                    sql += "{} = %s".format(paramKey)
                    queryParams.append(paramVal)
            if not queryParams:
                abort(400)
            sql += " WHERE userId = %s"
            queryParams.append(self._uid)
            resultMsg = "successfully updated user info"
            self._app.logger.info("updating user {} with: {}".format(
                self._uid, queryParams))
            # TODO:  notify friends if thumbnail and/or phoneNumber changed
        else:
            requiredColumns = [
                "deviceNotificationToken", "phoneNumber", "name", "email"
            ]
            sql = "INSERT INTO User ({}) VALUES(%s{})".format(
                ",".join(self._userColumns),
                ", %s" * (len(self._userColumns) - 1))
            for col in self._userColumns:
                paramVal = self.params.get(col, None)
                if paramVal and col in requiredColumns:
                    requiredColumns.remove(col)
                queryParams.append(paramVal)
            if len(requiredColumns) > 0:
                self._app.logger.error(
                    "adding new user missing required field(s): {}".format(
                        requiredColumns))
                abort(400)
            if self._uidFromPhoneNum(self.params["phoneNumber"]):
                self._app.logger.warning(
                    "tried to add duplicate phoneNumber: {}".format(
                        self.params["phoneNumber"]))
                return make_response(jsonify({"message": "duplicate"}), 403)
            resultMsg = "successfully registered new user"
            self._app.logger.info(
                "adding new user with: {}".format(queryParams))
        cursor = self._db.cursor()
        try:
            cursor.execute(sql, queryParams)
            self._db.commit()
        except Exception as e:
            self._db.rollback()
            raise
        if self._uid:
            return make_response(
                jsonify({
                    "message": resultMsg,
                    "userId": self._uid
                }), 200)
        self._uid = self._uidFromPhoneNum(self.params["phoneNumber"])
        authToken = self._encodeAuthToken()
        return make_response(
            jsonify({
                "message": resultMsg,
                "userId": self._uid,
                "authToken": authToken.decode()
            }), 200)

    @apihandler
    def setStatus(self):
        free = self.params.get("free", False)
        if not free:
            abort(400)
        self._app.logger.info("user {} set free status".format(self._uid))
        insertCursor = self._db.cursor()
        try:
            nowstr = datetime.datetime.utcnow().strftime("%Y-%m-%d %H-%M-%S")
            insertCursor.execute(
                "INSERT INTO FreeLog (userId, timestamp) VALUES(%s, %s)",
                (self._uid, nowstr))
            self._db.commit()
        except Exception as e:
            self._db.rollback()
            raise
        friendCursor = self._db.cursor()
        sql = """SELECT FL.userId, U.deviceNotificationToken 
                 FROM FreeLog AS FL
                 INNER JOIN User AS U ON FL.userId = U.userId 
                 INNER JOIN Friend AS FF1 ON FL.userId = FF1.userId1 
                 INNER JOIN Friend AS FF2 ON FL.userId = FF2.userId2 
                 WHERE FF1.userId2 = %s AND FF2.userId1 = %s
                 AND FL.timestamp > %s"""
        timestr = (datetime.datetime.utcnow() +
                   datetime.timedelta(hours=-12)).strftime("%Y-%m-%d %H-%M-%S")
        friendCursor.execute(sql, (self._uid, self._uid, timestr))
        friends = []
        for friend in friendCursor.fetchall():
            friends.append(friend[0])
            self._pushNotification(friend[1], {
                "type": "friendFree",
                "userId": self._uid
            })
        return make_response(jsonify(friends), 200)

    def _friendCount(self):
        cursor = self._db.cursor()
        cursor.execute(
            "SELECT COUNT(*) FROM Friend WHERE userId1 = %s OR userId2= %s",
            (self._uid, self._uid))
        return cursor.fetchone()[0]

    def _removeFriend(self, friendUid, friendDeviceToken):
        nowstr = datetime.datetime.utcnow().strftime("%Y-%m-%d %H-%M-%S")
        cursor = self._db.cursor()
        try:
            cursor.execute(
                "UPDATE Friend SET timeEnded = %s WHERE timeEnded IS NULL AND ((userId1 = %s AND userId2 = %s) OR (userId1 = %s AND userId2 = %s))",
                (nowstr, self._uid, friendUid, friendUid, self._uid))
            self._db.commit()
            self._pushNotification(friendDeviceToken, {
                "type": "removeFriend",
                "userId": self._uid
            })
        except Exception as e:
            self._db.rollback()
            raise

    def _promoteFriendReq(self, friendUid):
        nowstr = datetime.datetime.utcnow().strftime("%Y-%m-%d %H-%M-%S")
        try:
            cursor = self._db.cursor()
            cursor.execute(
                "INSERT INTO Friend (userId1, userId2, timeStarted, timeEnded) VALUES(%s, %s, %s, %s)",
                (friendUid, self._uid, nowstr, None))
            cursor.execute(
                "DELETE FROM FriendRequest WHERE sourceUserId = %s AND targetUserId = %s",
                (friendUid, self._uid))
            self._db.commit()
        except Exception as e:
            self._db.rollback()
            raise

    def _addFriendReq(self, friendUid):
        cursor = self._db.cursor()
        cursor.execute(
            "SELECT * FROM FriendRequest WHERE sourceUserId = %s AND targetUserId = %s",
            (self._uid, friendUid))
        existingFriendReq = cursor.fetchone()
        nowstr = datetime.datetime.utcnow().strftime("%Y-%m-%d %H-%M-%S")
        if existingFriendReq:
            sql = "UPDATE FriendRequest SET timestamp = %s WHERE sourceUserId = %s AND targetUserId = %s"
            queryParams = (nowstr, self._uid, friendUid)
        else:
            sql = "INSERT INTO FriendRequest (sourceUserId, targetUserId, timestamp) VALUES(%s, %s, %s)"
            queryParams = (self._uid, friendUid, nowstr)
        cursor = self._db.cursor()
        try:
            cursor.execute(sql, queryParams)
            self._db.commit()
        except Exception as e:
            self._db.rollback()
            raise
        return (nowstr, existingFriendReq is None)

    def _notifyFriendRequest(self,
                             reqType,
                             friendDeviceToken,
                             requestedTimestamp,
                             repeat=False):
        cursor = self._db.cursor()
        cursor.execute(
            "SELECT phoneNumber, name, thumbnail FROM User WHERE userId = %s",
            (self._uid, ))
        user = cursor.fetchone()
        assert (user)
        if reqType == "friendRequest":
            msg = self.params.get(
                "message",
                "{} suggested you become Veni friends.".format(user[1]))
        else:
            msg = "{} accepted friend request.".format(user[1])
        friendPayload = {
            "type": reqType,
            "message": msg,
            "userId": self._uid,
            "phoneNumber": user[0],
            "name": user[1],
            "thumbnail": user[2]
        }
        if requestedTimestamp and isinstance(requestedTimestamp,
                                             datetime.datetime):
            friendPayload["requestedTimestamp"] = requestedTimestamp.strftime(
                "%Y-%m-%d %H-%M-S")
        else:
            friendPayload["requestedTimestamp"] = requestedTimestamp
        if repeat:
            friendPayload["repeat"] = True
        self._pushNotification(friendDeviceToken, friendPayload)

    # TODO:  auto-expiring friends requires push notification --> use a separate script
    @apihandler
    def addFriend(self):
        if self._friendCount() >= self._maxFriends:
            self._app.logger.info(
                "user {} tried to add too many friends".format(self._uid))
            abort(403)
        cursor = self._db.cursor()
        cursor.execute(
            "SELECT userId, deviceNotificationToken, phoneNumber, name, thumbnail FROM User WHERE phoneNumber = %s",
            (self.params["friendPhoneNumber"], ))
        friendUser = cursor.fetchone()
        if not friendUser:
            self._app.logger.warning(
                "user {} tried to add friend with unknown phoneNumber={}".
                format(self._uid, self.params["friendPhoneNumber"]))
            abort(404)
        if "remove" in self.params:
            self._app.logger.info("user {} removing friend {}".format(
                self._uid, friendUser[0]))
            self._removeFriend(friendUser[0], friendUser[1])
            return make_response(
                jsonify({"message": "successfully removed friend"}), 200)
        cursor = self._db.cursor()
        cursor.execute(
            "SELECT timestamp FROM FriendRequest WHERE sourceUserId = %s AND targetUserId = %s",
            (friendUser[0], self._uid))
        friendReq = cursor.fetchone()
        if friendReq:
            self._app.logger.info(
                "user {} accepted friend request from {}".format(
                    self._uid, friendUser[0]))
            self._promoteFriendReq(friendUser[0])
            self._notifyFriendRequest("friendAccepted", friendUser[1],
                                      friendReq[0])
            return make_response(
                jsonify({
                    "friend": {
                        "userId": friendUser[0],
                        "phoneNumber": friendUser[2],
                        "name": friendUser[3],
                        "thumbnail": friendUser[4]
                    }
                }), 200)
        else:
            self._app.logger.info("user {} friend request to {}".format(
                self._uid, friendUser[0]))
            requestedTimestamp, newReq = self._addFriendReq(friendUser[0])
            self._notifyFriendRequest("friendRequest", friendUser[1],
                                      requestedTimestamp, not newReq)
            return make_response(jsonify({"message": "sent friend request"}),
                                 202)

    @apihandler
    def contactFriend(self):
        self._app.logger.info("user {} contacting {}".format(
            self._uid, self.params["friendUserId"]))
        sql = "INSERT INTO ContactLog (sourceUserId, targetUserId, timestamp) VALUES (%s, %s, %s)"
        cursor = self._db.cursor()
        try:
            nowstr = datetime.datetime.utcnow().strftime("%Y-%m-%d %H-%M-%S")
            cursor.execute(sql,
                           (self._uid, self.params["friendUserId"], nowstr))
            self._db.commit()
        except Exception as e:
            self._db.rollback()
            raise
        return make_response(jsonify({"message": "contact attempt logged"}),
                             200)
Beispiel #13
0
def fcm_send_single_device_data_message(
        registration_id,
        condition=None,
        collapse_key=None,
        delay_while_idle=False,
        time_to_live=None,
        restricted_package_name=None,
        low_priority=False,
        dry_run=False,
        data_message=None,
        content_available=None,
        api_key=None,
        timeout=5,
        json_encoder=None):
    """
    Send push message to a single device
    All arguments correspond to that defined in pyfcm/fcm.py.

    Args:
        registration_id (str): FCM device registration IDs.
        data_message (dict): Data message payload to send alone or with the
            notification message

    Keyword Args:
        collapse_key (str, optional): Identifier for a group of messages
            that can be collapsed so that only the last message gets sent
            when delivery can be resumed. Defaults to ``None``.
        delay_while_idle (bool, optional): If ``True`` indicates that the
            message should not be sent until the device becomes active.
        time_to_live (int, optional): How long (in seconds) the message
            should be kept in FCM storage if the device is offline. The
            maximum time to live supported is 4 weeks. Defaults to ``None``
            which uses the FCM default of 4 weeks.
        low_priority (boolean, optional): Whether to send notification with
            the low priority flag. Defaults to ``False``.
        restricted_package_name (str, optional): Package name of the
            application where the registration IDs must match in order to
            receive the message. Defaults to ``None``.
        dry_run (bool, optional): If ``True`` no message will be sent but
            request will be tested.
        timeout (int, optional): set time limit for the request
    Returns:
        :dict:`multicast_id(long), success(int), failure(int),
            canonical_ids(int), results(list)`:
        Response from FCM server.

    Raises:
        AuthenticationError: If :attr:`api_key` is not set or provided or there
            is an error authenticating the sender.
        FCMServerError: Internal server error or timeout error on Firebase cloud
            messaging server
        InvalidDataError: Invalid data provided
        InternalPackageError: Mostly from changes in the response of FCM,
            contact the project owner to resolve the issue
    """
    push_service = FCMNotification(
        api_key=SETTINGS.get("FCM_SERVER_KEY") if api_key is None else api_key,
        json_encoder=json_encoder,
    )
    return push_service.single_device_data_message(
        registration_id=registration_id,
        condition=condition,
        collapse_key=collapse_key,
        delay_while_idle=delay_while_idle,
        time_to_live=time_to_live,
        restricted_package_name=restricted_package_name,
        low_priority=low_priority,
        dry_run=dry_run,
        data_message=data_message,
        content_available=content_available,
        timeout=timeout
    )
Beispiel #14
0
from pyfcm import FCMNotification

push_service = FCMNotification(
    api_key=
    "AAAAJTNYVvo:APA91bGMFBpgLfDzMqsji42jiudHeYP_xTvmO_-KGVMHJWp9lugsKIx2Eb5AM3peoguak_Y-EPbmqA86u13WvxiKqIBGkUtrbWjUgs7qBXjzPIu2s07IJ4-OIaPCWwLSupVd_t-acLVM"
)

# Your api-key can be gotten from:  https://console.firebase.google.com/project/<project-name>/settings/cloudmessaging

registration_id = "eOoXzmclKUEImb2nQLxlDj:APA91bEVJiCOh5vGYLRSD454AVE5bbk7eWRLjZp1uABHJ08wsxvcWB3Ws_eTldEcDS-CJSuWCWQvYplvDGup_BYrKoK6TF7rinKb1pksRfVwYFFExYONO6NK5uGro1mkoDqsQgUijwf-"
# payload = {"key":"Hi Mubashir, your customized news for today is ready"}
data_message = {
    "Nick": "Mario",
    "body": "great match!",
    "Room": "PortugalVSDenmark"
}
message_title = "Hello"
# result = push_service.notify_single_device(low_priority=False,registration_id=registration_id, message_title=message_title, data_message=message_body)
result = push_service.single_device_data_message(
    registration_id=registration_id,
    low_priority=False,
    data_message=data_message)
print(result)
Beispiel #15
0
                        logging.warn("%s: old notification not acknowledged, not re-sending", token)
                else:
                    logging.warn("iOS push not configured but iOS source requested")
            else:
                logging.warn("unknown source type %s" % source)
        else:
            if ios_onscreen:
                # rain has stopped and the notification is (possibly) still
                # displayed on the device.
                if source == "ios":
                    try:
                        apns.send_message(token, None, badge=0, content_available=True, extra={"clear_all": True})
                    except BadDeviceToken:
                        logging.warn("%s: silent iOS notification failed with BadDeviceToken, removing push client", token)
                        collection.remove(doc_id)
                    except Unregistered:
                        logging.warn("%s: silent iOS notification failed with Unregistered, removing push client", token)
                        collection.remove(doc_id)
                    else:
                        logging.warn("%s: sent silent notification" % token)
                        collection.update({"_id": doc_id}, { "$set": {"ios_onscreen": False} })
                elif source == "android":
                    result = fcm.single_device_data_message(registration_id=token, data_message={"clear_all": True})
                    logging.warn("%s: Delivered android data push with result=%s" % (token, result))
                    collection.update({"_id": doc_id}, { "$set": {"ios_onscreen": False} })
                else:
                    logging.error("%s: Unsupported source" % token)
        cnt = cnt + 1

    logging.warn("===> Processed %d total clients" % cnt)
Beispiel #16
0
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(Button, GPIO.IN)
GPIO.setup(LED_B, GPIO.OUT)
GPIO.output(LED_B, True)

################################
print 'Start'
print "ring the door bell"

while True:

    if GPIO.input(Button) == 0:
        door_bell_on = 1  #on
        result = push_service.single_device_data_message(
            registration_id=registration_id, data_message=data_message)
        print result
        os.system("mpg321 doorbell_sound.mp3"
                  )  #doorbell sound on & need doorbell_sound.mp3

        while True:
            try:
                print '0,1 Waiting for connection'
                #if 'yes' signal from android
                c_response, addr = server_socket.accept()
                print '...connected from :', addr
                confirm_data = ''
                confirm_data = c_response.recv(BUFSIZE)

            #except timeout:
            #   pass
Beispiel #17
0
def firebase(registrationId, dataMessage):
    push_service = FCMNotification(api_key="AIzaSyDNvYj9Is5cOkuH7XJCRqW1zcMxOx2azr0")
    registrationID = registrationId
    dataMessage = dataMessage

    result = push_service.single_device_data_message(registration_id=registrationID, data_message=dataMessage)
Beispiel #18
0
def single_device_data_message(registration_id: str, data_message: dict,
                               **kwargs):
    push_service = FCMNotification(api_key=settings.FCM_API_KEY)
    return push_service.single_device_data_message(
        registration_id=registration_id, data_message=data_message, **kwargs)