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

Added ability to start from url

Changed files
+73
+73
Index.html
··· 54 54 const likesCollection = 'app.bsky.feed.like'; 55 55 const repostsCollection = 'app.bsky.feed.repost'; 56 56 57 + function getQueryParams() { 58 + const params = new URLSearchParams(window.location.search); 59 + 60 + // Get post_url and validate it's a Bluesky URL or AT URI 61 + let postUrl = params.get('post_url') || ''; 62 + if (postUrl && !postUrl.startsWith('https://bsky.app/') && !postUrl.startsWith('at://')) { 63 + console.warn('Invalid post_url parameter. Must be a Bluesky URL or AT URI.'); 64 + postUrl = ''; 65 + } 66 + 67 + // Get winner_count and ensure it's a positive number 68 + let winnerCount = parseInt(params.get('winner_count')) || 1; 69 + if (winnerCount < 1) { 70 + console.warn('Invalid winner_count parameter. Must be a positive number.'); 71 + winnerCount = 1; 72 + } 73 + 74 + // Get option and ensure it's one of the valid options 75 + let option = params.get('option') || 'likes'; 76 + if (option && !['likes', 'reposts', 'both'].includes(option)) { 77 + console.warn('Invalid option parameter. Must be "likes", "reposts", or "both".'); 78 + option = 'likes'; 79 + } 80 + 81 + return { 82 + post_url: postUrl, 83 + winner_count: winnerCount, 84 + option: option 85 + }; 86 + } 87 + 57 88 async function callConstellationEndpoint(target, collection, path, cursor = null) { 58 89 try { 59 90 const url = new URL(`${constellationEndpoint}/links/distinct-dids`); ··· 89 120 winners: [], 90 121 participants: 0, 91 122 showResults: false, 123 + 124 + // Initialize component with query parameters 125 + init() { 126 + const params = getQueryParams(); 127 + 128 + // Set form values from query parameters 129 + if (params.post_url) { 130 + this.post_url = params.post_url; 131 + } 132 + 133 + if (params.winner_count && params.winner_count > 0) { 134 + this.winner_count = params.winner_count; 135 + } 136 + 137 + // Set winning options based on the option parameter 138 + if (params.option) { 139 + this.likes_only = params.option === 'likes'; 140 + this.reposts_only = params.option === 'reposts'; 141 + this.likes_and_reposts = params.option === 'both'; 142 + } 143 + 144 + // Automatically run the giveaway if post_url is provided 145 + if (params.post_url) { 146 + // Use setTimeout to ensure the component is fully initialized 147 + setTimeout(() => { 148 + this.runGiveaway(); 149 + }, 100); 150 + } 151 + }, 92 152 93 153 validateCheckBoxes(event) { 94 154 const targetId = event.target.id; ··· 313 373 314 374 <a href="https://tangled.sh/@baileytownsend.dev/at-giveaways" class="link mt-4 block">View on <span 315 375 class="font-semibold italic">tangled.sh</span></a> 376 + 377 + <!-- URL Parameters Documentation --> 378 + <div class="mt-6 p-4 bg-base-200 rounded-lg text-sm"> 379 + <h3 class="text-lg font-bold mb-2">🔗 URL Parameters</h3> 380 + <p class="mb-2">You can create links that automatically run giveaways with specific parameters:</p> 381 + <ul class="list-disc pl-5 mb-2"> 382 + <li><code>post_url</code>: URL of the Bluesky post</li> 383 + <li><code>winner_count</code>: Number of winners (default: 1)</li> 384 + <li><code>option</code>: 'likes', 'reposts', or 'both' (default: 'likes')</li> 385 + </ul> 386 + <p class="text-xs">Example: <code>?post_url=https://bsky.app/profile/user.bsky.social/post/123&winner_count=3&option=both</code> 387 + </p> 388 + </div> 316 389 </div> 317 390 </div> 318 391 </div>