{"id":18644557,"url":"https://github.com/hekku2/discord-image-poster","last_synced_at":"2026-04-16T01:33:02.873Z","repository":{"id":245354945,"uuid":"815506142","full_name":"Hekku2/discord-image-poster","owner":"Hekku2","description":"A bot which posts a random image to discord channel from Azure Blob Storage.","archived":false,"fork":false,"pushed_at":"2024-07-16T13:11:42.000Z","size":135,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-20T08:43:45.517Z","etag":null,"topics":["azure","blob-storage","discord-bot","dotnet-isolated","function-app"],"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/Hekku2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2024-06-15T11:10:13.000Z","updated_at":"2024-07-14T19:45:51.000Z","dependencies_parsed_at":"2024-06-28T15:57:18.663Z","dependency_job_id":"b6452e2b-da8a-48ad-8ac6-42fb32cce196","html_url":"https://github.com/Hekku2/discord-image-poster","commit_stats":null,"previous_names":["hekku2/discord-image-poster"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/Hekku2/discord-image-poster","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hekku2%2Fdiscord-image-poster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hekku2%2Fdiscord-image-poster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hekku2%2Fdiscord-image-poster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hekku2%2Fdiscord-image-poster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hekku2","download_url":"https://codeload.github.com/Hekku2/discord-image-poster/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hekku2%2Fdiscord-image-poster/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31867710,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T15:24:51.572Z","status":"ssl_error","status_checked_at":"2026-04-15T15:24:39.138Z","response_time":63,"last_error":"SSL_read: 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":["azure","blob-storage","discord-bot","dotnet-isolated","function-app"],"created_at":"2024-11-07T06:12:45.616Z","updated_at":"2026-04-16T01:33:02.847Z","avatar_url":"https://github.com/Hekku2.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Discord Image Poster\n\nA bot which posts periodically a random image to discord channel from Azure\nStorage.\n\nCurrently this is designed to work with one server and one channel.\n\n## How does it work?\n\nIn short, software periodically selects random image from image storage and\nsends it to discord channel.\n\nIn depth\n 1. Image sending is periodically triggered by Function App TimerTrigger.\n 1. When Image sending is triggered, software selects a random image from\n index. Selection is not really random, it prefers less posted images. See\n [RandomizationService](src/Common/RandomizationService/RandomizationService.cs)\n for implementation details.\n   * If there is no index, software builds an index of images available in\n   source.\n 1. After image is selected, software downloads the image from storage to memory\n   * If Image is removed, error is logged and image is not sent to channel.\n 1. After file is downloaded, image is sent to Azure AI Vision for analysis\n   * This functionality can be disabled with from Feature Settings\n 1. Caption and tags from Azure AI Vision response are saved to index.\n 1. Image is sent to discord with received caption. If image analysis is not used, file name is used as caption.\n\nSame with flowchart:\n\n```mermaid\nflowchart TD\n  A[Timer triggered] --\u003e B{Is index built?};\n  B -- Yes --\u003e D[Get random image from index];\n  B -- No --\u003e C[Build index!];\n  C ----\u003e D;\n  D ----\u003e E{Does Image exist?};\n  E -- No --\u003e X[Process finished];\n  E -- Yes --\u003e F[Download image];\n  F ----\u003e G{Image analysis enabled};\n  G -- Yes --\u003e H[Send to Image Analysis Service];\n  G -- No --\u003e I{Is Discord sending enabled?};\n  H ----\u003e I;\n  I -- Yes --\u003e K[Send image to Discord];\n  I -- No --\u003e X;\n  K ----\u003e X;\n```\n\nIndexing\n * Indexing is performed automatically if index doesn't exist.\n * Image index can be regenerated by calling the related function.\n * Currently changes in storage don't trigger image index regeneration.\n * The index contains data of the images and how often those have been posted\n and other similar metadata.\n * Images can also be ignored. Ignored images are not selected by randomization\n logic.\n\n## Tools\n\nThis section lists tools that are used in developing and deploying this\nsoftware. Some are not strictly needed, but make developing easier.\n\nDevelopment\n  * Dotnet 8.0 (or later)\n  * Azure Powershell\n    * Bicep with version that supports importing user types (0.28.1 is\n    enough, earlier may also suffice)\n  * Docker (and docker compose).\n\n## Deployment and running\n\nFollowing section describes what needs be done to deploy and run this\napplication. Instructions are still WIP, proper documentation and scripts can\nbe provided later.\n\nThis service can be run in following ways\n\n1. Local, without container. (Azure Core Tools, `func start`)\n2. Local, with container (docker compose)\n3. From Azure (the intended way for production)\n\n### Configuration\n\nDiscord\n\n  1. Create application in [Discord portal](https://discord.com/developers/applications).\n  2. [Installing Discord Bot to Discord Server](README.md#installing-discord-bot-to-discord-server)\n  3. Get Token from Discord Portal (Check the bot page)\n  4. Get Guild Id (server ID) and Channel Id from Discord server. Easies way to is\n  to navigate to Discord server with browser and take those ids from browser url,\n  such as `https://discord.com/channels/123123/666666`\n\n#### Installing Discord Bot to Discord Server\n\nNot sure if there is an easier way, but the current way is to call following url:\n`https://discord.com/oauth2/authorize?client_id=\u003cbot id here\u003e\u0026permissions=2048\u0026scope=bot`\n\n  * Permission 2048 is \"Send Messages\"\n  * Other combinations can be checked from `https://discord.com/developers/applications/\u003cid here\u003e/bot`\n\n### Running locally with Azure Core Tools\n\nThis requires Azurite or proper Azure Storage to function correctly.\n\nSettings are read from `local.settings.json` which needs to be generated.\n\nExample:\n\n```json\n{\n    \"IsEncrypted\": false,\n    \"Values\": {\n        \"AzureWebJobsStorage\": \"UseDevelopmentStorage=true\",\n        \"FUNCTIONS_WORKER_RUNTIME\": \"dotnet-isolated\",\n        \"DiscordOptions__Token\": \"token here\",\n        \"DiscordOptions__GuildId\": \"server id here\",\n        \"DiscordOptions__ChannelId\": \"channel id here\",\n        \"BlobStorageImageSourceOptions__ConnectionString\": \"DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://local.storage.emulator:10000/devstoreaccount1;QueueEndpoint=http://local.storage.emulator:10001/devstoreaccount1;\",\n        \"BlobStorageImageSourceOptions__ContainerName\": \"images\",\n        \"BlobStorageImageSourceOptions__FolderPath\": \"testfolder\"\n    }\n}\n\n```\n\nTo start\n\n```bash\ncd ./src/FunctionApp.Isolated/\nfunc start\n```\n\n### Running locally in container\n\nPreparation\n 1. Create `developer-settings.json` (based on developer-settings-sample.json)\n 1. Create .env file for docker compose\n\n```bash\ndocker compose build\ndocker compose up\n```\n\nNOTE: For some reason, timer doesn't seem start correctly on the first time, but it seems to after retry.\n`Microsoft.Azure.WebJobs.Host.Listeners.FunctionListenerException: The listener for function 'Functions.SendRandomImage' was unable to start`\n\nThen call `http://localhost:8080/api/SendImage?code=mock-secret-for-local-testing`\n\n### Running in Azure\n\nPreparation\n 1. Create `developer-settings.json` (based on developer-settings-sample.json)\n\n```bash\n./Create-Environment.ps1\n./Publish-App.ps1\n```\n\nThen get the url from Azure Portal etc.\n\n## Outside documentation\n\nRelevant parts of documentation\n\n * Azurite\n   * [Authentication](https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage)\n * Discord.Net\n   * [DiscordRestClient](https://docs.discordnet.dev/api/Discord.Rest.DiscordRestClient.html)\n   * [UserExtensions.SendFileAsync](https://docs.discordnet.dev/api/Discord.UserExtensions.html#Discord_UserExtensions_SendFileAsync_Discord_IUser_Discord_FileAttachment_System_String_System_Boolean_Discord_Embed_Discord_RequestOptions_Discord_MessageComponent_Discord_Embed___)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhekku2%2Fdiscord-image-poster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhekku2%2Fdiscord-image-poster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhekku2%2Fdiscord-image-poster/lists"}