android-notify 1.24.4__py3-none-any.whl → 1.31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of android-notify might be problematic. Click here for more details.
- android_notify/__init__.py +1 -6
- android_notify/core.py +10 -3
- android_notify/styles.py +13 -3
- android_notify/sword.py +375 -0
- android_notify-1.31.dist-info/METADATA +361 -0
- android_notify-1.31.dist-info/RECORD +9 -0
- android_notify/_dev.py +0 -112
- android_notify/advanced_dev.py +0 -345
- android_notify-1.24.4.dist-info/METADATA +0 -298
- android_notify-1.24.4.dist-info/RECORD +0 -10
- {android_notify-1.24.4.dist-info → android_notify-1.31.dist-info}/WHEEL +0 -0
- {android_notify-1.24.4.dist-info → android_notify-1.31.dist-info}/top_level.txt +0 -0
android_notify/__init__.py
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
from .core import send_notification
|
|
2
2
|
from .styles import NotificationStyles
|
|
3
|
-
|
|
4
|
-
from .advanced import EnhancedNotificationManager
|
|
5
|
-
from ._dev import NotificationBuilder
|
|
6
|
-
except Exception as e:
|
|
7
|
-
# print('Failed to Import Advanced Features:', e)
|
|
8
|
-
pass
|
|
3
|
+
from .sword import Notification
|
android_notify/core.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
from jnius import autoclass,cast
|
|
1
|
+
""" Non-Advanced Stuff """
|
|
3
2
|
import random
|
|
4
3
|
import os
|
|
4
|
+
from jnius import autoclass,cast
|
|
5
5
|
|
|
6
6
|
ON_ANDROID = False
|
|
7
7
|
try:
|
|
@@ -64,7 +64,14 @@ def get_image_uri(relative_path):
|
|
|
64
64
|
return Uri.parse(f"file://{output_path}")
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def send_notification(
|
|
67
|
+
def send_notification(
|
|
68
|
+
title:str,
|
|
69
|
+
message:str,
|
|
70
|
+
style=None,
|
|
71
|
+
img_path=None,
|
|
72
|
+
channel_name="Default Channel",
|
|
73
|
+
channel_id:str="default_channel"
|
|
74
|
+
):
|
|
68
75
|
"""
|
|
69
76
|
Send a notification on Android.
|
|
70
77
|
|
android_notify/styles.py
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
class NotificationStyles:
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
class NotificationStyles():
|
|
2
|
+
""" Safely Adding Styles"""
|
|
3
|
+
DEFAULT = "simple"
|
|
4
|
+
|
|
5
|
+
PROGRESS = "progress"
|
|
4
6
|
INBOX = "inbox"
|
|
7
|
+
BIG_TEXT = "big_text"
|
|
8
|
+
|
|
5
9
|
LARGE_ICON = "large_icon"
|
|
10
|
+
BIG_PICTURE = "big_picture"
|
|
11
|
+
BOTH_IMGS = "both_imgs"
|
|
12
|
+
|
|
13
|
+
MESSAGING = "messaging" # TODO
|
|
14
|
+
CUSTOM = "custom" # TODO
|
|
15
|
+
|
android_notify/sword.py
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"""This Module Contain Class for creating Notification With Java"""
|
|
2
|
+
import difflib
|
|
3
|
+
import random
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
from jnius import autoclass,cast # pylint: disable=W0611, C0114
|
|
7
|
+
|
|
8
|
+
DEV=0
|
|
9
|
+
ON_ANDROID = False
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
# Get the required Java classes
|
|
13
|
+
PythonActivity = autoclass('org.kivy.android.PythonActivity')
|
|
14
|
+
String = autoclass('java.lang.String')
|
|
15
|
+
Intent = autoclass('android.content.Intent')
|
|
16
|
+
PendingIntent = autoclass('android.app.PendingIntent')
|
|
17
|
+
context = PythonActivity.mActivity # Get the app's context
|
|
18
|
+
BitmapFactory = autoclass('android.graphics.BitmapFactory')
|
|
19
|
+
BuildVersion = autoclass('android.os.Build$VERSION')
|
|
20
|
+
NotificationManager = autoclass('android.app.NotificationManager')
|
|
21
|
+
NotificationChannel = autoclass('android.app.NotificationChannel')
|
|
22
|
+
ON_ANDROID = True
|
|
23
|
+
except Exception as e:# pylint: disable=W0718
|
|
24
|
+
MESSAGE='This Package Only Runs on Android !!! ---> Check "https://github.com/Fector101/android_notify/" to see design patterns and more info.' # pylint: disable=C0301
|
|
25
|
+
print(MESSAGE if DEV else '')
|
|
26
|
+
|
|
27
|
+
if ON_ANDROID:
|
|
28
|
+
try:
|
|
29
|
+
from android.permissions import request_permissions, Permission,check_permission # pylint: disable=E0401
|
|
30
|
+
from android.storage import app_storage_path # pylint: disable=E0401
|
|
31
|
+
|
|
32
|
+
NotificationManagerCompat = autoclass('androidx.core.app.NotificationManagerCompat')
|
|
33
|
+
NotificationCompat = autoclass('androidx.core.app.NotificationCompat')
|
|
34
|
+
|
|
35
|
+
# Notification Design
|
|
36
|
+
NotificationCompatBuilder = autoclass('androidx.core.app.NotificationCompat$Builder') # pylint: disable=C0301
|
|
37
|
+
NotificationCompatBigTextStyle = autoclass('androidx.core.app.NotificationCompat$BigTextStyle') # pylint: disable=C0301
|
|
38
|
+
NotificationCompatBigPictureStyle = autoclass('androidx.core.app.NotificationCompat$BigPictureStyle') # pylint: disable=C0301
|
|
39
|
+
NotificationCompatInboxStyle = autoclass('androidx.core.app.NotificationCompat$InboxStyle')
|
|
40
|
+
except Exception as e:# pylint: disable=W0718
|
|
41
|
+
print(e if DEV else '','Import Fector101')
|
|
42
|
+
# print(e if DEV else '')
|
|
43
|
+
print("""
|
|
44
|
+
Dependency Error: Add the following in buildozer.spec:
|
|
45
|
+
* android.gradle_dependencies = androidx.core:core-ktx:1.15.0, androidx.core:core:1.6.0
|
|
46
|
+
* android.enable_androidx = True
|
|
47
|
+
* android.permissions = POST_NOTIFICATIONS
|
|
48
|
+
""")
|
|
49
|
+
|
|
50
|
+
class Notification:
|
|
51
|
+
"""
|
|
52
|
+
Send a notification on Android.
|
|
53
|
+
|
|
54
|
+
:param title: Title of the notification.
|
|
55
|
+
:param message: Message body.
|
|
56
|
+
:param style: Style of the notification
|
|
57
|
+
('simple', 'progress', 'big_text', 'inbox', 'big_picture', 'large_icon', 'both_imgs').
|
|
58
|
+
both_imgs == using lager icon and big picture
|
|
59
|
+
:param big_picture_path: Path to the image resource.
|
|
60
|
+
:param large_icon_path: Path to the image resource.
|
|
61
|
+
---
|
|
62
|
+
(Advance Options)
|
|
63
|
+
:param channel_name: Defaults to "Default Channel"
|
|
64
|
+
:param channel_id: Defaults to "default_channel"
|
|
65
|
+
---
|
|
66
|
+
(Options during Dev On PC)
|
|
67
|
+
:param logs: Defaults to True
|
|
68
|
+
"""
|
|
69
|
+
notification_ids=[]
|
|
70
|
+
style_values=[
|
|
71
|
+
'','simple',
|
|
72
|
+
'progress','big_text',
|
|
73
|
+
'inbox', 'big_picture',
|
|
74
|
+
'large_icon','both_imgs',
|
|
75
|
+
'custom'
|
|
76
|
+
] # TODO make pattern for non-android Notifications
|
|
77
|
+
defaults={
|
|
78
|
+
'title':'Default Title',
|
|
79
|
+
'message':'Default Message', # TODO Might change message para to list if style set to inbox
|
|
80
|
+
'style':'simple',
|
|
81
|
+
'big_picture_path':'',
|
|
82
|
+
'large_icon_path':'',
|
|
83
|
+
'progress_max_value': 100,
|
|
84
|
+
'progress_current_value': 0,
|
|
85
|
+
'channel_name':'Default Channel',
|
|
86
|
+
'channel_id':'default_channel',
|
|
87
|
+
'logs':True,
|
|
88
|
+
}
|
|
89
|
+
# During Development (When running on PC)
|
|
90
|
+
logs=not ON_ANDROID
|
|
91
|
+
def __init__(self,**kwargs):
|
|
92
|
+
self.__validateArgs(kwargs)
|
|
93
|
+
# Basic options
|
|
94
|
+
self.title=''
|
|
95
|
+
self.message=''
|
|
96
|
+
self.style=''
|
|
97
|
+
self.large_icon_path=''
|
|
98
|
+
self.big_picture_path=''
|
|
99
|
+
self.progress_current_value=0
|
|
100
|
+
self.progress_max_value=100
|
|
101
|
+
# Advance Options
|
|
102
|
+
self.channel_name=''
|
|
103
|
+
self.channel_id=''
|
|
104
|
+
self.silent=False
|
|
105
|
+
# During Dev on PC
|
|
106
|
+
self.logs=self.logs
|
|
107
|
+
# Private (Don't Touch)
|
|
108
|
+
self.__id = self.__getUniqueID()
|
|
109
|
+
self.__setArgs(kwargs)
|
|
110
|
+
self.__builder=None
|
|
111
|
+
if not ON_ANDROID:
|
|
112
|
+
return
|
|
113
|
+
# TODO make send method wait for __asks_permission_if_needed method
|
|
114
|
+
self.__asks_permission_if_needed()
|
|
115
|
+
self.notification_manager = context.getSystemService(context.NOTIFICATION_SERVICE)
|
|
116
|
+
|
|
117
|
+
def updateTitle(self,new_title):
|
|
118
|
+
"""Changes Old Title
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
new_title (str): New Notification Title
|
|
122
|
+
"""
|
|
123
|
+
self.title=new_title
|
|
124
|
+
if ON_ANDROID:
|
|
125
|
+
self.__builder.setContentTitle(new_title)
|
|
126
|
+
|
|
127
|
+
def updateMessage(self,new_message):
|
|
128
|
+
"""Changes Old Message
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
new_message (str): New Notification Message
|
|
132
|
+
"""
|
|
133
|
+
self.message=new_message
|
|
134
|
+
if ON_ANDROID:
|
|
135
|
+
self.__builder.setContentText(new_message)
|
|
136
|
+
|
|
137
|
+
def updateProgressBar(self,current_value,message:str=''):
|
|
138
|
+
"""message defaults to last message"""
|
|
139
|
+
self.__builder.setProgress(self.progress_max_value, current_value, False)
|
|
140
|
+
if message:
|
|
141
|
+
self.__builder.setContentText(String(message))
|
|
142
|
+
self.notification_manager.notify(self.__id, self.__builder.build())
|
|
143
|
+
|
|
144
|
+
def removeProgressBar(self,message=''):
|
|
145
|
+
"""message defaults to last message"""
|
|
146
|
+
if message:
|
|
147
|
+
self.__builder.setContentText(String(message))
|
|
148
|
+
self.__builder.setProgress(0, 0, False)
|
|
149
|
+
self.notification_manager.notify(self.__id, self.__builder.build())
|
|
150
|
+
|
|
151
|
+
def send(self,silent:bool=False):
|
|
152
|
+
"""Sends notification
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
silent (bool): True if you don't want to show briefly on screen
|
|
156
|
+
"""
|
|
157
|
+
self.silent=self.silent or silent
|
|
158
|
+
if ON_ANDROID:
|
|
159
|
+
self.__startNotificationBuild()
|
|
160
|
+
self.notification_manager.notify(self.__id, self.__builder.build())
|
|
161
|
+
elif self.logs:
|
|
162
|
+
print(f"""
|
|
163
|
+
Dev Notification Properties:
|
|
164
|
+
title: '{self.title}'
|
|
165
|
+
message: '{self.message}'
|
|
166
|
+
large_icon_path: '{self.large_icon_path}'
|
|
167
|
+
big_picture_path: '{self.big_picture_path}'
|
|
168
|
+
style: '{self.style}'
|
|
169
|
+
Silent: '{self.silent}'
|
|
170
|
+
(Won't Print Logs When Complied,except if selected `Notification.logs=True`
|
|
171
|
+
""")
|
|
172
|
+
if DEV:
|
|
173
|
+
print(f'channel_name: {self.channel_name}, Channel ID: {self.channel_id}, id: {self.__id}')
|
|
174
|
+
print('Can\'t Send Package Only Runs on Android !!! ---> Check "https://github.com/Fector101/android_notify/" for Documentation.\n' if DEV else '\n') # pylint: disable=C0301
|
|
175
|
+
|
|
176
|
+
def __validateArgs(self,inputted_kwargs):
|
|
177
|
+
|
|
178
|
+
def checkInReference(inputted_keywords,accepteable_inputs,input_type):
|
|
179
|
+
def singularForm(plural_form):
|
|
180
|
+
return plural_form[:-1]
|
|
181
|
+
invalid_args= set(inputted_keywords) - set(accepteable_inputs)
|
|
182
|
+
if invalid_args:
|
|
183
|
+
suggestions=[]
|
|
184
|
+
for arg in invalid_args:
|
|
185
|
+
closest_match = difflib.get_close_matches(arg,accepteable_inputs,n=2,cutoff=0.6)
|
|
186
|
+
if closest_match:
|
|
187
|
+
suggestions.append(f"* '{arg}' Invalid -> Did you mean '{closest_match[0]}'? ") # pylint: disable=C0301
|
|
188
|
+
else:
|
|
189
|
+
suggestions.append(f"* {arg} is not a valid {singularForm(input_type)}.")
|
|
190
|
+
suggestion_text='\n'.join(suggestions)
|
|
191
|
+
hint_msg=singularForm(input_type) if len(invalid_args) < 2 else input_type
|
|
192
|
+
|
|
193
|
+
raise ValueError(f"Invalid {hint_msg} provided: \n\t{suggestion_text}\n\t* list of valid {input_type}: [{', '.join(accepteable_inputs)}]")
|
|
194
|
+
|
|
195
|
+
allowed_keywords=self.defaults.keys()
|
|
196
|
+
inputted_keywords_=inputted_kwargs.keys()
|
|
197
|
+
checkInReference(inputted_keywords_,allowed_keywords,'arguments')
|
|
198
|
+
|
|
199
|
+
# Validate style values
|
|
200
|
+
if 'style' in inputted_keywords_ and inputted_kwargs['style'] not in self.style_values:
|
|
201
|
+
checkInReference([inputted_kwargs['style']],self.style_values,'values')
|
|
202
|
+
|
|
203
|
+
def __setArgs(self,options_dict:dict):
|
|
204
|
+
for key,value in options_dict.items():
|
|
205
|
+
if key == 'channel_name':
|
|
206
|
+
setattr(self,key, value[:40] if value else self.defaults[key])
|
|
207
|
+
elif key == 'channel_id' and value:
|
|
208
|
+
setattr(self,key, self.__generate_channel_id(value) if value else self.defaults[key])
|
|
209
|
+
|
|
210
|
+
setattr(self,key, value if value else self.defaults[key])
|
|
211
|
+
|
|
212
|
+
if "channel_id" not in options_dict and 'channel_name' in options_dict:
|
|
213
|
+
setattr(self,'channel_id', self.__generate_channel_id(options_dict['channel_name']))
|
|
214
|
+
|
|
215
|
+
def __startNotificationBuild(self):
|
|
216
|
+
self.__createBasicNotification()
|
|
217
|
+
if self.style not in ['simple','']:
|
|
218
|
+
self.__addNotificationStyle()
|
|
219
|
+
|
|
220
|
+
def __createBasicNotification(self):
|
|
221
|
+
# Notification Channel (Required for Android 8.0+)
|
|
222
|
+
if BuildVersion.SDK_INT >= 26 and self.notification_manager.getNotificationChannel(self.channel_id) is None:
|
|
223
|
+
importance=NotificationManagerCompat.IMPORTANCE_DEFAULT if self.silent else NotificationManagerCompat.IMPORTANCE_HIGH # pylint: disable=possibly-used-before-assignment
|
|
224
|
+
channel = NotificationChannel(
|
|
225
|
+
self.channel_id,
|
|
226
|
+
self.channel_name,
|
|
227
|
+
importance
|
|
228
|
+
)
|
|
229
|
+
self.notification_manager.createNotificationChannel(channel)
|
|
230
|
+
|
|
231
|
+
# Build the notification
|
|
232
|
+
self.__builder = NotificationCompatBuilder(context, self.channel_id)# pylint: disable=E0606
|
|
233
|
+
self.__builder.setContentTitle(self.title)
|
|
234
|
+
self.__builder.setContentText(self.message)
|
|
235
|
+
self.__builder.setSmallIcon(context.getApplicationInfo().icon)
|
|
236
|
+
self.__builder.setDefaults(NotificationCompat.DEFAULT_ALL) # pylint: disable=E0606
|
|
237
|
+
if not self.silent:
|
|
238
|
+
self.__builder.setPriority(NotificationCompat.PRIORITY_DEFAULT if self.silent else NotificationCompat.PRIORITY_HIGH)
|
|
239
|
+
|
|
240
|
+
def __addNotificationStyle(self):
|
|
241
|
+
# pylint: disable=trailing-whitespace
|
|
242
|
+
|
|
243
|
+
large_icon_javapath=None
|
|
244
|
+
if self.large_icon_path:
|
|
245
|
+
try:
|
|
246
|
+
large_icon_javapath = self.__get_image_uri(self.large_icon_path)
|
|
247
|
+
except FileNotFoundError as e:
|
|
248
|
+
print('Failed Adding Big Picture Bitmap: ',e)
|
|
249
|
+
|
|
250
|
+
big_pic_javapath=None
|
|
251
|
+
if self.big_picture_path:
|
|
252
|
+
try:
|
|
253
|
+
big_pic_javapath = self.__get_image_uri(self.big_picture_path)
|
|
254
|
+
except FileNotFoundError as e:
|
|
255
|
+
print('Failed Adding Lagre Icon Bitmap: ',e)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
if self.style == "big_text":
|
|
259
|
+
big_text_style = NotificationCompatBigTextStyle() # pylint: disable=E0606
|
|
260
|
+
big_text_style.bigText(self.message)
|
|
261
|
+
self.__builder.setStyle(big_text_style)
|
|
262
|
+
|
|
263
|
+
elif self.style == "inbox":
|
|
264
|
+
inbox_style = NotificationCompatInboxStyle() # pylint: disable=E0606
|
|
265
|
+
for line in self.message.split("\n"):
|
|
266
|
+
inbox_style.addLine(line)
|
|
267
|
+
self.__builder.setStyle(inbox_style)
|
|
268
|
+
|
|
269
|
+
elif self.style == "big_picture" and big_pic_javapath:
|
|
270
|
+
big_pic_bitmap = self.__getBitmap(big_pic_javapath)
|
|
271
|
+
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(big_pic_bitmap) # pylint: disable=E0606
|
|
272
|
+
self.__builder.setStyle(big_picture_style)
|
|
273
|
+
|
|
274
|
+
elif self.style == "large_icon" and large_icon_javapath:
|
|
275
|
+
large_icon_bitmap = self.__getBitmap(large_icon_javapath)
|
|
276
|
+
self.__builder.setLargeIcon(large_icon_bitmap)
|
|
277
|
+
|
|
278
|
+
elif self.style == 'both_imgs' and (large_icon_javapath or big_pic_javapath):
|
|
279
|
+
if big_pic_javapath:
|
|
280
|
+
big_pic_bitmap = self.__getBitmap(big_pic_javapath)
|
|
281
|
+
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(big_pic_bitmap)
|
|
282
|
+
self.__builder.setStyle(big_picture_style)
|
|
283
|
+
elif large_icon_javapath:
|
|
284
|
+
large_icon_bitmap = self.__getBitmap(large_icon_javapath)
|
|
285
|
+
self.__builder.setLargeIcon(large_icon_bitmap)
|
|
286
|
+
elif self.style == 'progress':
|
|
287
|
+
self.__builder.setContentTitle(String(self.title))
|
|
288
|
+
self.__builder.setContentText(String(self.message))
|
|
289
|
+
self.__builder.setProgress(self.progress_max_value, self.progress_current_value, False)
|
|
290
|
+
# elif self.style == 'custom':
|
|
291
|
+
# self.__builder = self.__doCustomStyle()
|
|
292
|
+
|
|
293
|
+
# def __doCustomStyle(self):
|
|
294
|
+
# # TODO Will implement when needed
|
|
295
|
+
# return self.__builder
|
|
296
|
+
|
|
297
|
+
def __getUniqueID(self):
|
|
298
|
+
reasonable_amount_of_notifications=101
|
|
299
|
+
notification_id = random.randint(1, reasonable_amount_of_notifications)
|
|
300
|
+
while notification_id in self.notification_ids:
|
|
301
|
+
notification_id = random.randint(1, 100)
|
|
302
|
+
self.notification_ids.append(notification_id)
|
|
303
|
+
return notification_id
|
|
304
|
+
|
|
305
|
+
def __asks_permission_if_needed(self):
|
|
306
|
+
"""
|
|
307
|
+
Ask for permission to send notifications if needed.
|
|
308
|
+
"""
|
|
309
|
+
def on_permissions_result(permissions, grant): # pylint: disable=unused-argument
|
|
310
|
+
if self.logs:
|
|
311
|
+
print("Permission Grant State: ",grant)
|
|
312
|
+
|
|
313
|
+
permissions=[Permission.POST_NOTIFICATIONS] # pylint: disable=E0606
|
|
314
|
+
if not all(check_permission(p) for p in permissions):
|
|
315
|
+
request_permissions(permissions,on_permissions_result) # pylint: disable=E0606
|
|
316
|
+
|
|
317
|
+
def __get_image_uri(self,relative_path):
|
|
318
|
+
"""
|
|
319
|
+
Get the absolute URI for an image in the assets folder.
|
|
320
|
+
:param relative_path: The relative path to the image (e.g., 'assets/imgs/icon.png').
|
|
321
|
+
:return: Absolute URI java Object (e.g., 'file:///path/to/file.png').
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
output_path = os.path.join(app_storage_path(),'app', relative_path) # pylint: disable=possibly-used-before-assignment
|
|
325
|
+
# print(output_path) # /data/user/0/(package.domain+package.name)/files/app/assets/imgs/icon.png | pylint: disable=:line-too-long
|
|
326
|
+
|
|
327
|
+
if not os.path.exists(output_path):
|
|
328
|
+
# TODO Use images From Any where even Web
|
|
329
|
+
raise FileNotFoundError(f"Image not found at path: {output_path}, (Can Only Use Images in App Path)")
|
|
330
|
+
Uri = autoclass('android.net.Uri')
|
|
331
|
+
return Uri.parse(f"file://{output_path}")
|
|
332
|
+
def __getBitmap(self,img_path):
|
|
333
|
+
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(img_path))
|
|
334
|
+
|
|
335
|
+
def __generate_channel_id(self,channel_name: str) -> str:
|
|
336
|
+
"""
|
|
337
|
+
Generate a readable and consistent channel ID from a channel name.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
channel_name (str): The name of the notification channel.
|
|
341
|
+
|
|
342
|
+
Returns:
|
|
343
|
+
str: A sanitized channel ID.
|
|
344
|
+
"""
|
|
345
|
+
# Normalize the channel name
|
|
346
|
+
channel_id = channel_name.strip().lower()
|
|
347
|
+
# Replace spaces and special characters with underscores
|
|
348
|
+
channel_id = re.sub(r'[^a-z0-9]+', '_', channel_id)
|
|
349
|
+
# Remove leading/trailing underscores
|
|
350
|
+
channel_id = channel_id.strip('_')
|
|
351
|
+
return channel_id[:50]
|
|
352
|
+
|
|
353
|
+
# try:
|
|
354
|
+
# notify=Notification(titl='My Title',channel_name='Go')#,logs=False)
|
|
355
|
+
# # notify.channel_name='Downloads'
|
|
356
|
+
# notify.message="Blah"
|
|
357
|
+
# notify.send()
|
|
358
|
+
# notify.updateTitle('New Title')
|
|
359
|
+
# notify.updateMessage('New Message')
|
|
360
|
+
# notify.send(True)
|
|
361
|
+
# except Exception as e:
|
|
362
|
+
# print(e)
|
|
363
|
+
|
|
364
|
+
# notify=Notification(title='My Title1')
|
|
365
|
+
# # notify.updateTitle('New Title1')
|
|
366
|
+
# notify.send()
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# Notification.logs=False # Add in Readme
|
|
370
|
+
# notify=Notification(style='large_icon',title='My Title',channel_name='Some thing about a thing ')#,logs=False)
|
|
371
|
+
# # notify.channel_name='Downloads'
|
|
372
|
+
# notify.message="Blah"
|
|
373
|
+
# notify.send()
|
|
374
|
+
# notify.updateTitle('New Title')
|
|
375
|
+
# notify.updateMessage('New Message')
|