ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenHuman Rewards Referrals 完整解析:推荐奖励、优惠券兑换、Discord 社区成就与邀请码机制

OpenHuman Rewards  Referrals 完整解析:推荐奖励、优惠券兑换、Discord 社区成就与邀请码机制 OpenHuman Rewards Referrals 完整解析推荐奖励、优惠券兑换、Discord 社区成就与邀请码机制【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman本文以 OpenHuman 的官方功能文档gitbooks/features/rewards-and-referrals.md为主线结合仓库中 Rust 核心src/openhuman/hosted/referral/与 React 前端app/src/pages/Rewards.tsx、app/src/pages/Invites.tsx、app/src/services/api/的源码实现系统讲解应用内“奖励与推荐”体系的三个松散耦合的成长机制推荐计划Referrals、促销优惠券Coupons与社区奖励Community Rewards外加独立的邀请码Invite Codes管理。读完本文你将掌握各功能面的数据模型、状态机、前后端调用链与底层 RPC 适配层原理并能据此排查“本地会话下功能不可用”“WebView fetch 失败”“角色未分配”等实际现象。一、功能概览三个机制共用一个界面OpenHuman 将三类“增长玩法”捆绑在同一个Rewards界面下它们业务上彼此独立只是共享一个入口机制作用推荐计划Referral program分享你的推荐码好友完成转化后你获得信用额度credit促销优惠券Promo coupons兑换促销码获得促销信用promotional credit与推荐奖励相互独立社区奖励Community rewards绑定 Discord 账号随使用量里程碑解锁角色与奖励邀请码管理则独立于 Rewards 界面位于单独的/invites页面。一个关键前提以上所有功能都要求已登录的后端会话signed-in backend session。在纯本地会话local-only session下Rewards 页面只显示一个引导登录的空状态empty state所有这些功能离线不可用。对应前端实现见 Rewards.tsx当isLocalSessionToken(coreSnapshot.sessionToken)为真时直接渲染EmptyStateCard提示文案由 i18n 键rewards.localUnavailable提供并引导用户跳转/settings/account。二、Rewards 界面三个视图与地址化导航功能文档描述/rewards拥有三个 chip 标签页中间默认选中Rewards社区。从当前仓库源码看这一交互已演化为更彻底的形式三个表面不再是同一页面上的标签而是各有一个侧边栏条目sidebar entry的独立视图并用 URL 参数?view作为地址从而支持刷新后状态保持与直接链接跳转。// app/src/pages/Rewards.tsx type RewardsView rewards | referrals | redeem; const VIEWS: readonly RewardsView[] [rewards, referrals, redeem] as const;视图?view值侧边栏图标对应内容Rewards社区缺省 /?viewrewardsGiftDiscord 连接、进度环、可解锁的社区角色Referrals推荐?viewreferralsUsers推荐码、收益、被推荐用户活动Coupons优惠券?viewredeemTicket兑换促销码、兑换历史视图切换通过setView写入 URLview rewards时删除view参数其他视图则写入对应值Rewards.tsx。未识别或缺失的?view一律回落fallback到rewards保证侧边栏始终恰好高亮一个条目。另外Rewards 页面注册了一个oauth:success事件监听任何 OAuth 连接如 Discord完成后深链监听器会派发该事件页面随即静默刷新快照使 Discord 用户名与连接状态实时更新Rewards.tsx。三、Referrals 推荐计划3.1 推荐码与分享每个账号拥有唯一推荐码。你可以复制它或使用Share优先调用系统原生分享面板失败时回退到剪贴板发送一条预填充消息内容包含你的推荐码与应用下载链接。3.2 数据展示四个磁贴 活动表Referrals 标签页展示四块信息你的推荐码code累计收益total earnedUSD待转化推荐pending referrals已完成推荐completed referrals下方是一张活动表列出每条被推荐记录被推荐人的掩码身份masked identity如j***gmail.com、状态徽章、奖励金额与时间戳。掩码优先取自后端下发的referredUserMasked字段若后端只提供referredDisplayName或用户 id前端归一化逻辑也会兜底处理见 referralApi.ts。数据模型定义在 app/src/types/referral.tsReferralStats包含referralCode、referralLink、totalstotalRewardUsd/pendingCount/convertedCount、referrals行数组、appliedReferralCode与canApplyReferral。3.3 推荐状态机Referral 状态含义Joined加入被推荐用户已注册但尚未转化Completed完成被推荐用户已转化推荐奖励已入账Expired过期关系失效预留状态由后端驱动注意 UI 层与后端的措辞差异后端只区分pending | convertedexpired为预留值前端归一化函数把后端的joined映射为pending、completed/complete映射为convertedreferralApi.ts。因此文档表格里的 “Joined / Completed / Expired” 本质上是归一化后的 UI 状态名。3.4 应用他人推荐码Apply如果你是被他人推荐且仍符合资格的用户界面会显示一个apply 表单让你输入对方的推荐码。资格判断canApplyReferral完全由后端决定——典型规则是尚未订阅、且尚未应用过任何推荐码的用户才有资格。一旦应用成功表单会被“已关联推荐码”的确认信息替换。金额、转化规则与资格判定全部服务端强制server-side enforced。桌面端核心在这里只是一个薄适配层thin adapter。3.5 底层原理referral 域是“无状态 RPC 适配器”从源码结构看referral 域src/openhuman/hosted/referral/不持有任何业务逻辑、状态或自有 schema——它只是一个无状态 RPC 适配器用带认证的reqwest请求调用托管后端hosted backend的/referral/*接口并把原始data负载原样返回给 CLI / JSON-RPC 客户端。它之所以存在是因为桌面 WebView 的fetch到后端可能抛出笼统的 “Load failed”源于 CORS / TLS / WebKit 限制因此这些调用复用了与 billing 域相同的服务端reqwest路径。这一点在 ops.rs 的模块注释和 README.md 中均有明确说明。对外暴露两个 RPC 方法注册见 src/core/all.rsRPC 方法后端调用用途输入openhuman.referral_get_stats即referral.get_statsGET /referral/stats拉取推荐码、链接、总额与被推荐人列表无openhuman.referral_claim即referral.claimPOST /referral/claim应用推荐码可带设备指纹作为滥用信号code必填、deviceFingerprint可选RPC schema 定义于 schemas.rsreferral_get_stats输出statsJSON来自后端data字段referral_claim输出resultJSON入参通过ReferralClaimParams以 camelCase 反序列化device_fingerprint字段带#[serde(default)]。未知方法名会返回一个unknown占位 schema 且只含error输出。关键实现细节ops.rsrequire_token私有助手从凭据库读取会话令牌先get_session_token然后trim并拒绝空串否则fail closed返回错误no backend session token; run auth_store_session first——两个方法在没有会话时都以此方式失败。get_stats通过effective_backend_api_url(config.api_url)解析有效后端地址构造BackendOAuthClient后执行authed_json(GET, /referral/stats)。claim_referral构造请求体时会对code做trim对deviceFingerprint同样 trim 并丢弃纯空白字符串后才转发schema handlerhandle_referral_claim侧也做了一遍防御性的重复过滤。前端 referralApi.ts 通过callCoreCommand(openhuman.referral_get_stats)/callCoreCommand(openhuman.referral_claim, { code, deviceFingerprint })调用上述 RPC。设备指纹由 deviceFingerprint.ts 提供以openhuman_device_fingerprint_v1为键存入localStorage优先使用crypto.randomUUID()不可用时回退到时间戳 随机串是一个稳定的匿名标识stable anonymous id供后端做滥用信号分析。四、Coupons 优惠券兑换Coupons 标签页用于兑换**促销码promo codes**换取促销信用与推荐奖励相互独立。界面包含两块统计磁贴促销信用余额promo credit balanceUSD已兑换码数量count of redeemed codes输入一个码并兑换即可兑换结果要么立即生效applied要么在依赖后续操作时先被接受为pending待定。下方是一张近期兑换记录表列出每个码、奖励金额、状态与兑换时间。Coupon 状态含义Applied已应用已兑现——信用已进入你的账户Pending action待触发条件性优惠券等待某个触发动作Redeemed已兑换已被接受但尚未兑现五、Community Rewards 与 Discord5.1 进度环与角色奖励Rewards社区标签页将使用量“游戏化”。一个**进度环progress ring**展示你已解锁成就数占总成就数的比例**角色与奖励roles rewards**列表则描述每个里程碑部分里程碑附带可选的 USD 信用。页面底部用状态徽章当前连续天数 current streak、累计 token 数汇总你的活动。5.2 围绕 Discord 的三个操作奖励以Discord 角色的形式发放因此该标签页围绕“绑定 Discord 账号”构建Connect Discord执行 OAuth 授权流程openhuman.auth.oauth_connectprovider 为discord成功后快照刷新并显示你的 Discord 用户名。Join Discord打开社区服务器邀请链接。Disconnect解除账号绑定清除存储的 Discord ID操作幂等。从 rewardsApi.ts 可以看到对应的 HTTP 接口GET /rewards/me拉取快照15 秒超时REWARDS_SNAPSHOT_TIMEOUT_MS 15_000POST /rewards/claimbody 为{ rewardType }领取奖励DELETE /rewards/discord解绑 Discord。5.3 快照数据模型与角色状态GET /rewards/me的快照结构定义在 app/src/types/rewards.ts前端归一化逻辑见 rewardsApi.tsdiscordlinked、discordId、username、inviteUrl、membershipStatussummaryunlockedCount、totalCount、assignedDiscordRoleCount、claimableCount后端不支持领取功能时该字段缺省、planFREE | BASIC | PRO、hasActiveSubscriptionmetricscurrentStreakDays、longestStreakDays、cumulativeTokens、featuresUsedCount、trackedFeaturesCount、lastEvaluatedAt、lastSyncedAtachievements成就数组含title、description、unlocked、progressLabel、roleId、discordRoleStatus、creditAmountUsd、rewardTokens、rewardRecurring以及领取相关的claimable / claimed / claimedAt / claimPeriod后四者带缺省值保证旧后端返回的快照依然合法。绑定完成后每个已解锁成就都会展示其 Discord 角色分配状态角色状态含义Assigned已分配角色已在服务器上授予Pending待分配已解锁但角色尚未分配Join to claim加入后领取已绑定但未加入服务器——加入即可获得角色底层角色状态枚举更细assigned | not_assigned | not_linked | not_in_guild | not_configured | unavailablerewards.ts成员状态为member | not_in_guild | not_linked | unavailable。如果你已解锁带角色的成就但未加入服务器会出现一条claim banner提示你加入领取。POST /rewards/claim的返回RewardsClaimResult还携带alreadyClaimed幂等重复领取标识、tokens、amountUsd与newPromoBalanceUsd领取后新的促销余额说明部分成就是“可领取的月度/一次性 token 或 USD 信用”。5.4 与 GitHub 贡献者奖励的边界基于 GitHub 的贡献者奖励是独立机制一个 GitHub Actions 工作流会在贡献者首个 PR 合并后发布 Discord/周边merch邀请评论。它不属于应用内 Rewards 界面也不使用应用内的 GitHub OAuth。也就是说仓库里的contributor-rewards工作流与应用内奖励体系完全解耦不要混为一谈。六、Invite Codes 邀请码/invites/invites页面与推荐码是两码事。它管理的是门控新用户注册的个人邀请码invite codesRedeem兑换如果你尚未被邀请输入一个邀请码来抢占名额。Your invite codes我的邀请码发给你的一批邀请码列表。每行展示等宽字体monospace的码、复制按钮与enabled/disabled状态。当currentUses maxUses使用次数耗尽时该码自动翻转为禁用并显示是谁兑换了它。数据模型见 app/src/types/invite.tsexport interface InviteCode { _id: string; code: string; owner: string; type: USER | CAMPAIGN; // 邀请码类型 maxUses: number; // 最大可用次数 currentUses: number; // 当前已用次数 usageHistory: UsageHistoryEntry[]; // 谁在何时兑换 isActive: boolean; createdAt: string; }typeUSER用户发放或CAMPAIGN活动发放maxUses/currentUses使用额度计数器currentUses maxUses即失效usageHistory兑换记录每项包含兑换用户信息userId及其username/firstName等与usedAt时间戳。页面实现Invites.tsx中已兑尽的邀请码显示disabled徽章未兑尽则显示enabled徽章并有剪贴板反馈useClipboardFeedback。七、本地会话与后端会话的行为差异汇总一张表便于快速判断你在哪种会话下会遇到什么场景表现本地会话local-only打开/rewards显示空状态卡片提示需登录CTA 跳转/settings/account已登录后端会话但未存储会话令牌时调用 referral RPCfail closed错误no backend session token; run auth_store_session firstDiscord 未绑定成就的discordRoleStatus为not_linked需先执行 OAuth 连接已绑定但未加入服务器角色状态为not_in_guild出现 claim banner 提示加入八、总结与延伸阅读OpenHuman 的奖励与推荐体系在架构上刻意保持“薄客户端、厚服务端”业务规则金额、转化条件、资格、角色分配全部由托管后端裁决桌面端只做两件事——React 前端负责交互与展示Rust core 中的 referral 域以无状态 RPC 适配器方式代理请求以规避 WebViewfetch的 “Load failed” 问题。这种设计既保证了规则可以随时在服务端调整也让离线/本地模式下的降级路径非常清晰直接空状态 引导登录。想继续深入可以阅读Billing usage——推荐、优惠券与成就信用最终在哪里被消费Welcome文档首页referral 域实现README.md、ops.rs、schemas.rs前端页面与组件Rewards.tsx、Invites.tsx、RewardsCommunityTab.tsx、ReferralRewardsSection.tsx、RewardsCouponSection.tsx类型与 API 层referral.ts、rewards.ts、invite.ts、referralApi.ts、rewardsApi.ts设备指纹deviceFingerprint.ts。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进