flowtask 5.8.4__cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.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.
Files changed (470) hide show
  1. flowtask/__init__.py +93 -0
  2. flowtask/__main__.py +38 -0
  3. flowtask/bots/__init__.py +6 -0
  4. flowtask/bots/check.py +93 -0
  5. flowtask/bots/codebot.py +51 -0
  6. flowtask/components/ASPX.py +148 -0
  7. flowtask/components/AddDataset.py +352 -0
  8. flowtask/components/Amazon.py +523 -0
  9. flowtask/components/AutoTask.py +314 -0
  10. flowtask/components/Azure.py +80 -0
  11. flowtask/components/AzureUsers.py +106 -0
  12. flowtask/components/BaseAction.py +91 -0
  13. flowtask/components/BaseLoop.py +198 -0
  14. flowtask/components/BestBuy.py +800 -0
  15. flowtask/components/CSVToGCS.py +120 -0
  16. flowtask/components/CompanyScraper/__init__.py +1 -0
  17. flowtask/components/CompanyScraper/parsers/__init__.py +6 -0
  18. flowtask/components/CompanyScraper/parsers/base.py +102 -0
  19. flowtask/components/CompanyScraper/parsers/explorium.py +192 -0
  20. flowtask/components/CompanyScraper/parsers/leadiq.py +206 -0
  21. flowtask/components/CompanyScraper/parsers/rocket.py +133 -0
  22. flowtask/components/CompanyScraper/parsers/siccode.py +109 -0
  23. flowtask/components/CompanyScraper/parsers/visualvisitor.py +130 -0
  24. flowtask/components/CompanyScraper/parsers/zoominfo.py +118 -0
  25. flowtask/components/CompanyScraper/scrapper.py +1054 -0
  26. flowtask/components/CopyTo.py +177 -0
  27. flowtask/components/CopyToBigQuery.py +243 -0
  28. flowtask/components/CopyToMongoDB.py +291 -0
  29. flowtask/components/CopyToPg.py +609 -0
  30. flowtask/components/CopyToRethink.py +207 -0
  31. flowtask/components/CreateGCSBucket.py +102 -0
  32. flowtask/components/CreateReport/CreateReport.py +228 -0
  33. flowtask/components/CreateReport/__init__.py +9 -0
  34. flowtask/components/CreateReport/charts/__init__.py +15 -0
  35. flowtask/components/CreateReport/charts/bar.py +51 -0
  36. flowtask/components/CreateReport/charts/base.py +66 -0
  37. flowtask/components/CreateReport/charts/pie.py +64 -0
  38. flowtask/components/CreateReport/utils.py +9 -0
  39. flowtask/components/CustomerSatisfaction.py +196 -0
  40. flowtask/components/DataInput.py +200 -0
  41. flowtask/components/DateList.py +255 -0
  42. flowtask/components/DbClient.py +163 -0
  43. flowtask/components/DialPad.py +146 -0
  44. flowtask/components/DocumentDBQuery.py +200 -0
  45. flowtask/components/DownloadFrom.py +371 -0
  46. flowtask/components/DownloadFromD2L.py +113 -0
  47. flowtask/components/DownloadFromFTP.py +181 -0
  48. flowtask/components/DownloadFromIMAP.py +315 -0
  49. flowtask/components/DownloadFromS3.py +198 -0
  50. flowtask/components/DownloadFromSFTP.py +265 -0
  51. flowtask/components/DownloadFromSharepoint.py +110 -0
  52. flowtask/components/DownloadFromSmartSheet.py +114 -0
  53. flowtask/components/DownloadS3File.py +229 -0
  54. flowtask/components/Dummy.py +59 -0
  55. flowtask/components/DuplicatePhoto.py +411 -0
  56. flowtask/components/EmployeeEvaluation.py +237 -0
  57. flowtask/components/ExecuteSQL.py +323 -0
  58. flowtask/components/ExtractHTML.py +178 -0
  59. flowtask/components/FileBase.py +178 -0
  60. flowtask/components/FileCopy.py +181 -0
  61. flowtask/components/FileDelete.py +82 -0
  62. flowtask/components/FileExists.py +146 -0
  63. flowtask/components/FileIteratorDelete.py +112 -0
  64. flowtask/components/FileList.py +194 -0
  65. flowtask/components/FileOpen.py +75 -0
  66. flowtask/components/FileRead.py +120 -0
  67. flowtask/components/FileRename.py +106 -0
  68. flowtask/components/FilterIf.py +284 -0
  69. flowtask/components/FilterRows/FilterRows.py +200 -0
  70. flowtask/components/FilterRows/__init__.py +10 -0
  71. flowtask/components/FilterRows/functions.py +4 -0
  72. flowtask/components/GCSToBigQuery.py +103 -0
  73. flowtask/components/GoogleA4.py +150 -0
  74. flowtask/components/GoogleGeoCoding.py +344 -0
  75. flowtask/components/GooglePlaces.py +315 -0
  76. flowtask/components/GoogleSearch.py +539 -0
  77. flowtask/components/HTTPClient.py +268 -0
  78. flowtask/components/ICIMS.py +146 -0
  79. flowtask/components/IF.py +179 -0
  80. flowtask/components/IcimsFolderCopy.py +173 -0
  81. flowtask/components/ImageFeatures/__init__.py +5 -0
  82. flowtask/components/ImageFeatures/process.py +233 -0
  83. flowtask/components/IteratorBase.py +251 -0
  84. flowtask/components/LangchainLoader/__init__.py +5 -0
  85. flowtask/components/LangchainLoader/loader.py +194 -0
  86. flowtask/components/LangchainLoader/loaders/__init__.py +22 -0
  87. flowtask/components/LangchainLoader/loaders/abstract.py +362 -0
  88. flowtask/components/LangchainLoader/loaders/basepdf.py +50 -0
  89. flowtask/components/LangchainLoader/loaders/docx.py +91 -0
  90. flowtask/components/LangchainLoader/loaders/html.py +119 -0
  91. flowtask/components/LangchainLoader/loaders/pdfblocks.py +146 -0
  92. flowtask/components/LangchainLoader/loaders/pdfmark.py +79 -0
  93. flowtask/components/LangchainLoader/loaders/pdftables.py +135 -0
  94. flowtask/components/LangchainLoader/loaders/qa.py +67 -0
  95. flowtask/components/LangchainLoader/loaders/txt.py +55 -0
  96. flowtask/components/LeadIQ.py +650 -0
  97. flowtask/components/Loop.py +253 -0
  98. flowtask/components/Lowes.py +334 -0
  99. flowtask/components/MS365Usage.py +156 -0
  100. flowtask/components/MSTeamsMessages.py +320 -0
  101. flowtask/components/MarketClustering.py +1051 -0
  102. flowtask/components/MergeFiles.py +362 -0
  103. flowtask/components/MilvusOutput.py +87 -0
  104. flowtask/components/NearByStores.py +175 -0
  105. flowtask/components/NetworkNinja/__init__.py +6 -0
  106. flowtask/components/NetworkNinja/models/__init__.py +52 -0
  107. flowtask/components/NetworkNinja/models/abstract.py +177 -0
  108. flowtask/components/NetworkNinja/models/account.py +39 -0
  109. flowtask/components/NetworkNinja/models/client.py +19 -0
  110. flowtask/components/NetworkNinja/models/district.py +14 -0
  111. flowtask/components/NetworkNinja/models/events.py +101 -0
  112. flowtask/components/NetworkNinja/models/forms.py +499 -0
  113. flowtask/components/NetworkNinja/models/market.py +16 -0
  114. flowtask/components/NetworkNinja/models/organization.py +34 -0
  115. flowtask/components/NetworkNinja/models/photos.py +125 -0
  116. flowtask/components/NetworkNinja/models/project.py +44 -0
  117. flowtask/components/NetworkNinja/models/region.py +28 -0
  118. flowtask/components/NetworkNinja/models/store.py +203 -0
  119. flowtask/components/NetworkNinja/models/user.py +151 -0
  120. flowtask/components/NetworkNinja/router.py +854 -0
  121. flowtask/components/Odoo.py +175 -0
  122. flowtask/components/OdooInjector.py +192 -0
  123. flowtask/components/OpenFromXML.py +126 -0
  124. flowtask/components/OpenWeather.py +41 -0
  125. flowtask/components/OpenWithBase.py +616 -0
  126. flowtask/components/OpenWithPandas.py +715 -0
  127. flowtask/components/PGPDecrypt.py +199 -0
  128. flowtask/components/PandasIterator.py +187 -0
  129. flowtask/components/PandasToFile.py +189 -0
  130. flowtask/components/Paradox.py +339 -0
  131. flowtask/components/ParamIterator.py +117 -0
  132. flowtask/components/ParseHTML.py +84 -0
  133. flowtask/components/PlacerStores.py +249 -0
  134. flowtask/components/Pokemon.py +507 -0
  135. flowtask/components/PositiveBot.py +62 -0
  136. flowtask/components/PowerPointSlide.py +400 -0
  137. flowtask/components/PrintMessage.py +127 -0
  138. flowtask/components/ProductCompetitors/__init__.py +5 -0
  139. flowtask/components/ProductCompetitors/parsers/__init__.py +7 -0
  140. flowtask/components/ProductCompetitors/parsers/base.py +72 -0
  141. flowtask/components/ProductCompetitors/parsers/bestbuy.py +86 -0
  142. flowtask/components/ProductCompetitors/parsers/lowes.py +103 -0
  143. flowtask/components/ProductCompetitors/scrapper.py +155 -0
  144. flowtask/components/ProductCompliant.py +169 -0
  145. flowtask/components/ProductInfo/__init__.py +1 -0
  146. flowtask/components/ProductInfo/parsers/__init__.py +5 -0
  147. flowtask/components/ProductInfo/parsers/base.py +83 -0
  148. flowtask/components/ProductInfo/parsers/brother.py +97 -0
  149. flowtask/components/ProductInfo/parsers/canon.py +167 -0
  150. flowtask/components/ProductInfo/parsers/epson.py +118 -0
  151. flowtask/components/ProductInfo/parsers/hp.py +131 -0
  152. flowtask/components/ProductInfo/parsers/samsung.py +97 -0
  153. flowtask/components/ProductInfo/scraper.py +319 -0
  154. flowtask/components/ProductPricing.py +118 -0
  155. flowtask/components/QS.py +261 -0
  156. flowtask/components/QSBase.py +201 -0
  157. flowtask/components/QueryIterator.py +273 -0
  158. flowtask/components/QueryToInsert.py +327 -0
  159. flowtask/components/QueryToPandas.py +432 -0
  160. flowtask/components/RESTClient.py +195 -0
  161. flowtask/components/RethinkDBQuery.py +189 -0
  162. flowtask/components/Rsync.py +74 -0
  163. flowtask/components/RunSSH.py +59 -0
  164. flowtask/components/RunShell.py +71 -0
  165. flowtask/components/SalesForce.py +20 -0
  166. flowtask/components/SaveImageBank/__init__.py +257 -0
  167. flowtask/components/SchedulingVisits.py +592 -0
  168. flowtask/components/ScrapPage.py +216 -0
  169. flowtask/components/ScrapSearch.py +79 -0
  170. flowtask/components/SendNotify.py +257 -0
  171. flowtask/components/SentimentAnalysis.py +694 -0
  172. flowtask/components/ServiceScrapper/__init__.py +5 -0
  173. flowtask/components/ServiceScrapper/parsers/__init__.py +1 -0
  174. flowtask/components/ServiceScrapper/parsers/base.py +94 -0
  175. flowtask/components/ServiceScrapper/parsers/costco.py +93 -0
  176. flowtask/components/ServiceScrapper/scrapper.py +199 -0
  177. flowtask/components/SetVariables.py +156 -0
  178. flowtask/components/SubTask.py +182 -0
  179. flowtask/components/SuiteCRM.py +48 -0
  180. flowtask/components/Switch.py +175 -0
  181. flowtask/components/TableBase.py +148 -0
  182. flowtask/components/TableDelete.py +312 -0
  183. flowtask/components/TableInput.py +143 -0
  184. flowtask/components/TableOutput/TableOutput.py +384 -0
  185. flowtask/components/TableOutput/__init__.py +3 -0
  186. flowtask/components/TableSchema.py +534 -0
  187. flowtask/components/Target.py +223 -0
  188. flowtask/components/ThumbnailGenerator.py +156 -0
  189. flowtask/components/ToPandas.py +67 -0
  190. flowtask/components/TransformRows/TransformRows.py +507 -0
  191. flowtask/components/TransformRows/__init__.py +9 -0
  192. flowtask/components/TransformRows/functions.py +559 -0
  193. flowtask/components/TransposeRows.py +176 -0
  194. flowtask/components/UPCDatabase.py +86 -0
  195. flowtask/components/UnGzip.py +171 -0
  196. flowtask/components/Uncompress.py +172 -0
  197. flowtask/components/UniqueRows.py +126 -0
  198. flowtask/components/Unzip.py +107 -0
  199. flowtask/components/UpdateOperationalVars.py +147 -0
  200. flowtask/components/UploadTo.py +299 -0
  201. flowtask/components/UploadToS3.py +136 -0
  202. flowtask/components/UploadToSFTP.py +160 -0
  203. flowtask/components/UploadToSharepoint.py +205 -0
  204. flowtask/components/UserFunc.py +122 -0
  205. flowtask/components/VivaTracker.py +140 -0
  206. flowtask/components/WSDLClient.py +123 -0
  207. flowtask/components/Wait.py +18 -0
  208. flowtask/components/Walmart.py +199 -0
  209. flowtask/components/Workplace.py +134 -0
  210. flowtask/components/XMLToPandas.py +267 -0
  211. flowtask/components/Zammad/__init__.py +41 -0
  212. flowtask/components/Zammad/models.py +0 -0
  213. flowtask/components/ZoomInfoScraper.py +409 -0
  214. flowtask/components/__init__.py +104 -0
  215. flowtask/components/abstract.py +18 -0
  216. flowtask/components/flow.py +530 -0
  217. flowtask/components/google.py +335 -0
  218. flowtask/components/group.py +221 -0
  219. flowtask/components/py.typed +0 -0
  220. flowtask/components/reviewscrap.py +132 -0
  221. flowtask/components/tAutoincrement.py +117 -0
  222. flowtask/components/tConcat.py +109 -0
  223. flowtask/components/tExplode.py +119 -0
  224. flowtask/components/tFilter.py +184 -0
  225. flowtask/components/tGroup.py +236 -0
  226. flowtask/components/tJoin.py +270 -0
  227. flowtask/components/tMap/__init__.py +9 -0
  228. flowtask/components/tMap/functions.py +54 -0
  229. flowtask/components/tMap/tMap.py +450 -0
  230. flowtask/components/tMelt.py +112 -0
  231. flowtask/components/tMerge.py +114 -0
  232. flowtask/components/tOrder.py +93 -0
  233. flowtask/components/tPandas.py +94 -0
  234. flowtask/components/tPivot.py +71 -0
  235. flowtask/components/tPluckCols.py +76 -0
  236. flowtask/components/tUnnest.py +82 -0
  237. flowtask/components/user.py +401 -0
  238. flowtask/conf.py +457 -0
  239. flowtask/download.py +102 -0
  240. flowtask/events/__init__.py +11 -0
  241. flowtask/events/events/__init__.py +20 -0
  242. flowtask/events/events/abstract.py +95 -0
  243. flowtask/events/events/alerts/__init__.py +362 -0
  244. flowtask/events/events/alerts/colfunctions.py +131 -0
  245. flowtask/events/events/alerts/functions.py +158 -0
  246. flowtask/events/events/dummy.py +12 -0
  247. flowtask/events/events/exec.py +124 -0
  248. flowtask/events/events/file/__init__.py +7 -0
  249. flowtask/events/events/file/base.py +51 -0
  250. flowtask/events/events/file/copy.py +23 -0
  251. flowtask/events/events/file/delete.py +16 -0
  252. flowtask/events/events/interfaces/__init__.py +9 -0
  253. flowtask/events/events/interfaces/client.py +67 -0
  254. flowtask/events/events/interfaces/credentials.py +28 -0
  255. flowtask/events/events/interfaces/notifications.py +58 -0
  256. flowtask/events/events/jira.py +122 -0
  257. flowtask/events/events/log.py +26 -0
  258. flowtask/events/events/logerr.py +52 -0
  259. flowtask/events/events/notify.py +59 -0
  260. flowtask/events/events/notify_event.py +160 -0
  261. flowtask/events/events/publish.py +54 -0
  262. flowtask/events/events/sendfile.py +104 -0
  263. flowtask/events/events/task.py +97 -0
  264. flowtask/events/events/teams.py +98 -0
  265. flowtask/events/events/webhook.py +58 -0
  266. flowtask/events/manager.py +287 -0
  267. flowtask/exceptions.c +39393 -0
  268. flowtask/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  269. flowtask/extensions/__init__.py +3 -0
  270. flowtask/extensions/abstract.py +82 -0
  271. flowtask/extensions/logging/__init__.py +65 -0
  272. flowtask/hooks/__init__.py +9 -0
  273. flowtask/hooks/actions/__init__.py +22 -0
  274. flowtask/hooks/actions/abstract.py +66 -0
  275. flowtask/hooks/actions/dummy.py +23 -0
  276. flowtask/hooks/actions/jira.py +74 -0
  277. flowtask/hooks/actions/rest.py +320 -0
  278. flowtask/hooks/actions/sampledata.py +37 -0
  279. flowtask/hooks/actions/sensor.py +23 -0
  280. flowtask/hooks/actions/task.py +9 -0
  281. flowtask/hooks/actions/ticket.py +37 -0
  282. flowtask/hooks/actions/zammad.py +55 -0
  283. flowtask/hooks/hook.py +62 -0
  284. flowtask/hooks/models.py +17 -0
  285. flowtask/hooks/service.py +187 -0
  286. flowtask/hooks/step.py +91 -0
  287. flowtask/hooks/types/__init__.py +23 -0
  288. flowtask/hooks/types/base.py +129 -0
  289. flowtask/hooks/types/brokers/__init__.py +11 -0
  290. flowtask/hooks/types/brokers/base.py +54 -0
  291. flowtask/hooks/types/brokers/mqtt.py +35 -0
  292. flowtask/hooks/types/brokers/rabbitmq.py +82 -0
  293. flowtask/hooks/types/brokers/redis.py +83 -0
  294. flowtask/hooks/types/brokers/sqs.py +44 -0
  295. flowtask/hooks/types/fs.py +232 -0
  296. flowtask/hooks/types/http.py +49 -0
  297. flowtask/hooks/types/imap.py +200 -0
  298. flowtask/hooks/types/jira.py +279 -0
  299. flowtask/hooks/types/mail.py +205 -0
  300. flowtask/hooks/types/postgres.py +98 -0
  301. flowtask/hooks/types/responses/__init__.py +8 -0
  302. flowtask/hooks/types/responses/base.py +5 -0
  303. flowtask/hooks/types/sharepoint.py +288 -0
  304. flowtask/hooks/types/ssh.py +141 -0
  305. flowtask/hooks/types/tagged.py +59 -0
  306. flowtask/hooks/types/upload.py +85 -0
  307. flowtask/hooks/types/watch.py +71 -0
  308. flowtask/hooks/types/web.py +36 -0
  309. flowtask/interfaces/AzureClient.py +137 -0
  310. flowtask/interfaces/AzureGraph.py +839 -0
  311. flowtask/interfaces/Boto3Client.py +326 -0
  312. flowtask/interfaces/DropboxClient.py +173 -0
  313. flowtask/interfaces/ExcelHandler.py +94 -0
  314. flowtask/interfaces/FTPClient.py +131 -0
  315. flowtask/interfaces/GoogleCalendar.py +201 -0
  316. flowtask/interfaces/GoogleClient.py +133 -0
  317. flowtask/interfaces/GoogleDrive.py +127 -0
  318. flowtask/interfaces/GoogleGCS.py +89 -0
  319. flowtask/interfaces/GoogleGeocoding.py +93 -0
  320. flowtask/interfaces/GoogleLang.py +114 -0
  321. flowtask/interfaces/GooglePub.py +61 -0
  322. flowtask/interfaces/GoogleSheet.py +68 -0
  323. flowtask/interfaces/IMAPClient.py +137 -0
  324. flowtask/interfaces/O365Calendar.py +113 -0
  325. flowtask/interfaces/O365Client.py +220 -0
  326. flowtask/interfaces/OneDrive.py +284 -0
  327. flowtask/interfaces/Outlook.py +155 -0
  328. flowtask/interfaces/ParrotBot.py +130 -0
  329. flowtask/interfaces/SSHClient.py +378 -0
  330. flowtask/interfaces/Sharepoint.py +496 -0
  331. flowtask/interfaces/__init__.py +36 -0
  332. flowtask/interfaces/azureauth.py +119 -0
  333. flowtask/interfaces/cache.py +201 -0
  334. flowtask/interfaces/client.py +82 -0
  335. flowtask/interfaces/compress.py +525 -0
  336. flowtask/interfaces/credentials.py +124 -0
  337. flowtask/interfaces/d2l.py +239 -0
  338. flowtask/interfaces/databases/__init__.py +5 -0
  339. flowtask/interfaces/databases/db.py +223 -0
  340. flowtask/interfaces/databases/documentdb.py +55 -0
  341. flowtask/interfaces/databases/rethink.py +39 -0
  342. flowtask/interfaces/dataframes/__init__.py +11 -0
  343. flowtask/interfaces/dataframes/abstract.py +21 -0
  344. flowtask/interfaces/dataframes/arrow.py +71 -0
  345. flowtask/interfaces/dataframes/dt.py +69 -0
  346. flowtask/interfaces/dataframes/pandas.py +167 -0
  347. flowtask/interfaces/dataframes/polars.py +60 -0
  348. flowtask/interfaces/db.py +263 -0
  349. flowtask/interfaces/env.py +46 -0
  350. flowtask/interfaces/func.py +137 -0
  351. flowtask/interfaces/http.py +1780 -0
  352. flowtask/interfaces/locale.py +40 -0
  353. flowtask/interfaces/log.py +75 -0
  354. flowtask/interfaces/mask.py +143 -0
  355. flowtask/interfaces/notification.py +154 -0
  356. flowtask/interfaces/playwright.py +339 -0
  357. flowtask/interfaces/powerpoint.py +368 -0
  358. flowtask/interfaces/py.typed +0 -0
  359. flowtask/interfaces/qs.py +376 -0
  360. flowtask/interfaces/result.py +87 -0
  361. flowtask/interfaces/selenium_service.py +779 -0
  362. flowtask/interfaces/smartsheet.py +154 -0
  363. flowtask/interfaces/stat.py +39 -0
  364. flowtask/interfaces/task.py +96 -0
  365. flowtask/interfaces/template.py +118 -0
  366. flowtask/interfaces/vectorstores/__init__.py +1 -0
  367. flowtask/interfaces/vectorstores/abstract.py +133 -0
  368. flowtask/interfaces/vectorstores/milvus.py +669 -0
  369. flowtask/interfaces/zammad.py +107 -0
  370. flowtask/models.py +193 -0
  371. flowtask/parsers/__init__.py +15 -0
  372. flowtask/parsers/_yaml.c +11978 -0
  373. flowtask/parsers/_yaml.cpython-310-x86_64-linux-gnu.so +0 -0
  374. flowtask/parsers/argparser.py +235 -0
  375. flowtask/parsers/base.c +15155 -0
  376. flowtask/parsers/base.cpython-310-x86_64-linux-gnu.so +0 -0
  377. flowtask/parsers/json.c +11968 -0
  378. flowtask/parsers/json.cpython-310-x86_64-linux-gnu.so +0 -0
  379. flowtask/parsers/maps.py +49 -0
  380. flowtask/parsers/toml.c +11968 -0
  381. flowtask/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  382. flowtask/plugins/__init__.py +16 -0
  383. flowtask/plugins/components/__init__.py +0 -0
  384. flowtask/plugins/handler/__init__.py +45 -0
  385. flowtask/plugins/importer.py +31 -0
  386. flowtask/plugins/sources/__init__.py +0 -0
  387. flowtask/runner.py +283 -0
  388. flowtask/scheduler/__init__.py +9 -0
  389. flowtask/scheduler/functions.py +493 -0
  390. flowtask/scheduler/handlers/__init__.py +8 -0
  391. flowtask/scheduler/handlers/manager.py +504 -0
  392. flowtask/scheduler/handlers/models.py +58 -0
  393. flowtask/scheduler/handlers/service.py +72 -0
  394. flowtask/scheduler/notifications.py +65 -0
  395. flowtask/scheduler/scheduler.py +993 -0
  396. flowtask/services/__init__.py +0 -0
  397. flowtask/services/bots/__init__.py +0 -0
  398. flowtask/services/bots/telegram.py +264 -0
  399. flowtask/services/files/__init__.py +11 -0
  400. flowtask/services/files/manager.py +522 -0
  401. flowtask/services/files/model.py +37 -0
  402. flowtask/services/files/service.py +767 -0
  403. flowtask/services/jira/__init__.py +3 -0
  404. flowtask/services/jira/jira_actions.py +191 -0
  405. flowtask/services/tasks/__init__.py +13 -0
  406. flowtask/services/tasks/launcher.py +213 -0
  407. flowtask/services/tasks/manager.py +323 -0
  408. flowtask/services/tasks/service.py +275 -0
  409. flowtask/services/tasks/task_manager.py +376 -0
  410. flowtask/services/tasks/tasks.py +155 -0
  411. flowtask/storages/__init__.py +16 -0
  412. flowtask/storages/exceptions.py +12 -0
  413. flowtask/storages/files/__init__.py +8 -0
  414. flowtask/storages/files/abstract.py +29 -0
  415. flowtask/storages/files/filesystem.py +66 -0
  416. flowtask/storages/tasks/__init__.py +19 -0
  417. flowtask/storages/tasks/abstract.py +26 -0
  418. flowtask/storages/tasks/database.py +33 -0
  419. flowtask/storages/tasks/filesystem.py +108 -0
  420. flowtask/storages/tasks/github.py +119 -0
  421. flowtask/storages/tasks/memory.py +45 -0
  422. flowtask/storages/tasks/row.py +25 -0
  423. flowtask/tasks/__init__.py +0 -0
  424. flowtask/tasks/abstract.py +526 -0
  425. flowtask/tasks/command.py +118 -0
  426. flowtask/tasks/pile.py +486 -0
  427. flowtask/tasks/py.typed +0 -0
  428. flowtask/tasks/task.py +778 -0
  429. flowtask/template/__init__.py +161 -0
  430. flowtask/tests.py +257 -0
  431. flowtask/types/__init__.py +8 -0
  432. flowtask/types/typedefs.c +11347 -0
  433. flowtask/types/typedefs.cpython-310-x86_64-linux-gnu.so +0 -0
  434. flowtask/utils/__init__.py +24 -0
  435. flowtask/utils/constants.py +117 -0
  436. flowtask/utils/encoders.py +21 -0
  437. flowtask/utils/executor.py +112 -0
  438. flowtask/utils/functions.cpp +14280 -0
  439. flowtask/utils/functions.cpython-310-x86_64-linux-gnu.so +0 -0
  440. flowtask/utils/json.cpp +13349 -0
  441. flowtask/utils/json.cpython-310-x86_64-linux-gnu.so +0 -0
  442. flowtask/utils/mail.py +63 -0
  443. flowtask/utils/parseqs.c +13324 -0
  444. flowtask/utils/parserqs.cpython-310-x86_64-linux-gnu.so +0 -0
  445. flowtask/utils/stats.py +308 -0
  446. flowtask/utils/transformations.py +74 -0
  447. flowtask/utils/uv.py +12 -0
  448. flowtask/utils/validators.py +97 -0
  449. flowtask/version.py +11 -0
  450. flowtask-5.8.4.dist-info/LICENSE +201 -0
  451. flowtask-5.8.4.dist-info/METADATA +209 -0
  452. flowtask-5.8.4.dist-info/RECORD +470 -0
  453. flowtask-5.8.4.dist-info/WHEEL +6 -0
  454. flowtask-5.8.4.dist-info/entry_points.txt +3 -0
  455. flowtask-5.8.4.dist-info/top_level.txt +2 -0
  456. plugins/components/CreateQR.py +39 -0
  457. plugins/components/TestComponent.py +28 -0
  458. plugins/components/Use1.py +13 -0
  459. plugins/components/Workplace.py +117 -0
  460. plugins/components/__init__.py +3 -0
  461. plugins/sources/__init__.py +0 -0
  462. plugins/sources/get_populartimes.py +78 -0
  463. plugins/sources/google.py +150 -0
  464. plugins/sources/hubspot.py +679 -0
  465. plugins/sources/icims.py +679 -0
  466. plugins/sources/mobileinsight.py +501 -0
  467. plugins/sources/newrelic.py +262 -0
  468. plugins/sources/uap.py +268 -0
  469. plugins/sources/venu.py +244 -0
  470. plugins/sources/vocinity.py +314 -0
@@ -0,0 +1,216 @@
1
+ """
2
+ Scrapping a Web Page Using Selenium + ChromeDriver + BeautifulSoup.
3
+
4
+
5
+ Example:
6
+
7
+ ```yaml
8
+ ScrapPage:
9
+ url: https://www.consumeraffairs.com/insurance/assurant-phone-insurance.html?page=2#sort=recent
10
+ rotate_ua: true
11
+ use_selenium: true
12
+ use_proxy: true
13
+ paid_proxy: true
14
+ as_mobile: false
15
+ timeout: 60
16
+ wait_until:
17
+ - - class_name
18
+ - js-rvw
19
+ screenshot:
20
+ filename: reviews_page.png
21
+ directory: /home/ubuntu/symbits/ejemplo/screenshots/
22
+ outputs:
23
+ - scraped_content
24
+ - screenshot_path
25
+ ```
26
+
27
+ """
28
+ import asyncio
29
+ from collections.abc import Callable
30
+ from pathlib import Path, PurePath
31
+ from typing import Optional
32
+ from navconfig import BASE_DIR
33
+ # Internals
34
+ from ..exceptions import (
35
+ ComponentError,
36
+ DataNotFound,
37
+ TimeOutError
38
+ )
39
+ from .flow import FlowComponent
40
+ from ..interfaces import HTTPService, SeleniumService
41
+
42
+
43
+ class ScrapPage(SeleniumService, HTTPService, FlowComponent):
44
+ """ScrapPage.
45
+ Scrapping a Web Page using Selenium.
46
+ """
47
+ def __init__(
48
+ self,
49
+ loop: asyncio.AbstractEventLoop = None,
50
+ job: Callable = None,
51
+ stat: Callable = None,
52
+ **kwargs,
53
+ ):
54
+ """Init Method."""
55
+ self.url: str = kwargs.get("url", None)
56
+ self.urls: list = kwargs.get('urls', [])
57
+ self.find_elements: list = kwargs.get('find_elements', [])
58
+ self.rotate_ua: bool = True
59
+ kwargs['rotate_ua'] = True # Forcing UA Rotation.
60
+ self.use_selenium: bool = kwargs.pop(
61
+ "use_selenium",
62
+ False
63
+ )
64
+ # URL Function: generate the URL based on a function:
65
+ self.url_function: str = kwargs.pop('url_function', None)
66
+ # Return the Driver (avoid closing the Driver at the end of the process).
67
+ self.return_driver: bool = kwargs.pop('return_driver', False)
68
+ super(ScrapPage, self).__init__(
69
+ loop=loop,
70
+ job=job,
71
+ stat=stat,
72
+ **kwargs
73
+ )
74
+ # Fix the Headers for Scrapping:
75
+ self.headers: dict = {
76
+ "Host": self.extract_host(self.url),
77
+ **self.headers
78
+ }
79
+
80
+ async def start(self, **kwargs) -> bool:
81
+ await super(ScrapPage, self).start(**kwargs)
82
+ if self.use_selenium is True:
83
+ await self.get_driver()
84
+ # Generate a URL based on a URL Function:
85
+ if self.url_function:
86
+ fn = getattr(self, self.url_function, None)
87
+ if fn:
88
+ self.url = await fn()
89
+ return True
90
+
91
+ async def close(self, **kwargs) -> bool:
92
+ if self.use_selenium is True:
93
+ if self.return_driver is False:
94
+ self.close_driver()
95
+ return True
96
+
97
+ async def run_http(self):
98
+ """Run the Scrapping Tool Using HTTPx."""
99
+ result, error = await self.session(
100
+ url=self.url,
101
+ method=self.method,
102
+ headers=self.headers,
103
+ cookies=self.cookies,
104
+ follow_redirects=True,
105
+ use_proxy=self.use_proxy
106
+ )
107
+ if error:
108
+ raise ComponentError(
109
+ f"Error running HTTP: {error}"
110
+ )
111
+ if not result:
112
+ raise DataNotFound(
113
+ f"No content on URL {self.url}"
114
+ )
115
+ return result
116
+
117
+ async def run_selenium(self):
118
+ """Run the Scrapping Tool Using Selenium."""
119
+ try:
120
+ await self.get_page(self.url, self.cookies)
121
+ found_elements = None
122
+ file = None
123
+ content = None
124
+ if self.inner_tag:
125
+ content = self.driver().find_element(*self.inner_tag).get_attribute('innerHTML')
126
+ else:
127
+ content = self.driver().page_source
128
+ if hasattr(self, 'screenshot'):
129
+ # capture an screenshot from the page and save it (and returning as binary as well)
130
+ filename = self.screenshot.get('filename', 'screenshot.png')
131
+ directory = Path(self.screenshot.get(
132
+ 'directory', BASE_DIR.joinpath('static', 'images', 'screenshots')
133
+ ))
134
+ if not directory.is_absolute():
135
+ directory = BASE_DIR.joinpath('static', 'images', directory)
136
+ if directory.exists() is False:
137
+ directory.mkdir(parents=True, exist_ok=True)
138
+ # Take the screenshot
139
+ file = directory.joinpath(filename)
140
+ self.save_screenshot(str(file))
141
+ if self.find_elements:
142
+ # For the main content, fallback to page_source:
143
+ content = self.driver().page_source
144
+ try:
145
+ print('FINDING > ', self.find_elements)
146
+ elements = self.driver().find_elements(*self.find_elements)
147
+ found_elements = elements
148
+ except Exception as exc:
149
+ # Log the exception as a warning instead of raising it
150
+ self.logger.warning(
151
+ f"Unable to find elements with locator {self.find_elements}: {exc}"
152
+ )
153
+ found_elements = []
154
+ # Return the content of the page.
155
+ return content, file, found_elements
156
+ except (TimeOutError, ComponentError):
157
+ raise
158
+ except Exception as exc:
159
+ raise ComponentError(
160
+ f"Error running Selenium: {exc}"
161
+ )
162
+
163
+ def _build_result_content(self, content: str, screenshot: PurePath, found_elements: Optional[list] = None) -> dict:
164
+ """Build the Result Content."""
165
+ soup = self.get_soup(content)
166
+ _xml, _html = self.get_etree(content)
167
+ result = {
168
+ "raw": content,
169
+ "soup": soup,
170
+ "html": _html,
171
+ "xml": _xml,
172
+ "screenshot": screenshot
173
+ }
174
+ if found_elements is not None:
175
+ result["found_elements"] = found_elements
176
+ return result
177
+
178
+ async def run(self):
179
+ """Run the Scrapping Tool."""
180
+ self._result = None
181
+ screenshot = None
182
+ found_elements = None
183
+ try:
184
+ if self.use_selenium is True:
185
+ if self.urls:
186
+ results = []
187
+ for url in self.urls:
188
+ self.url = url
189
+ self.headers['Host'] = self.extract_host(url)
190
+ self.headers['Referer'] = url
191
+ content, screenshot, found_elements = await self.run_selenium()
192
+ result = self._build_result_content(content, screenshot, found_elements)
193
+ results.append(
194
+ {"url": url, "content": result}
195
+ )
196
+ self._result = results
197
+ return results
198
+ else:
199
+ content, screenshot, found_elements = await self.run_selenium()
200
+ else:
201
+ content = await self.run_http()
202
+ if not content:
203
+ raise DataNotFound(
204
+ f"No content on URL {self.url}"
205
+ )
206
+ except ComponentError:
207
+ raise
208
+ except Exception as exc:
209
+ raise ComponentError(
210
+ f"Error running ScrapPage: {exc}"
211
+ )
212
+ if self.return_driver is True:
213
+ self._result = self.driver()
214
+ else:
215
+ self._result = self._build_result_content(content, screenshot, found_elements)
216
+ return self._result
@@ -0,0 +1,79 @@
1
+ from bs4 import BeautifulSoup
2
+ from .ScrapPage import ScrapPage
3
+ from ..exceptions import ComponentError
4
+
5
+
6
+ class ScrapSearch(ScrapPage):
7
+ """Search by a Product, retrieve the URL (based on rules) and scrap the page."""
8
+ # TODO: Idea is for making the search functions pluggable.
9
+ def __init__(self, **kwargs):
10
+ self.find_element: tuple = kwargs.pop('find_element', ('li', {'class': ['sku-item']}))
11
+ super().__init__(**kwargs)
12
+ self.product_sku: str = kwargs.pop('product_sku', None)
13
+ self.brand: str = kwargs.pop('brand', None)
14
+
15
+ async def _bby_products(self):
16
+ front_url = "https://www.bestbuy.com/site/searchpage.jsp?cp="
17
+ middle_url = "&searchType=search&st="
18
+ page_count = 1
19
+ # TODO: Get the Brand and Model from the Component.
20
+ model = self.product_sku
21
+ brand = self.brand
22
+ search_term = f'{brand}%20{model}'
23
+ end_url = "&_dyncharset=UTF-8&id=pcat17071&type=page&sc=Global&nrp=&sp=&qp=&list=n&af=true&iht=y&usc=All%20Categories&ks=960&keys=keys" # noqa
24
+ url = front_url + str(page_count) + middle_url + search_term + end_url
25
+ print('SEARCH URL: ', url)
26
+ return url
27
+
28
+ async def _search_bby_products(self, content: str) -> str:
29
+ soup = BeautifulSoup(content, 'html.parser')
30
+ # Find all elements with class "sku-item"
31
+ product_items = soup.find_all(*self.find_element)
32
+ # Iterate over each product item
33
+ url = None
34
+ for item in product_items:
35
+ # Get the "data-sku-id" attribute
36
+ sku_id = item.get("data-sku-id")
37
+ # Check if the SKU ID matches your target SKU ID
38
+ if sku_id == self.product_sku:
39
+ print(f"Found matching SKU ID: {sku_id}")
40
+ # Now look for the child with class "sku-title"
41
+ pd = item.find('h4', {'class': ['sku-title']})
42
+ anchor = pd.a
43
+ url = "https://www.bestbuy.com{url}".format(
44
+ url=anchor['href']
45
+ )
46
+ print('Product URL: ', url)
47
+ return url
48
+
49
+ async def run(self):
50
+ # Run works differently for ScrapPage:
51
+ self._result = None
52
+ screenshot = None
53
+ # 1. Get the Product List URL
54
+ fn = getattr(self, f"_{self.url_function}", None)
55
+ if not fn:
56
+ raise ComponentError(
57
+ f"Function {self.url_function} not found."
58
+ )
59
+ url = await fn()
60
+ if self.use_selenium is True:
61
+ await self.get_page(url, self.cookies)
62
+ content = self.driver().page_source
63
+ # 2. Search the Product
64
+ search_fn = getattr(self, f"_search_{self.url_function}", None)
65
+ if search_fn:
66
+ url = await search_fn(content)
67
+ if url:
68
+ # 3. Get the URL
69
+ self.url = url
70
+ # 4. Run the Scrapping Tool to extract the Product page.
71
+ content, screenshot = await self.run_selenium()
72
+ if self.return_driver is True:
73
+ self._result = self.driver()
74
+ else:
75
+ self._result = self._build_result_content(
76
+ content,
77
+ screenshot
78
+ )
79
+ return self._result
@@ -0,0 +1,257 @@
1
+ import os
2
+ import asyncio
3
+ from typing import Dict, List
4
+ from collections.abc import Callable, Iterable
5
+ from pathlib import Path
6
+ from navconfig.logging import logging
7
+ from notify import Notify
8
+ from notify.models import Actor
9
+ from ..exceptions import ComponentError, FileNotFound
10
+ from .flow import FlowComponent
11
+ from ..interfaces import DBSupport
12
+
13
+
14
+ def expand_path(filename: str) -> Iterable[Path]:
15
+ p = Path(filename)
16
+ return Path(p.parent).expanduser().glob(p.name)
17
+
18
+
19
+ class SendNotify(DBSupport, FlowComponent):
20
+ """
21
+ SendNotify
22
+
23
+ Overview
24
+
25
+ The SendNotify class is a component for sending notifications to a list of recipients via various
26
+ channels (e.g., email) using the Notify component. It supports adding attachments, templating messages
27
+ with masked variables, and utilizing custom credentials for authentication.
28
+
29
+ .. table:: Properties
30
+ :widths: auto
31
+
32
+ +----------------+----------+-----------+----------------------------------------------------------------------+
33
+ | Name | Required | Summary |
34
+ +----------------+----------+-----------+----------------------------------------------------------------------+
35
+ | via | Yes | The method for sending the notification, e.g., "email". |
36
+ +----------------+----------+-----------+----------------------------------------------------------------------+
37
+ | account | Yes | A dictionary with server credentials, including `host`, `port`, |
38
+ | | | `username`, and `password`. |
39
+ +----------------+----------+-----------+----------------------------------------------------------------------+
40
+ | recipients | Yes | List of dictionaries with target user details for notification. |
41
+ +----------------+----------+-----------+----------------------------------------------------------------------+
42
+ | list | No | Optional mailing list name for retrieving recipients from the database. |
43
+ +----------------+----------+-----------+----------------------------------------------------------------------+
44
+ | attachments | No | List of file paths for attachments to include in the notification. |
45
+ +----------------+----------+-----------+----------------------------------------------------------------------+
46
+ | message | Yes | Dictionary with the notification message content, supporting template variables. |
47
+ +----------------+----------+-----------+----------------------------------------------------------------------+
48
+
49
+ Returns
50
+
51
+ This component returns the input data after sending the notification. Metrics are recorded for each
52
+ successful send, with details on recipients and the message content. If any specified attachment file
53
+ is missing, a `FileNotFound` exception is raised. If there are errors in setting up or sending the
54
+ notification, a `ComponentError` is raised with descriptive messages.
55
+
56
+
57
+ Example:
58
+
59
+ ```yaml
60
+ SendNotify:
61
+ via: email
62
+ account:
63
+ hostname: NAVIGATOR_ALERT_EMAIL_HOSTNAME
64
+ port: NAVIGATOR_ALERT_EMAIL_PORT
65
+ password: NAVIGATOR_ALERT_EMAIL_PASSWORD
66
+ username: NAVIGATOR_ALERT_EMAIL_USERNAME
67
+ attachments:
68
+ - /home/ubuntu/symbits/bose/files/report/troc_open_tickets_{today}.csv
69
+ masks:
70
+ '{today}':
71
+ - today
72
+ - mask: '%Y-%m-%d'
73
+ '{yesterday}':
74
+ - yesterday
75
+ - mask: '%Y-%m-%d'
76
+ '{human-today}':
77
+ - today
78
+ - mask: '%m/%d/%Y'
79
+ '{human-yesterday}':
80
+ - yesterday
81
+ - mask: '%m/%d/%Y'
82
+ '#today-timestamp#':
83
+ - current_timestamp
84
+ - tz: America/New_York
85
+ recipients:
86
+ - name: Carlos Rivero
87
+ account:
88
+ address: crivero@trocglobal.com
89
+ - name: Arturo Martinez
90
+ account:
91
+ address: amartinez@trocglobal.com
92
+ - name: Jhoanir Torres
93
+ account:
94
+ address: jhtorres@trocglobal.com
95
+ - name: Steven Greenstein
96
+ account:
97
+ address: sgreenstein@trocglobal.com
98
+ - name: Sabra Pierre
99
+ account:
100
+ address: spierre1@trocglobal.com
101
+ - name: Daniel McGee
102
+ account:
103
+ address: dmcgee@trocglobal.com
104
+ - name: Kile Harris
105
+ account:
106
+ address: kharris10@trocglobal.com
107
+ - name: Gerardo Espinoza
108
+ account:
109
+ address: gespinoza@trocglobal.com
110
+ - name: Christopher Harmon
111
+ account:
112
+ address: charmon@trocglobal.com
113
+ message:
114
+ subject: T-ROC BOSE Break&Fix Open Tickets ({human-today})
115
+ message_content: Please find attached the report generated on {human-today}.This
116
+ is an automated message - please do not reply directly to this email.
117
+ template: email_custom_report.html
118
+ clientName: Bose
119
+ dateGenerated: '{human-today}'
120
+ created_at: '#today-timestamp#'
121
+ ```
122
+
123
+ """ # noqa
124
+
125
+ _credentials: dict = {
126
+ "hostname": str,
127
+ "port": int,
128
+ "username": str,
129
+ "password": str,
130
+ }
131
+
132
+ def __init__(
133
+ self,
134
+ loop: asyncio.AbstractEventLoop = None,
135
+ job: Callable = None,
136
+ stat: Callable = None,
137
+ **kwargs,
138
+ ):
139
+ """Init Method."""
140
+ self.attachments: List = []
141
+ self.list_attachment: List = []
142
+ self.notify: Callable = None
143
+ self.recipients: List = []
144
+ self._recipients: List = []
145
+ self.via: str = "email"
146
+ self.message: Dict = {}
147
+ # renaming account to credentials in kwargs:
148
+ if "account" in kwargs:
149
+ kwargs["credentials"] = kwargs.pop("account")
150
+ super(SendNotify, self).__init__(
151
+ loop=loop,
152
+ job=job,
153
+ stat=stat,
154
+ **kwargs
155
+ )
156
+
157
+ def status_sent(self, recipient, message, result, *args, **kwargs):
158
+ print(
159
+ f"Notification with status {result!s} to {recipient.account!s}"
160
+ )
161
+ logging.info(f"Notification with status {result!s} to {recipient.account!s}")
162
+ status = {"recipient": recipient, "result": result}
163
+ self.add_metric("Sent", status)
164
+
165
+ async def start(self, **kwargs):
166
+ if self.previous:
167
+ self.data = self.input
168
+ await super().start(**kwargs)
169
+ self.processing_credentials()
170
+ # TODO: generate file from dataset (dataframe)
171
+ # using mailing list:
172
+ if hasattr(self, "list"):
173
+ # getting the mailing list:
174
+ lst = self.list
175
+ sql = f"SELECT * FROM troc.get_mailing_list('{lst!s}')"
176
+ try:
177
+ connection = self.get_connection()
178
+ async with await connection.connection() as conn:
179
+ result, error = await conn.query(sql)
180
+ if error:
181
+ raise ComponentError(
182
+ f"CreateReport: Error on Recipients: {error!s}."
183
+ )
184
+ for r in result:
185
+ actor = Actor(**dict(r))
186
+ self._recipients.append(actor)
187
+ except Exception as err:
188
+ logging.exception(err)
189
+ else:
190
+ # determine the recipients:
191
+ try:
192
+ self._recipients = [Actor(**user) for user in self.recipients]
193
+ except Exception as err:
194
+ raise ComponentError(f"Error formatting Recipients: {err}") from err
195
+ if not self._recipients:
196
+ raise ComponentError("SendNotify: Invalid Number of Recipients.")
197
+ if hasattr(self, "masks"):
198
+ for _, attach in enumerate(self.attachments):
199
+ attachment = self.mask_replacement(attach)
200
+ # resolve filenames:
201
+ files = expand_path(attachment)
202
+ for file in files:
203
+ self.list_attachment.append(file)
204
+ # Mask transform of message
205
+ for key, value in self.message.items():
206
+ self.message[key] = self.mask_replacement(value)
207
+ self._logger.notice(
208
+ f"Variable: {key} = {self.message[key]}"
209
+ )
210
+ # Verify if file exists
211
+ for file in self.list_attachment:
212
+ if not file.exists():
213
+ raise FileNotFound(
214
+ f"File doesn't exists: {file}"
215
+ )
216
+ return True
217
+
218
+ async def close(self):
219
+ if self.notify:
220
+ try:
221
+ await self.notify.close()
222
+ except Exception as err:
223
+ print(err)
224
+
225
+ async def run(self):
226
+ """
227
+ Running the Notification over all recipients.
228
+ """
229
+ self._result = self.data # by-pass override data (pass-through)
230
+ if self.data is not None:
231
+ if isinstance(self.data, list):
232
+ self.message['filenames'] = self.data
233
+ elif isinstance(self.data, dict):
234
+ self.message.update(self.data)
235
+
236
+ # create the notify component
237
+ account = {**self.credentials}
238
+
239
+ try:
240
+ self.notify = Notify(self.via, loop=self._loop, **account)
241
+ self.notify.sent = self.status_sent
242
+ except Exception as err:
243
+ raise ComponentError(f"Error Creating Notification App: {err}") from err
244
+ try:
245
+ result = await self.notify.send(
246
+ recipient=self._recipients,
247
+ attachments=self.list_attachment,
248
+ **self.message,
249
+ )
250
+ logging.debug(f"Notification Status: {result}")
251
+ # add metric:
252
+ self.add_metric("Notification", self.message)
253
+ except Exception as err:
254
+ raise ComponentError(f"SendNotify Error: {err}") from err
255
+ if self.data is None:
256
+ return True
257
+ return self._result