Run a giveaway from a bsky post. Choose from those who interacted with it

Updated info

Changed files
+96 -9
images
+75 -8
Index.html
··· 3 3 <head> 4 4 <meta charset="UTF-8"> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <meta property="og:title" content="at://giveaways ๐ŸŽ‰"> 7 + <meta property="og:image" content="/images/cover.jpg"> 8 + <meta property="og:description" content="Host a giveaway from a Bluesky post."> 9 + 6 10 <title>at://giveaways ๐ŸŽ‰</title> 7 11 <link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css"/> 8 12 <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script> ··· 27 31 http: new WellKnownHandleResolver(), 28 32 }, 29 33 }); 30 - const handle = await handleResolver.resolve('baileytownsend.dev'); 31 - console.log(handle); 34 + 35 + window.resolveHandle = async (handle) => await handleResolver.resolve(handle); 36 + 37 + </script> 38 + 39 + <script> 40 + 41 + function isValidHttpUrl(string) { 42 + let url; 43 + try { 44 + url = new URL(string); 45 + } catch (_) { 46 + return false; 47 + } 48 + return url.protocol === "http:" || url.protocol === "https:"; 49 + } 50 + 51 + document.addEventListener('alpine:init', () => { 52 + Alpine.data('giveaway', () => ({ 53 + //Form input 54 + post_url: '', 55 + likes_only: false, 56 + reposts_only: false, 57 + likes_and_reposts: false, 58 + 59 + error: '', 60 + 61 + validateCheckBoxes(event) { 62 + const targetId = event.target.id; 63 + this.likes_only = targetId === 'likes'; 64 + this.reposts_only = targetId === 'reposts_only'; 65 + this.likes_and_reposts = targetId === 'likes_and_reposts'; 66 + }, 67 + 68 + test() { 69 + console.log('test'); 70 + }, 71 + async runGiveaway() { 72 + //TODO validation of input 32 73 74 + if (!isValidHttpUrl(this.post_url)) { 75 + this.error = 'Invalid Bluesky post URL'; 76 + return; 77 + } 33 78 79 + let postSplit = this.post_url.split('/'); 80 + 81 + let handle = postSplit[4]; 82 + console.log(handle); 83 + let recordKey = postSplit[6]; 84 + console.log(recordKey); 85 + let result = await window.resolveHandle(handle); 86 + console.log(result); 87 + } 88 + 89 + })) 90 + }) 34 91 </script> 35 92 </head> 36 93 ··· 56 113 </div> 57 114 </div> 58 115 <div class="card bg-base-100 w-full max-w-sm shrink-0 shadow-2xl"> 59 - <div class="card-body"> 116 + <div class="card-body" x-data="giveaway"> 60 117 <fieldset class="fieldset"> 61 118 <label for="post_url" class="label">Post Url</label> 62 - <input id="post_url" type="url" class="input" 119 + <input x-model="post_url" id="post_url" type="text" class="input" 63 120 placeholder="https://bsky.app/profile/baileytownsend.dev/post/3lbq7o74fcc2d"/> 64 121 <label for="winner_count" class="label">How many winners?</label> 65 122 <input id="winner_count" type="number" class="input" value="1"/> 66 123 <fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4"> 67 124 <legend class="fieldset-legend">Winning options</legend> 68 125 <label class="label"> 69 - <input id="likes" type="checkbox" checked="checked" class="checkbox"/> 126 + <input x-model="likes_only" x-on:change="validateCheckBoxes($event)" 127 + id="likes" 128 + type="checkbox" 129 + checked="checked" 130 + class="checkbox"/> 70 131 Likes only 71 132 </label> 72 133 <label class="label"> 73 - <input id="reposts_only" type="checkbox" 134 + <input x-model="reposts_only" x-on:change="validateCheckBoxes($event)" id="reposts_only" 135 + type="checkbox" 74 136 class="checkbox"/> 75 137 Reposts only 76 138 </label> 77 139 <label class="label"> 78 - <input id="likes_and_reposts" type="checkbox" 140 + <input x-model="likes_and_reposts" x-on:change="validateCheckBoxes($event)" 141 + id="likes_and_reposts" 142 + type="checkbox" 79 143 class="checkbox"/> 80 144 Likes & Reposts 81 145 </label> 82 146 83 147 </fieldset> 84 - <button class="btn btn-neutral mt-4">I choose you!</button> 148 + <span x-show="error" x-text="error" class="text-red-500"></span> 149 + <button x-on:click="await runGiveaway()" class="btn btn-neutral mt-4">I choose 150 + you! 151 + </button> 85 152 </fieldset> 86 153 <a href="https://tangled.sh/@baileytownsend.dev/at-giveaways" class="link">View on <span hx-boost="true" 87 154 class="font-semibold italic">tangled.sh</span></a>
+21 -1
README.md
··· 1 - ## at://giveaways ๐ŸŽ‰ 1 + # at://giveaways ๐ŸŽ‰ 2 + 3 + # WIP as in it's not acutally doing anything yet, plan to be done tonight 4 + 5 + Host a giveaway from a Bluesky post. 6 + 7 + ![](./images/cover.jpg) 8 + 9 + # Tech 10 + 11 + * Simple one page html implementation 12 + * [Alpine.js](https://alpinejs.dev/) for reactivity 13 + * [tailwindcss](https://tailwindcss.com/) and [daisyUI](https://daisyui.com/) to keep us stylish 14 + * [@atcute/identity-resolver](https://github.com/mary-ext/atcute/tree/trunk/packages/identity/identity-resolver) for 15 + identity resolution 16 + * [constellation](https://constellation.microcosm.blue/) to get the dids of who liked, reposted, etc 17 + 18 + # Setup 19 + 20 + 1. Open [index.html](./Index.html) if your favorite web browser, or host this whole folder on a web server 21 + 2. Enjoy ๐Ÿป
images/cover.jpg

This is a binary file and will not be displayed.