mirror of
https://github.com/hanzoai/gui.git
synced 2026-10-25 02:31:41 +00:00
This repo could never sync. There was NO merge-base with tamagui — 372 commits
here against 15,791 there, unrelated histories — because it began as a
copy-paste rebrand with a flattened layout. Every "sync" since was a hand
re-application that drifted, which is why the tree sat on 7.3.1 while upstream
shipped fixes we then rediscovered by hand.
This commit's PARENT IS TAMAGUI. A future sync is `git merge tama/main` then
`node scripts/rebrand.mjs` — a real merge, because the history is now shared.
174 packages: 166 upstream, our 8 restored (chrome, shell, telemetry, recipes,
get, font-geist-{sans,mono}, @hanzo/booker), bento-get gained. 170/170 build.
Our patches to files UPSTREAM ALSO OWNS are carried, which the package-level
delta missed and which was where the value actually was:
- useMedia's server snapshot (`initState ?? getMedia()`). Upstream still
returns undefined there, so every Tamagui Dialog kills a prerender — the
exact crash hanzo.app spent a day on.
- data-slot on web host nodes, absent upstream entirely.
Both applied ONTO upstream's newer files (it rewrote useMedia +150/-63 and
createComponent +160/-55), marked `PATCH (ours, carried across the transplant)`.
Seven traps are encoded in scripts/rebrand.mjs, each found by a gate:
skip itself and lockfiles; special-case the double-branded names in BOTH scoped
and bare form; map path strings, not just paths; drop a level for the flattened
group; check disk rather than a stale index.
Rust build artifacts are NOT committed. An earlier draft of this commit swept
apps/desktop/src-tauri/target/debug in via `git add -A` — 3,859 files including
a 272MB .a, over GitHub's 100MB cap, so the push could never have landed. They
are gitignored now.
Co-Authored-By: Hanzo Dev <[email protected]>
160 lines
4.2 KiB
TypeScript
160 lines
4.2 KiB
TypeScript
#!/usr/bin/env tsx
|
|
|
|
/**
|
|
* Remove Discord users from Takeout role based on analysis file
|
|
*
|
|
* Usage:
|
|
* tsx scripts/takeout/remove-discord-users.ts <users-to-remove-file.json> [--dry-run]
|
|
*/
|
|
|
|
import { Client, GatewayIntentBits } from '@discordjs/core'
|
|
import { REST } from '@discordjs/rest'
|
|
import { WebSocketManager } from '@discordjs/ws'
|
|
import { readFileSync } from 'fs'
|
|
|
|
const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN
|
|
|
|
// Discord IDs from features/discord/helpers.ts
|
|
const TAKEOUT_ROLE_ID = '1131082605052301403'
|
|
const GUI_DISCORD_GUILD_ID = '909986013848412191'
|
|
const DELAY_MS = 1000 // Rate limiting - 1 second between removals
|
|
|
|
if (!DISCORD_BOT_TOKEN) {
|
|
console.error('Missing DISCORD_BOT_TOKEN environment variable')
|
|
process.exit(1)
|
|
}
|
|
|
|
async function getDiscordClient() {
|
|
const rest = new REST({ version: '10' }).setToken(DISCORD_BOT_TOKEN)
|
|
|
|
const gateway = new WebSocketManager({
|
|
token: DISCORD_BOT_TOKEN,
|
|
intents: GatewayIntentBits.GuildMessages | GatewayIntentBits.MessageContent,
|
|
rest,
|
|
})
|
|
|
|
const discordClient = new Client({ rest, gateway })
|
|
return discordClient
|
|
}
|
|
|
|
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
|
|
async function removeRoleFromUser(
|
|
discordClient: Client,
|
|
userId: string,
|
|
username: string,
|
|
dryRun: boolean
|
|
): Promise<boolean> {
|
|
if (dryRun) {
|
|
console.log(` [DRY RUN] Would remove role from ${username}`)
|
|
return true
|
|
}
|
|
|
|
try {
|
|
await discordClient.api.guilds.removeRoleFromMember(
|
|
GUI_DISCORD_GUILD_ID,
|
|
userId,
|
|
TAKEOUT_ROLE_ID
|
|
)
|
|
console.log(` ✅ Removed role from ${username}`)
|
|
return true
|
|
} catch (error: any) {
|
|
console.error(` ❌ Failed to remove role from ${username}:`, error.message)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
const args = process.argv.slice(2)
|
|
const dryRun = args.includes('--dry-run')
|
|
const usersFile = args.find((arg) => !arg.startsWith('--'))
|
|
|
|
if (!usersFile) {
|
|
console.error(
|
|
'Usage: tsx remove-discord-users.ts <users-to-remove-file.json> [--dry-run]'
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('\n' + '='.repeat(80))
|
|
console.log(`REMOVE DISCORD USERS${dryRun ? ' (DRY RUN)' : ''}`)
|
|
console.log('='.repeat(80) + '\n')
|
|
|
|
// Read the users file
|
|
console.log(`📖 Reading file: ${usersFile}`)
|
|
const fileContent = JSON.parse(readFileSync(usersFile, 'utf-8'))
|
|
const usersToRemove = fileContent.users
|
|
|
|
console.log(` Found ${usersToRemove.length} users to remove`)
|
|
console.log(` Generated at: ${fileContent.generated_at}`)
|
|
|
|
if (usersToRemove.length === 0) {
|
|
console.log('\n✅ No users to remove!')
|
|
return
|
|
}
|
|
|
|
console.log(
|
|
`\n⚠️ WARNING: This will remove the Takeout role from ${usersToRemove.length} Discord users`
|
|
)
|
|
|
|
if (!dryRun) {
|
|
console.log('\n⏸️ Starting in 3 seconds... (Ctrl+C to cancel)')
|
|
await delay(3000)
|
|
}
|
|
|
|
console.log('\n' + '='.repeat(80))
|
|
console.log('PROCESSING')
|
|
console.log('='.repeat(80) + '\n')
|
|
|
|
const discordClient = await getDiscordClient()
|
|
|
|
let successCount = 0
|
|
let failureCount = 0
|
|
|
|
for (let i = 0; i < usersToRemove.length; i++) {
|
|
const user = usersToRemove[i]
|
|
console.log(
|
|
`[${i + 1}/${usersToRemove.length}] ${user.username} (${user.global_name || 'no global name'})`
|
|
)
|
|
console.log(` Discord ID: ${user.discord_id}`)
|
|
console.log(
|
|
` Inactive subs: ${user.inactive_subscription_ids?.join(', ') || 'none'}`
|
|
)
|
|
|
|
const success = await removeRoleFromUser(
|
|
discordClient,
|
|
user.discord_id,
|
|
user.username,
|
|
dryRun
|
|
)
|
|
|
|
if (success) {
|
|
successCount++
|
|
} else {
|
|
failureCount++
|
|
}
|
|
|
|
// Rate limiting
|
|
if (i < usersToRemove.length - 1) {
|
|
await delay(DELAY_MS)
|
|
}
|
|
}
|
|
|
|
console.log('\n' + '='.repeat(80))
|
|
console.log('SUMMARY')
|
|
console.log('='.repeat(80))
|
|
console.log(`✅ Successfully removed: ${successCount}`)
|
|
console.log(`❌ Failed: ${failureCount}`)
|
|
console.log(`📊 Total processed: ${successCount + failureCount}`)
|
|
|
|
if (dryRun) {
|
|
console.log('\n💡 Run without --dry-run to actually remove users')
|
|
} else if (failureCount === 0) {
|
|
console.log('\n🎉 All users removed successfully!')
|
|
} else {
|
|
console.log('\n⚠️ Some removals failed. Check the errors above.')
|
|
}
|
|
}
|
|
|
|
main().catch(console.error)
|