garpix-notify


Namegarpix-notify JSON
Version 5.16.2 PyPI version JSON
download
home_pagehttps://github.com/garpixcms/garpix_notify
Summary
upload_time2023-09-19 09:56:18
maintainer
docs_urlNone
authorGarpix LTD
requires_python
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Garpix Notify


## Quickstart

Install with pip:

```bash
pip install garpix_notify
```

Add the `garpix_notify` and dependencies to your `INSTALLED_APPS`:

```python
# settings.py

INSTALLED_APPS = [
    # ...
    'fcm_django',
    'garpix_notify',
]

FCM_DJANGO_SETTINGS = {
        "APP_VERBOSE_NAME": "Firebase Cloud Messaging",
        "FCM_SERVER_KEY": "[your api key]",
        "ONE_DEVICE_PER_USER": False,
        "DELETE_INACTIVE_DEVICES": False,
}

```

Package not included migrations, set path to migration directory. Don't forget create this directory (`app/migrations/garpix_notify/`) and place empty `__init__.py`:

```
app/migrations/
app/migrations/__init__.py  # empty file
app/migrations/garpix_notify/__init__.py  # empty file
```

Add path to settings:

```python
# settings.py

MIGRATION_MODULES = {
    'garpix_notify': 'app.migrations.garpix_notify',
}
```

Add mixins to settings if you need to add extra functionality to Notify models:

```python

# settings.py
   
GARPIX_NOTIFY_MIXIN = 'app.models.notify_mixin.NotifyMixin'  
GARPIX_SYSTEM_NOTIFY_MIXIN = 'app.models.notify_mixin.SystemNotifyMixin'  
```

Create your custom user model and add `AUTH_USER_MODEL` to `app/settings.py`:

```
AUTH_USER_MODEL = 'user.User'

```

Run make migrations:

```bash
python manage.py makemigrations
```

Migrate:

```bash
python manage.py migrate
```

### Example

#### Step 1. Set notify types in `app/settings.py`, for example:

```python
REGISTRATION_EVENT = 1
FEEDBACK_EVENT = 2
EXAMPLE_EVENT_1 = 3
EXAMPLE_EVENT_2 = 4


NOTIFY_EVENTS = {
    REGISTRATION_EVENT: {
        'title': 'Register',
    },
    FEEDBACK_EVENT: {
        'title': 'Feeback',
    },
    EXAMPLE_EVENT_1: {
        'title': 'Example 1',
    },
    EXAMPLE_EVENT_2: {
        'title': 'Example 2',
    },
}

CHOICES_NOTIFY_EVENT = [(k, v['title']) for k, v in NOTIFY_EVENTS.items()]

```
#### Step 2. Import default settings in your ``app/settings.py``
```python

    from garpix_notify.settings import *
```
or copy from here if you want more customization
```python
# notify config

PERIODIC_SENDING = 60
EMAIL_MAX_DAY_LIMIT = 240
EMAIL_MAX_HOUR_LIMIT = 240
# SMS
SMS_URL_TYPE = 0
SMS_API_ID = 1234567890
SMS_LOGIN = ''
SMS_PASSWORD = ''
SMS_FROM = ''
# CALL
CALL_URL_TYPE = 0
CALL_API_ID = 1234567890
CALL_LOGIN = ''
CALL_PASSWORD = ''
# TELEGRAM
TELEGRAM_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'
TELEGRAM_BOT_NAME = 'MySuperBot'
TELEGRAM_WELCOME_TEXT = 'Hello'
TELEGRAM_HELP_TEXT = '/set !help for HELP'
TELEGRAM_BAD_COMMAND_TEXT = 'Incorrect command format'
TELEGRAM_SUCCESS_ADDED_TEXT = 'Success'
TELEGRAM_FAILED_ADDED_TEXT = 'Failed'
TELEGRAM_PARSE_MODE = None
TELEGRAM_DISABLE_NOTIFICATION = False
TELEGRAM_DISABLE_PAGE_PREVIEW = False
TELEGRAM_SENDING_WITHOUT_REPLY = False
TELEGRAM_TIMEOUT = None
# VIBER
VIBER_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'
VIBER_BOT_NAME = 'MySuperViberBot'
VIBER_WELCOME_TEXT = 'Hello'
VIBER_SUCCESS_ADDED_TEXT = 'Success'
VIBER_FAILED_ADDED_TEXT = 'Failed'
VIBER_TEXT_FOR_NEW_SUB = 'HI!'
# WHATSAPP
IS_WHATS_APP_ENABLED = True
WHATS_APP_AUTH_TOKEN = None
WHATS_APP_ACCOUNT_SID = None
WHATS_APP_NUMBER_SENDER = None
# SETTINGS
EMAIL_MALLING = 1
GARPIX_NOTIFY_MIXIN = 'garpix_notify.mixins.notify_mixin.NotifyMixin'
NOTIFY_USER_WANT_MESSAGE_CHECK = None
NOTIFY_CALL_CODE_CHECK = None
GARPIX_NOTIFY_CELERY_SETTINGS = 'app.celery.app'
DEFAULT_SYSTEM_NOTIFY_TYPE = 'system'


```
#### Step 3. Go to the admin panel and go to the "Notifications" section - "SMTP accounts"

Add an SMTP account to send Email notifications. These will be the senders of Email notifications.

#### Step 4. Also go to "Notifications" - "Categories"

Create a category that will be used to send emails. Usually one category is enough. The ability to enter several categories
is necessary to divide them into informational and marketing notifications.

#### Step 4. Go to "Notifications" - "Templates"

Create a template for a specific event (when you added them to `settings.py`).

#### Step 5. Call Notify.send()

In the code where it is necessary to work out sending a notification, we perform the following actions:

```python
from django.conf import settings
from garpix_notify.models import Notify

# Syntax
# Notify.send(<event>, <context>[, <user=None>, <email=None>, <phone=None>, <files=None>, <data_json=None>])
# That is, we specify the event ID as the first parameter,
# create variables for the template,
# third - the user to send it to (it is not necessary to specify his email, phone number, etc.,
# because this will be determined automatically depending on the type of template)   

# Example
user = request.user  # this will be the recipient of the notification.

Notify.send(settings.REGISTRATION_EVENT, {
    'confirmation_code': 'abcdef12345',
}, user=user)

# If we do not have a user in the system, but we need to send an email, we can do the following

Notify.send(settings.EXAMPLE_EVENT_1, {
    'confirmation_code': 'abcdef12345',
}, email='example@mail.ru')

# If you need more detailed time settings, add send_at

Notify.send(settings.EXAMPLE_EVENT_1, {
    'confirmation_code': 'abcdef12345',
}, email='example@mail.ru', send_at=(datetime.datetime.now() + datetime.timedelta(days=1)))

# If you need to send a code by phone call
Notify.send(settings.EXAMPLE_EVENT_2, phone='79998881122', context={})

# or if you need to get the code directly
Notify.call(phone=79998881122)


```

#### Mass email and sms mailing:
To perform a mass mailing, you need to add user lists to the template.
Or directly in the notification.

#### New system Notifications:
Now system notifications are placed in an independent model. 
It is not necessary to create templates for them. 
Mass mailing is also available.

```python
from django.conf import settings
from garpix_notify.models import SystemNotify
from django.contrib.auth import get_user_model

# 1. Example of use without templates
User = get_user_model()
user = User.objects.filter().first()
SystemNotify.send({'test': 'data'}, user)

# 2. Example of using a template
SystemNotify.send({'test': 'data'}, event=settings.EXAMPLE_EVENT_2)
```
#### Do not forget run celery:

```
celery -A app worker --loglevel=info -B
```

# Telegram Notify

Register you bot [https://t.me/BotFather](https://t.me/BotFather)

Go to [http://localhost:8000/admin/garpix_notify/notifyconfig/](https://t.me/BotFather) and fill "Telegram" section (`API key` and `Bot name`).

Run daemon:

```bash
python3 backend/manage.py garpix_notify_telegram
```

Go to your bot and send `/start` command.

Also, see `user/admin.py` file (see instructions):

```python
from django.contrib import admin
from .models import User
from django.contrib.auth.admin import UserAdmin


@admin.register(User)
class UserAdmin(UserAdmin):
    fieldsets = (
        ('Telegram', {
            'fields': ('telegram_chat_id', 'telegram_secret', 'get_telegram_connect_user_help'),
        })
    ) + UserAdmin.fieldsets
    readonly_fields = ['telegram_secret', 'get_telegram_connect_user_help'] + list(UserAdmin.readonly_fields)
```

# System ws Notify

Add the `channels` to your `INSTALLED_APPS`:

```python
# settings.py

INSTALLED_APPS = [
    # ...
    'channels',
]
```

Add the `REDIS_HOST` and `REDIS_PORT` variables and `asgi` and `channels` configurations:

```python
# settings.py

REDIS_HOST = os.getenv('REDIS_HOST', 'localhost')
REDIS_PORT = os.getenv('REDIS_PORT', 6379)

...

ASGI_APPLICATION = 'app.asgi.application'
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [(REDIS_HOST, REDIS_PORT)],
        },
    },
}
```

Edit your `asgi.py` file

```python
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from garpix_notify import routing


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')

application = ProtocolTypeRouter({
  "http": get_asgi_application(),
  "websocket": AuthMiddlewareStack(
        URLRouter(
            routing.websocket_urlpatterns
        )
    ),
})
```

Socket notification example

```python
group_name = f'workflow-{user.pk}'
Notify.send(settings.MY_NOTIFY, {
        'message': 'my message',
    }, room_name=group_name, user=user)
```

For notifications of the SYSTEM type, a separate non-periodic task is used that works instantly, if room_name is missing system messages will be sent in `'room_{id}'` where `'id'` is user id

You can add notifies rotes to your project:

```python
urlpatterns = [
    # ...
    path('', include(('garpix_notify.urls', 'garpix_notify'), namespace='garpix_notify')),
]

```

# Changelog

See [CHANGELOG.md](CHANGELOG.md).

# Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).

# License

[MIT](LICENSE)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/garpixcms/garpix_notify",
    "name": "garpix-notify",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "Garpix LTD",
    "author_email": "info@garpix.com",
    "download_url": "https://files.pythonhosted.org/packages/92/a5/8902502a7facd66fd8f0eac6df479b7c4d34b9cc33391caa9274d1c63900/garpix_notify-5.16.2.tar.gz",
    "platform": null,
    "description": "# Garpix Notify\n\n\n## Quickstart\n\nInstall with pip:\n\n```bash\npip install garpix_notify\n```\n\nAdd the `garpix_notify` and dependencies to your `INSTALLED_APPS`:\n\n```python\n# settings.py\n\nINSTALLED_APPS = [\n    # ...\n    'fcm_django',\n    'garpix_notify',\n]\n\nFCM_DJANGO_SETTINGS = {\n        \"APP_VERBOSE_NAME\": \"Firebase Cloud Messaging\",\n        \"FCM_SERVER_KEY\": \"[your api key]\",\n        \"ONE_DEVICE_PER_USER\": False,\n        \"DELETE_INACTIVE_DEVICES\": False,\n}\n\n```\n\nPackage not included migrations, set path to migration directory. Don't forget create this directory (`app/migrations/garpix_notify/`) and place empty `__init__.py`:\n\n```\napp/migrations/\napp/migrations/__init__.py  # empty file\napp/migrations/garpix_notify/__init__.py  # empty file\n```\n\nAdd path to settings:\n\n```python\n# settings.py\n\nMIGRATION_MODULES = {\n    'garpix_notify': 'app.migrations.garpix_notify',\n}\n```\n\nAdd mixins to settings if you need to add extra functionality to Notify models:\n\n```python\n\n# settings.py\n   \nGARPIX_NOTIFY_MIXIN = 'app.models.notify_mixin.NotifyMixin'  \nGARPIX_SYSTEM_NOTIFY_MIXIN = 'app.models.notify_mixin.SystemNotifyMixin'  \n```\n\nCreate your custom user model and add `AUTH_USER_MODEL` to `app/settings.py`:\n\n```\nAUTH_USER_MODEL = 'user.User'\n\n```\n\nRun make migrations:\n\n```bash\npython manage.py makemigrations\n```\n\nMigrate:\n\n```bash\npython manage.py migrate\n```\n\n### Example\n\n#### Step 1. Set notify types in `app/settings.py`, for example:\n\n```python\nREGISTRATION_EVENT = 1\nFEEDBACK_EVENT = 2\nEXAMPLE_EVENT_1 = 3\nEXAMPLE_EVENT_2 = 4\n\n\nNOTIFY_EVENTS = {\n    REGISTRATION_EVENT: {\n        'title': 'Register',\n    },\n    FEEDBACK_EVENT: {\n        'title': 'Feeback',\n    },\n    EXAMPLE_EVENT_1: {\n        'title': 'Example 1',\n    },\n    EXAMPLE_EVENT_2: {\n        'title': 'Example 2',\n    },\n}\n\nCHOICES_NOTIFY_EVENT = [(k, v['title']) for k, v in NOTIFY_EVENTS.items()]\n\n```\n#### Step 2. Import default settings in your ``app/settings.py``\n```python\n\n    from garpix_notify.settings import *\n```\nor copy from here if you want more customization\n```python\n# notify config\n\nPERIODIC_SENDING = 60\nEMAIL_MAX_DAY_LIMIT = 240\nEMAIL_MAX_HOUR_LIMIT = 240\n# SMS\nSMS_URL_TYPE = 0\nSMS_API_ID = 1234567890\nSMS_LOGIN = ''\nSMS_PASSWORD = ''\nSMS_FROM = ''\n# CALL\nCALL_URL_TYPE = 0\nCALL_API_ID = 1234567890\nCALL_LOGIN = ''\nCALL_PASSWORD = ''\n# TELEGRAM\nTELEGRAM_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'\nTELEGRAM_BOT_NAME = 'MySuperBot'\nTELEGRAM_WELCOME_TEXT = 'Hello'\nTELEGRAM_HELP_TEXT = '/set !help for HELP'\nTELEGRAM_BAD_COMMAND_TEXT = 'Incorrect command format'\nTELEGRAM_SUCCESS_ADDED_TEXT = 'Success'\nTELEGRAM_FAILED_ADDED_TEXT = 'Failed'\nTELEGRAM_PARSE_MODE = None\nTELEGRAM_DISABLE_NOTIFICATION = False\nTELEGRAM_DISABLE_PAGE_PREVIEW = False\nTELEGRAM_SENDING_WITHOUT_REPLY = False\nTELEGRAM_TIMEOUT = None\n# VIBER\nVIBER_API_KEY = '000000000:AAAAAAAAAA-AAAAAAAA-_AAAAAAAAAAAAAA'\nVIBER_BOT_NAME = 'MySuperViberBot'\nVIBER_WELCOME_TEXT = 'Hello'\nVIBER_SUCCESS_ADDED_TEXT = 'Success'\nVIBER_FAILED_ADDED_TEXT = 'Failed'\nVIBER_TEXT_FOR_NEW_SUB = 'HI!'\n# WHATSAPP\nIS_WHATS_APP_ENABLED = True\nWHATS_APP_AUTH_TOKEN = None\nWHATS_APP_ACCOUNT_SID = None\nWHATS_APP_NUMBER_SENDER = None\n# SETTINGS\nEMAIL_MALLING = 1\nGARPIX_NOTIFY_MIXIN = 'garpix_notify.mixins.notify_mixin.NotifyMixin'\nNOTIFY_USER_WANT_MESSAGE_CHECK = None\nNOTIFY_CALL_CODE_CHECK = None\nGARPIX_NOTIFY_CELERY_SETTINGS = 'app.celery.app'\nDEFAULT_SYSTEM_NOTIFY_TYPE = 'system'\n\n\n```\n#### Step 3. Go to the admin panel and go to the \"Notifications\" section - \"SMTP accounts\"\n\nAdd an SMTP account to send Email notifications. These will be the senders of Email notifications.\n\n#### Step 4. Also go to \"Notifications\" - \"Categories\"\n\nCreate a category that will be used to send emails. Usually one category is enough. The ability to enter several categories\nis necessary to divide them into informational and marketing notifications.\n\n#### Step 4. Go to \"Notifications\" - \"Templates\"\n\nCreate a template for a specific event (when you added them to `settings.py`).\n\n#### Step 5. Call Notify.send()\n\nIn the code where it is necessary to work out sending a notification, we perform the following actions:\n\n```python\nfrom django.conf import settings\nfrom garpix_notify.models import Notify\n\n# Syntax\n# Notify.send(<event>, <context>[, <user=None>, <email=None>, <phone=None>, <files=None>, <data_json=None>])\n# That is, we specify the event ID as the first parameter,\n# create variables for the template,\n# third - the user to send it to (it is not necessary to specify his email, phone number, etc.,\n# because this will be determined automatically depending on the type of template)   \n\n# Example\nuser = request.user  # this will be the recipient of the notification.\n\nNotify.send(settings.REGISTRATION_EVENT, {\n    'confirmation_code': 'abcdef12345',\n}, user=user)\n\n# If we do not have a user in the system, but we need to send an email, we can do the following\n\nNotify.send(settings.EXAMPLE_EVENT_1, {\n    'confirmation_code': 'abcdef12345',\n}, email='example@mail.ru')\n\n# If you need more detailed time settings, add send_at\n\nNotify.send(settings.EXAMPLE_EVENT_1, {\n    'confirmation_code': 'abcdef12345',\n}, email='example@mail.ru', send_at=(datetime.datetime.now() + datetime.timedelta(days=1)))\n\n# If you need to send a code by phone call\nNotify.send(settings.EXAMPLE_EVENT_2, phone='79998881122', context={})\n\n# or if you need to get the code directly\nNotify.call(phone=79998881122)\n\n\n```\n\n#### Mass email and sms mailing:\nTo perform a mass mailing, you need to add user lists to the template.\nOr directly in the notification.\n\n#### New system Notifications:\nNow system notifications are placed in an independent model. \nIt is not necessary to create templates for them. \nMass mailing is also available.\n\n```python\nfrom django.conf import settings\nfrom garpix_notify.models import SystemNotify\nfrom django.contrib.auth import get_user_model\n\n# 1. Example of use without templates\nUser = get_user_model()\nuser = User.objects.filter().first()\nSystemNotify.send({'test': 'data'}, user)\n\n# 2. Example of using a template\nSystemNotify.send({'test': 'data'}, event=settings.EXAMPLE_EVENT_2)\n```\n#### Do not forget run celery:\n\n```\ncelery -A app worker --loglevel=info -B\n```\n\n# Telegram Notify\n\nRegister you bot [https://t.me/BotFather](https://t.me/BotFather)\n\nGo to [http://localhost:8000/admin/garpix_notify/notifyconfig/](https://t.me/BotFather) and fill \"Telegram\" section (`API key` and `Bot name`).\n\nRun daemon:\n\n```bash\npython3 backend/manage.py garpix_notify_telegram\n```\n\nGo to your bot and send `/start` command.\n\nAlso, see `user/admin.py` file (see instructions):\n\n```python\nfrom django.contrib import admin\nfrom .models import User\nfrom django.contrib.auth.admin import UserAdmin\n\n\n@admin.register(User)\nclass UserAdmin(UserAdmin):\n    fieldsets = (\n        ('Telegram', {\n            'fields': ('telegram_chat_id', 'telegram_secret', 'get_telegram_connect_user_help'),\n        })\n    ) + UserAdmin.fieldsets\n    readonly_fields = ['telegram_secret', 'get_telegram_connect_user_help'] + list(UserAdmin.readonly_fields)\n```\n\n# System ws Notify\n\nAdd the `channels` to your `INSTALLED_APPS`:\n\n```python\n# settings.py\n\nINSTALLED_APPS = [\n    # ...\n    'channels',\n]\n```\n\nAdd the `REDIS_HOST` and `REDIS_PORT` variables and `asgi` and `channels` configurations:\n\n```python\n# settings.py\n\nREDIS_HOST = os.getenv('REDIS_HOST', 'localhost')\nREDIS_PORT = os.getenv('REDIS_PORT', 6379)\n\n...\n\nASGI_APPLICATION = 'app.asgi.application'\nCHANNEL_LAYERS = {\n    'default': {\n        'BACKEND': 'channels_redis.core.RedisChannelLayer',\n        'CONFIG': {\n            \"hosts\": [(REDIS_HOST, REDIS_PORT)],\n        },\n    },\n}\n```\n\nEdit your `asgi.py` file\n\n```python\nimport os\nfrom channels.auth import AuthMiddlewareStack\nfrom channels.routing import ProtocolTypeRouter, URLRouter\nfrom django.core.asgi import get_asgi_application\nfrom garpix_notify import routing\n\n\nos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')\n\napplication = ProtocolTypeRouter({\n  \"http\": get_asgi_application(),\n  \"websocket\": AuthMiddlewareStack(\n        URLRouter(\n            routing.websocket_urlpatterns\n        )\n    ),\n})\n```\n\nSocket notification example\n\n```python\ngroup_name = f'workflow-{user.pk}'\nNotify.send(settings.MY_NOTIFY, {\n        'message': 'my message',\n    }, room_name=group_name, user=user)\n```\n\nFor notifications of the SYSTEM type, a separate non-periodic task is used that works instantly, if room_name is missing system messages will be sent in `'room_{id}'` where `'id'` is user id\n\nYou can add notifies rotes to your project:\n\n```python\nurlpatterns = [\n    # ...\n    path('', include(('garpix_notify.urls', 'garpix_notify'), namespace='garpix_notify')),\n]\n\n```\n\n# Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md).\n\n# Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n# License\n\n[MIT](LICENSE)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "",
    "version": "5.16.2",
    "project_urls": {
        "Homepage": "https://github.com/garpixcms/garpix_notify"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "79aebf63be50b6dfa96cd2f5d5a1af844d14c9430e31b3428410f3ddef0dbb26",
                "md5": "bf9dd5c8e170231260d0be3600c23daa",
                "sha256": "bfa58f5a0d5b1b7bfaaa88faed6c2d5006552ef840425bf59421277a90bd667a"
            },
            "downloads": -1,
            "filename": "garpix_notify-5.16.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "bf9dd5c8e170231260d0be3600c23daa",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 167640,
            "upload_time": "2023-09-19T09:56:16",
            "upload_time_iso_8601": "2023-09-19T09:56:16.798260Z",
            "url": "https://files.pythonhosted.org/packages/79/ae/bf63be50b6dfa96cd2f5d5a1af844d14c9430e31b3428410f3ddef0dbb26/garpix_notify-5.16.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "92a58902502a7facd66fd8f0eac6df479b7c4d34b9cc33391caa9274d1c63900",
                "md5": "963ce4d43d9da8d56398225e61a31e9d",
                "sha256": "b0dbc0ca4d252506788111076157bf6f91dabe36dde959122093f2f7372583e2"
            },
            "downloads": -1,
            "filename": "garpix_notify-5.16.2.tar.gz",
            "has_sig": false,
            "md5_digest": "963ce4d43d9da8d56398225e61a31e9d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 105345,
            "upload_time": "2023-09-19T09:56:18",
            "upload_time_iso_8601": "2023-09-19T09:56:18.624316Z",
            "url": "https://files.pythonhosted.org/packages/92/a5/8902502a7facd66fd8f0eac6df479b7c4d34b9cc33391caa9274d1c63900/garpix_notify-5.16.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-19 09:56:18",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "garpixcms",
    "github_project": "garpix_notify",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "garpix-notify"
}
        
Elapsed time: 0.20065s