{"id":27954128,"url":"https://github.com/sn4k3/updatum","last_synced_at":"2026-01-21T21:12:59.167Z","repository":{"id":291508580,"uuid":"977606052","full_name":"sn4k3/Updatum","owner":"sn4k3","description":"A C# library that enables automatic application updates via GitHub Releases.","archived":false,"fork":false,"pushed_at":"2025-12-30T21:23:44.000Z","size":1527,"stargazers_count":81,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-02T04:39:54.997Z","etag":null,"topics":["autoinstall","autoupdate","autoupdater","csharp","library-update","releases","update-checker","updater","updatum"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sn4k3.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["sn4k3"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://www.paypal.com/donate/?hosted_button_id=3F9DKDNPWEYR6"]}},"created_at":"2025-05-04T15:35:00.000Z","updated_at":"2025-12-30T21:23:47.000Z","dependencies_parsed_at":"2025-07-19T05:16:47.342Z","dependency_job_id":"4809af73-597c-476d-893f-b306e9fa42d6","html_url":"https://github.com/sn4k3/Updatum","commit_stats":null,"previous_names":["sn4k3/updatum"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/sn4k3/Updatum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sn4k3%2FUpdatum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sn4k3%2FUpdatum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sn4k3%2FUpdatum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sn4k3%2FUpdatum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sn4k3","download_url":"https://codeload.github.com/sn4k3/Updatum/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sn4k3%2FUpdatum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28643119,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T18:04:35.752Z","status":"ssl_error","status_checked_at":"2026-01-21T18:03:55.054Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autoinstall","autoupdate","autoupdater","csharp","library-update","releases","update-checker","updater","updatum"],"created_at":"2025-05-07T17:20:15.284Z","updated_at":"2026-01-21T21:12:59.157Z","avatar_url":"https://github.com/sn4k3.png","language":"C#","funding_links":["https://github.com/sponsors/sn4k3","https://www.paypal.com/donate/?hosted_button_id=3F9DKDNPWEYR6"],"categories":[],"sub_categories":[],"readme":"﻿# [![Logo](https://raw.githubusercontent.com/sn4k3/Updatum/main/media/Updatum-32.png)](#) Updatum\n\n[![License](https://img.shields.io/github/license/sn4k3/Updatum?style=for-the-badge)](https://github.com/sn4k3/Updatum/blob/master/LICENSE)\n[![GitHub repo size](https://img.shields.io/github/repo-size/sn4k3/Updatum?style=for-the-badge)](#)\n[![Code size](https://img.shields.io/github/languages/code-size/sn4k3/Updatum?style=for-the-badge)](#)\n[![Nuget](https://img.shields.io/nuget/v/Updatum?style=for-the-badge)](https://www.nuget.org/packages/Updatum)\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/sn4k3?color=red\u0026style=for-the-badge)](https://github.com/sponsors/sn4k3)\n\nUpdatum is a lightweight and easy-to-integrate C# library designed to automate your application updates using **GitHub Releases**.  \nIt simplifies the update process by checking for new versions, retrieving release notes, and optionally downloading and launching installers or executables.  \nWhether you're building a desktop tool or a larger application, Updatum helps you ensure your users are always on the latest version — effortlessly.\n\n## Features\n\n- **💻 Cross-Platform:** Works on Windows, Linux, and MacOS.\n- **⚙️ Flexible Integration:** Easily embed into your WPF, WinForms, or console applications.\n- **🔍 Update Checker:** Manually and/or automatically checks GitHub for the latest release version.\n- **📦 Asset Management:** Automatically fetches the latest release assets based on your platform and architecture.\n- **📄 Changelog Support:** Retrieve release notes directly from GitHub Releases.\n- **⬇️ Download with Progress Tracking:** Download and track progress handler.\n- **🔄 Auto-Upgrade Support:** Automatically upgrades your application to a new release.\n- **📦 No External Dependencies:** Minimal overhead and no need for complex update infrastructure.\n\n## Installation\n\n## NuGet:\n\n```\nPM\u003e Install-Package Updatum\n```\n\n## .NET CLI:\n\n```\ndotnet add package Updatum\n```\n\n## Package reference directly to your `.csproj` file:\n\n```xml\n\u003cPackageReference Include=\"Updatum\" Version=\"*\" /\u003e\n```\n\n## Requirements\n\n1. Publish your application to GitHub Releases.\n2. Name your assets accordingly for the platform and architecture:\n   - Windows: `MyApp_win-x64_v1.0.0.exe`, `MyApp_win-x64_v1.0.0.msi`, `MyApp_win-x64_v1.0.0.zip`\n   - Linux: `MyApp_linux-x64_v1.0.0.AppImage`, `MyApp_linux-x64_v1.0.0.zip`\n   - MacOS x64: `MyApp_osx-arm64_v1.0.0.zip`\n   - [Example for assets](https://github.com/sn4k3/UVtools/releases/latest)\n   - **NOTE:** The asset fetching is configurable via regex patterns.\n\n## Auto updater strategy\n\nYou can opt to install the update manually or automatically.\nIf automatic, Updatum will:\n\n- Check if asset is a zip file, if so, and if only one asset is found, it will extract the file to a temporary folder, and continue with the other checks.\n  - Otherwise, if the zip file contains multiple files it will be extracted to a temporary folder, and handled as a portable application.\n  - A script will be created and executed to perform checks, kill instances, merge files, rename the version in folder name and execute the new instance.\n- If file is an single-file application such as dotnet single-file executables or linux AppImage, it will be moved to the current folder and rename it to the current name and version.\n- If file is an installer, it will be executed and follow the normal installation process.\n\n### Compatibility\n\n- Portable applications (zip)\n- .NET single-file publishes\n- Windows Installer (exe and msi)\n- Linux [AppImage](https://appimage.org/)\n- macOS app bundle\n\n## Example\n\nCheck the [Updatum.FakeApp](https://github.com/sn4k3/Updatum/blob/main/Updatum.FakeApp/Program.cs) project for a complete example.\n\n\u003cdetails\u003e\n\u003csummary\u003eConsole output example\u003c/summary\u003e\n\n\n```\nChecking for updates for sn4k3/UVtools\nUpdater state changed: CheckingForUpdate\nUpdater state changed: None\nUpdate found: True\n\nChangelog:\n## v5.0.1\n\n\u003e Release date: 12/19/2024 06:56:33 +00:00\n\u003e Release diff: 1\n\n- (Fix) Windows MSI: System.IO.Compression.Native is missing when upgrading from 4.4.3 (#957)\n- (Fix) Index out of range when saving some file formats (#957)\n- (Change) Exposure time finder: Allow using 0 for the normal step in the multiple exposure generator (#958)\n\n---\n\n## v5.0.2\n\n\u003e Release date: 12/19/2024 15:28:39 +00:00\n\u003e Release diff: 2\n\n- (Fix) Remove a condition that prevents the new Anycubic file format from being used\n- (Upgrade) AvaloniaUI from 11.1.3 to 11.2.2\n\n---\n\n## v5.0.3\n\n\u003e Release date: 12/28/2024 19:22:42 +00:00\n\u003e Release diff: 3\n\n- Anycubic file format:\n  - (Fix) Reset TSMC values to comply with globals when decoding file and AdvancedMode is disabled (#971)\n  - (Fix) Setting the LiftHeight2 was setting the base value to BottomLiftHeight2\n  - (Fix) Setting the BottomRetractSpeed was not applying the value in the base property\n- Multiple exposure finder:\n   - (Fix) Counter triangles not taking all the new left space\n   - (Fix) When doing multiple heights the text label always show the base height\n- (Improvement) Layer image viewer internal handling\n- (Fix) Settings - Send to process: Unable to pick a process file, it was selecting folder instead\n- (Fix) Save As can show incorrect file extension description when there are other file formats with the same extension\n\n---\n\n## v5.0.4\n\n\u003e Release date: 01/08/2025 02:45:34 +00:00\n\u003e Release diff: 4\n\n- PCB Exposure:\n  - (Fix) Polygon primitive vertex count not parsing correctly when having argument (#976)\n  - (Fix) Obround aperture to follow the correct implementation (two semicircles connected by parallel lines tangent to their endpoints) (#976)\n  - (Fix) Implement the \"hole diameter\" argument in all apertures (#976)\n  - (Fix) Implement the \"rotation\" argument for the polygon aperture\n\n---\n\n## v5.0.5\n\n\u003e Release date: 01/09/2025 03:19:04 +00:00\n\u003e Release diff: 5\n\n- (Add) PrusaSlicer printer: Elegoo Saturn 4 Ultra 16K\n- (Improvement) Goo: Implement and support the tilting vat printers\n- (Improvement) All shapes in pixel editor will now respect the non-equal pixel pitch and compensate the lower side to print a regular shape, this also affects the polygons on PCB exposure tool and other tools as well\n- (Fix) PCB Exposure: Use raw polygons instead of angle aligned polygons to respect the gerber implementation (#976)\n\n---\n\n## v5.0.6\n\n\u003e Release date: 01/31/2025 02:21:16 +00:00\n\u003e Release diff: 6\n\n- **PCB Exposure:**\n  - (Fix) When importing gerber files via drag and drop to the main window the file was created with 0mm layer height and no exposure set\n  - (Fix) Merging multiple gerber files with mirror active was mirroring the image in each draw causing the wrong output (#980)\n  - (Fix) Excellon drill format does not load tools when they have spindle parameters [F/C] (#980)\n  - (Fix) Excellon drill format to respect the integer and decimal digit count when specifying them (#980)\n- **Stress Tower:**\n  - (Improvement) Allow to pause and cancel the operation\n  - (Improvement) Process layers in a more efficient way to reduce allocations and be able to produce the test without RAM hogging\n- (Upgrade) .NET from 9.0.0 to 9.0.1\n- (Upgrade) OpenCV from 4.9.0 to 4.10.0\n\n---\n\n## v5.0.7\n\n\u003e Release date: 02/15/2025 20:46:22 +00:00\n\u003e Release diff: 7\n\n- **Layer previewer: (#990)**\n  - (Add) Shortcuts: Ctrl/? + to zoom in and Ctrl/? - to zoom out in the layer previewer\n  - (Add) Allow to horizontal scroll the image with the mouse dispacement buttons and/or wheel (Only for mouse with such buttons)\n  - (Add) Hold Ctrl key while use the mouse wheel to vertical scroll the image instead of zoom\n  - (Add) Zoom behavior: Zoom with pre-defined levels or native incremental zoom (Configurable in settings, default: Levels)\n  - (Add) Zoom debounce time to prevent the zoom to be triggered multiple times when using a trackpad (Configurable in settings, default: 20ms)\n- (Improvement) Linux: Show app icon on AppImage after integration with the desktop environment\n- (Fix) Unable to find PrusaSlicer \u003e= 2.9.0 on Linux (Flatpak folder change) (#1000)\n- (Fix) PrusaSlicer: Anycubic Photon Mono M7 Max incorrect extension (#995)\n- (Upgrade) .NET from 9.0.1 to 9.0.2\n- (Upgrade) AvaloniaUI from 11.2.3 to 11.2.4\n\n---\n\n## v5.0.8\n\n\u003e Release date: 03/10/2025 04:05:17 +00:00\n\u003e Release diff: 8\n\n- (Fix) Ignore \"org.freedesktop.DBus.Error.ServiceUnknown\" exception to prevent crash on Linux (#964)\n- (Upgrade) AvaloniaUI from 11.2.3 to 11.2.4\n\n---\n\n## v5.0.9\n\n\u003e Release date: 04/04/2025 00:14:04 +00:00\n\u003e Release diff: 9\n\n- (Add) PrusaSlicer printer: Elegoo Mars 5 Ultra (#1006)\n- (Fix) Ignore the \"org.freedesktop.DBus.Error.UnknownMethod\" exception to prevent crash on Linux (#964)\n- (Fix) Goo: Bad print when using tilting VAT printer (#1013)\n- (Upgrade) .NET from 9.0.2 to 9.0.3\n- (Upgrade) AvaloniaUI from 11.2.5 to 11.2.6\n\n---\n\n## v5.1.0\n\n\u003e Release date: 04/22/2025 01:40:17 +00:00\n\u003e Release diff: 10\n\n- (Add) Pixel Arithmetic - Brightness Step: Mutates the initial brightness with a step that is added/subtracted to the current value dependent on the processed layer count (#1014)\n- (Fix) Anycubic ZIP: Implement the missing fields from manifest file and allow to tune TSMC and regular global values (#1018)\n- (Fix) Handle floating precision error when calculating the `PerLayerSettings` flag (#1013)\n- (Fix) Linux: Pixel editor drawing cursor preview not visible (#1019)\n- (Fix) Use `async Task` instead of `async void` where possible\n- (Improvement) Use some refactorings for NET 9.0 features\n- (Change) Compile openCV with lower linux requirement (#1015)\n- (Upgrade) .NET from 9.0.3 to 9.0.4\n- (Upgrade) AvaloniaUI from 11.2.6 to 11.3.0-beta2\n\n---\n\n## v5.1.1\n\n\u003e Release date: 05/09/2025 19:04:22 +00:00\n\u003e Release diff: 11\n\n- (Fix) Anycubic ZIP: `System.InvalidOperationException: Sequence contains no elements` when having empty layers (#1023)\n- (Improvement) CTB and GOO: Set all lift properties instead some of them for the tilting vat printers\n- (Improvement) Convert most Linq to ZLinq\n- (Upgrade) AvaloniaUI from 11.3.0-beta2 to 11.3.0\n\n---\n\n\nDo you want to download the v5.1.1 update? (y/yes/n/no)\ny\nDownloading UVtools_win-x64_v5.1.1.msi...\nUpdater state changed: DownloadingUpdate\nDownloaded: 0 MB / 78.16 MB  (0 %)\nDownloaded: 20.01 MB / 78.16 MB  (25.6 %)\nDownloaded: 40.8 MB / 78.16 MB  (52.2 %)\nDownloaded: 61.66 MB / 78.16 MB  (78.89 %)\nDownloaded: 78.16 MB / 78.16 MB  (100 %)\nUpdater state changed: None\nDownload finished: C:\\Users\\tiago\\AppData\\Local\\Temp\\UVtools_win-x64_v5.1.1.msi\nDo you want to install the update? (y/yes/n/no)\n```\n\n\u003c/details\u003e\n\n## Usage\n\n\n```csharp\n// Create an instance of UpdatumManager, keep it global and single instance.\n// By default it will fetch your current version from Assembly.GetEntryAssembly().GetName().Version\n// If you want to be safe and strict pass the current version, you can set 3rd argument as: Assembly.GetExecutingAssembly().GetName().Version\ninternal static readonly UpdatumManager AppUpdater = new(\"sn4k3\", \"UVtools\")\n{\n    InstallUpdateWindowsInstallerArguments = \"/qb\" // Displays a basic user interface for MSI package\n};\n\n\npublic static async Task Main(string[] args)\n{\n    try\n    {\n        // Check for updates\n        // Return true if a new version is available, otherwise false\n        var updateFound = await AppUpdater.CheckForUpdatesAsync();\n\n        // Stop if no update is found\n        if (!updateFound) return;\n\n        // Optional show a message to the user with the changelog\n        Console.WriteLine(\"Changelog:\");\n        Console.WriteLine(AppUpdater.GetChangelog());\n\n        // Downloads the update to temporary folder.\n        // Returns a UpdatumDownloadAsset object with the download information\n        // Returns null if failed to download the asset\n        var downloadedAsset = await AppUpdater.DownloadUpdateAsync();\n\n        if (downloadedAsset == null)\n        {\n            Console.WriteLine(\"Failed to download the update.\");\n            return;\n        }\n\n        // You can manually handle the installation or call the Install method:\n        // Returns false if the installation failed ortherwise it will never return true as the process will be terminated to complete the installation.\n        await AppUpdater.InstallUpdateAsync(downloadedAsset);\n    }\n    catch (Exception ex)\n    {\n        // Handle exceptions\n        Console.WriteLine($\"Error: {ex.Message}\");\n    }\n}\n```\n\n## Screenshots\n\n\n![UVtools screenshot](https://raw.githubusercontent.com/sn4k3/Updatum/main/media/assets/UVtools_screenshot.png)\n![NetSonar screenshot 1](https://raw.githubusercontent.com/sn4k3/Updatum/main/media/assets/NetSonar_screenshot_no_updates.png)\n![NetSonar screenshot 2](https://raw.githubusercontent.com/sn4k3/Updatum/main/media/assets/NetSonar_screenshot_update_found.png)\n![NetSonar screenshot 3](https://raw.githubusercontent.com/sn4k3/Updatum/main/media/assets/NetSonar_screenshot_update_changelog.png)\n![NetSonar screenshot 4](https://raw.githubusercontent.com/sn4k3/Updatum/main/media/assets/NetSonar_screenshot_update_download.png)\n\n## FAQs\n\n\u003cdetails\u003e\n\u003csummary\u003eHow to provide a custom asset pattern\u003c/summary\u003e\n\n### Customize the asset pattern\n\nYour asset naming convention may differ from the default one, and you can customize the asset fetcher to suit your needs.  \nBy using the property `AssetRegexPattern` you can provide a regex pattern to match your assets.\n\n```cssharp\n// Expect assets to be named like: MyApp_winx64_v1.0.0\nAppUpdater.AssetRegexPattern = $\"{RuntimeInformation.RuntimeIdentifier.Replace(\"-\", string.Empty)}\";\n```\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003eI have multiple assets with same name, but different extension\u003c/summary\u003e\n\n### Customize the asset extension filter\n\nIf you have multiple assets with the same name but different extensions, \nfor example `MyApp_win-x64_v1.0.0.zip` (The portable) and `MyApp_win-x64_v1.0.0.msi` (The installer),\nyou can use the `AssetExtensionFilter` property to filter them out.  \nYou will require some sort of file included in the application folder to know if user is running the portable or the installer version.\nIf you omit this step, the first asset will be used.\n\n\n```cssharp\nif (IsPortableApp) AppUpdater.AssetExtensionFilter = \"zip\";\n```\n\n**Notes:** \n\n- The `AssetRegexPattern` can also be used for the same porpose, but it is not recommended.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003eHow to listen for the download progress\u003c/summary\u003e\n\n### Listen for the download progress\n\nIf you using a binding framework like WPF, WinUI or Avalonia, you can use the properties directly:\n- `DownloadedMegabytes` to bind to a progress bar text\n- `DownloadTotalSizeMegabytes` to bind to a progress bar text\n- `DownloadedPercentage` to bind to a progress bar\n- Example: {0} / {1} Megabytes\n\nAs all properties raises changes the UI will reflect changes on such frameworks.  \nIf you require to listen for the download progress or redirect the value, you can subscribe `PropertyChanged` event.\n\n```csharp\nprivate static void AppUpdaterOnPropertyChanged(object? sender, PropertyChangedEventArgs e)\n{\n    if (e.PropertyName == nameof(UpdatumManager.DownloadedPercentage))\n    {\n        Console.WriteLine($\"Downloaded: {AppUpdater.DownloadedMegabytes} MB / {AppUpdater.DownloadTotalSizeMegabytes} MB  ({AppUpdater.DownloadedPercentage} %)\");\n    }\n}\n```\n\n**Notes:**\n\n- The frequency of progress change can be adjusted with: `DownloadProgressUpdateFrequencySeconds`\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eHow to check for updates in a time basis\u003c/summary\u003e\n\n### Check for updates in a time basis\n\nYou can make use of built-in timer object: `AutoUpdateCheckTimer` and listen for `UpdateFound` event.\n\n```csharp\nAppUpdater.AutoUpdateCheckTimer.Interval = TimeSpan.FromHours(1).TotalMilliseconds;\nAppUpdater.AutoUpdateCheckTimer.Start();\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eHow to force trigger an update\u003c/summary\u003e\n\n### Force trigger an update\n\nYou can force trigger an update check and event with by passing a specific version to compare with the latest release.  \nThe easiest way is to pass a empty version `0.0.0.0` to always trigger the update found event.\n\n```csharp\nvar updateFound = await AppUpdater.CheckForUpdatesAsync(new Version());\n```\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003eMy installer (.exe) or single-file app (.exe) does not upgrade\u003c/summary\u003e\n\n### Installers (.exe) and single-file apps\n\nWindows executables (.exe) can be either a installer or a single-file application.  \n- Installer requires executing and install by it own.  \n- Single-file applications requires replacing the current executable with the new one.\n\nThe problem arises when the asset is a .exe file, and Updatum cannot determine if it is a installer or a single-file application\nand then choose the wrong upgrade strategy.  \nBy default it tries to infer based on file signatures, such as: Inno Setup, NSIS, Nullsoft, InstallShield, Windows Installer, etc.\nwhich can also lead to false positives if your single-file application contains such signatures from typical raw strings or if\nthe installer does not include those signatures due a odd installer build.\n\n#### Solution\n\nUse the property `InstallUpdateWindowsExeType` to explicitly indicate the asset type to either `Installer` or `SingleFileApp`.\n\n```csharp\ninternal static readonly UpdatumManager AppUpdater = new(RepositoryOwner, RepositoryName)\n{\n    // Specifies the type of windows .exe being used in the assets.\n    // It is highly recommended to set this when having .exe assets.\n    // - When asset is an installer, set to Installer.\n    // - When asset is a single file executable, set to SingleFileExecutable.\n    // - When having both asset types, set to Auto.\n    InstallUpdateWindowsExeType = UpdatumWindowsExeType.Installer,\n\n    // ...\n    // ...\n    // ...\n};\n```\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsn4k3%2Fupdatum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsn4k3%2Fupdatum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsn4k3%2Fupdatum/lists"}