Billing Automation
wshobson/agents
Covers building subscription billing: billing cycles, subscription states, invoice generation, proration, tax handling and dunning for failed payments.
Complete implementation guide for Telegram/Teamgram premium features and monetization (v2.0.0).
$ npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills telegram-premium-features --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/telegram-premium-features .claude/skills/telegram-premium-features && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "telegram-premium-features" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-features into .claude/skills/telegram-premium-features/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "telegram-premium-features", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-featuresType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills telegram-premium-features --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/telegram-premium-features .agents/skills/telegram-premium-features && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "telegram-premium-features" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-features into .agents/skills/telegram-premium-features/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "telegram-premium-features", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills telegram-premium-features --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/telegram-premium-features .cursor/skills/telegram-premium-features && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "telegram-premium-features" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-features into .cursor/skills/telegram-premium-features/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "telegram-premium-features", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LeoYeAI/openclaw-master-skills.git --path skills/telegram-premium-features--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills telegram-premium-features --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/telegram-premium-features .gemini/skills/telegram-premium-features && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "telegram-premium-features" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-features into .gemini/skills/telegram-premium-features/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "telegram-premium-features", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LeoYeAI/openclaw-master-skills telegram-premium-featuresInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/telegram-premium-features .github/skills/telegram-premium-features && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "telegram-premium-features" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-features into .github/skills/telegram-premium-features/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "telegram-premium-features", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills telegram-premium-features --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/telegram-premium-features .opencode/skills/telegram-premium-features && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "telegram-premium-features" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/telegram-premium-features into .opencode/skills/telegram-premium-features/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "telegram-premium-features", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
telegram-premium-featuresComplete implementation guide for Telegram/Teamgram premium features and monetization (v2.0.0).
Telegram Premium Features is an agent skill from LeoYeAI/openclaw-master-skills. Complete implementation guide for Telegram/Teamgram premium features and monetization (v2.0.0). Use when building membership systems, payment integration, subscription lifecycle, coupons, analytics, and global payment solutions. Covers ten iterations of optimization from basic implementation to production-ready systems.
Its SKILL.md is about 4.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 12 other files, including reference files (for example `_meta.json`, `references/v1.1.0-payment-gateways.md` and `references/v1.2.0-lifecycle.md`).
It sits in Backend & APIs, covering Payments and billing. It works with Telegram. The repository describes itself as: 🧠 Curated collection of 1209+ best OpenClaw skills — weekly updated by MyClaw.ai. The licence is MIT.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit e5199b5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are go and sql).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
stripe.comdeveloper.paypal.comrevenuecat.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Telegram Premium Features loads about 4.5k tokens when it runs, and up to ~7.9k if it reads all its reference files. Until then it costs about 87 tokens; SKILL.md has 233 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LeoYeAI/openclaw-master-skills at commit e5199b5, republished under its MIT licence (© LeoYeAI). 233 words, ~4,515 tokens.
.claude/skills/telegram-premium-features/SKILL.md (or your agent's skills folder). This skill also uses 11 other files; get the full folder from GitHub.Complete guide for implementing monetization features in Telegram-compatible backends.
📚 十次版本迭代优化 (v1.0.0 → v2.0.0)
本技能经过十次迭代完善,从基础会员系统到全球化支付解决方案的完整知识体系。
| 版本 | 主题 | 文档 |
|---|---|---|
| v1.0.0 | 基础实现 | 本指南 |
| v1.1.0 | 支付网关对比 | 查看 |
| v1.2.0 | 订阅生命周期 | 查看 |
| v1.3.0 | 优惠券促销 | 查看 |
| v1.4.0 | 税务合规 | 查看 |
| v1.5.0 | 退款争议 | 查看 |
| v1.6.0 | 推荐奖励 | 查看 |
| v1.7.0 | 数据分析 | 查看 |
| v1.8.0 | A/B测试 | 查看 |
| v1.9.0 | 国际化 | 查看 |
| v2.0.0 | 完整总结 | 查看 |
基础搭建: 从 Membership System 开始
支付集成: 查看 v1.1.0支付网关
运营优化: 参考 v1.3.0优惠券 和 v1.7.0数据分析
全球化: 查看 v1.9.0国际化
This guide covers common premium features for IM platforms:
┌─────────────────────────────────────────────────────────┐
│ Feature Check Flow │
├─────────────────────────────────────────────────────────┤
│ 1. User requests feature (e.g., send large file) │
│ 2. System checks user tier (free/premium) │
│ 3. If premium → allow │
│ 4. If free → check quota │
│ 5. If quota exceeded → show upgrade prompt │
└─────────────────────────────────────────────────────────┘| Tier | Features | Price |
|---|---|---|
| Free | Basic messaging, 100MB file limit, 1 month history | Free |
| Basic | 500MB file limit, 6 months history, no ads | $4.99/mo |
| Premium | 2GB file limit, unlimited history, priority support | $9.99/mo |
| Business | 4GB file limit, unlimited history, custom domains | $19.99/mo |
-- User subscription status
CREATE TABLE user_subscriptions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
tier ENUM('free', 'basic', 'premium', 'business') DEFAULT 'free',
status ENUM('active', 'expired', 'cancelled') DEFAULT 'active',
started_at BIGINT DEFAULT 0,
expires_at BIGINT DEFAULT 0,
auto_renew BOOLEAN DEFAULT FALSE,
payment_method VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_id (user_id),
INDEX idx_expires (expires_at),
INDEX idx_status (status)
) ENGINE=InnoDB;
-- Subscription plans
CREATE TABLE subscription_plans (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
tier ENUM('basic', 'premium', 'business') NOT NULL,
price_monthly DECIMAL(10,2) NOT NULL,
price_yearly DECIMAL(10,2) NOT NULL,
features JSON,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- Insert default plans
INSERT INTO subscription_plans (name, tier, price_monthly, price_yearly, features) VALUES
('Basic', 'basic', 4.99, 49.99, '{"file_limit": 536870912, "history_months": 6, "ads": false}'),
('Premium', 'premium', 9.99, 99.99, '{"file_limit": 2147483648, "history_months": -1, "priority_support": true}'),
('Business', 'business', 19.99, 199.99, '{"file_limit": 4294967296, "history_months": -1, "custom_domain": true}');-- User quotas (daily/monthly limits)
CREATE TABLE user_quotas (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
quota_type VARCHAR(50) NOT NULL,
limit_value BIGINT DEFAULT 0,
used_value BIGINT DEFAULT 0,
reset_at BIGINT DEFAULT 0,
UNIQUE KEY uk_user_type (user_id, quota_type)
) ENGINE=InnoDB;
-- Quota types: messages_daily, files_daily, storage_used// subscription_manager.go
type SubscriptionManager struct {
db *sqlx.DB
redis *redis.Client
}
// CheckUserTier 检查用户等级
func (m *SubscriptionManager) CheckUserTier(ctx context.Context, userID int64) (Tier, error) {
// Try cache
cacheKey := fmt.Sprintf("user:tier:%d", userID)
cached, err := m.redis.Get(ctx, cacheKey).Result()
if err == nil {
return Tier(cached), nil
}
// Query database
var sub UserSubscription
err = m.db.GetContext(ctx, &sub,
"SELECT * FROM user_subscriptions WHERE user_id = ?", userID)
if err == sql.ErrNoRows {
return TierFree, nil
}
if err != nil {
return TierFree, err
}
// Check expiration
if sub.Status == "expired" || (sub.ExpiresAt > 0 && sub.ExpiresAt < time.Now().Unix()) {
m.ExpireSubscription(ctx, userID)
return TierFree, nil
}
// Cache result
m.redis.Set(ctx, cacheKey, string(sub.Tier), 5*time.Minute)
return Tier(sub.Tier), nil
}
// CheckFeatureAccess 检查功能访问权限
func (m *SubscriptionManager) CheckFeatureAccess(ctx context.Context, userID int64, feature string) (bool, error) {
tier, err := m.CheckUserTier(ctx, userID)
if err != nil {
return false, err
}
// Feature requirement mapping
requirements := map[string]Tier{
"large_files": TierBasic,
"unlimited_history": TierPremium,
"custom_domain": TierBusiness,
"priority_support": TierPremium,
}
requiredTier, exists := requirements[feature]
if !exists {
return true, nil // Feature doesn't require tier
}
return tier >= requiredTier, nil
}
// CheckQuota 检查配额
func (m *SubscriptionManager) CheckQuota(ctx context.Context, userID int64, quotaType string) (bool, int64, error) {
tier, _ := m.CheckUserTier(ctx, userID)
// Get tier limits
limits := m.getTierLimits(tier)
limit := limits[quotaType]
if limit < 0 {
return true, -1, nil // Unlimited
}
// Get current usage
var quota UserQuota
err := m.db.GetContext(ctx, "a,
"SELECT * FROM user_quotas WHERE user_id = ? AND quota_type = ?",
userID, quotaType)
if err == sql.ErrNoRows {
// No record yet
return true, limit, nil
}
if err != nil {
return false, 0, err
}
// Check if need reset
if quota.ResetAt < time.Now().Unix() {
m.resetQuota(ctx, userID, quotaType)
return true, limit, nil
}
remaining := limit - quota.UsedValue
return remaining > 0, remaining, nil
}
// UseQuota 使用配额
func (m *SubscriptionManager) UseQuota(ctx context.Context, userID int64, quotaType string, amount int64) error {
_, err := m.db.ExecContext(ctx,
`INSERT INTO user_quotas (user_id, quota_type, used_value, reset_at)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE used_value = used_value + VALUES(used_value)`,
userID, quotaType, amount, getNextResetTime())
return err
}
func (m *SubscriptionManager) getTierLimits(tier Tier) map[string]int64 {
limits := map[Tier]map[string]int64{
TierFree: {
"messages_daily": 1000,
"files_daily": 50,
"file_size": 100 * 1024 * 1024, // 100MB
"storage": 1024 * 1024 * 1024, // 1GB
},
TierBasic: {
"messages_daily": 10000,
"files_daily": 500,
"file_size": 500 * 1024 * 1024, // 500MB
"storage": 10 * 1024 * 1024 * 1024, // 10GB
},
TierPremium: {
"messages_daily": -1, // Unlimited
"files_daily": -1,
"file_size": 2 * 1024 * 1024 * 1024, // 2GB
"storage": 100 * 1024 * 1024 * 1024, // 100GB
},
}
return limits[tier]
}// stripe_payment.go
import "github.com/stripe/stripe-go/v74"
type StripePayment struct {
client *stripe.Client
}
func (p *StripePayment) CreateCheckoutSession(ctx context.Context, userID int64, planID int) (string, error) {
// Get plan details
plan, err := p.getPlan(ctx, planID)
if err != nil {
return "", err
}
params := &stripe.CheckoutSessionParams{
CustomerEmail: stripe.String(getUserEmail(userID)),
LineItems: []*stripe.CheckoutSessionLineItemParams{
{
PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{
Currency: stripe.String("usd"),
ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{
Name: stripe.String(plan.Name),
},
UnitAmount: stripe.Int64(int64(plan.Price * 100)), // cents
},
Quantity: stripe.Int64(1),
},
},
Mode: stripe.String(string(stripe.CheckoutSessionModeSubscription)),
SuccessURL: stripe.String(fmt.Sprintf("https://yourapp.com/success?user=%d", userID)),
CancelURL: stripe.String("https://yourapp.com/cancel"),
Metadata: map[string]string{
"user_id": fmt.Sprintf("%d", userID),
"plan_id": fmt.Sprintf("%d", planID),
},
}
session, err := stripe.CheckoutSession(params)
if err != nil {
return "", err
}
return session.URL, nil
}
func (p *StripePayment) HandleWebhook(payload []byte, sig string) error {
event, err := stripe.Webhook(payload, sig, webhookSecret)
if err != nil {
return err
}
switch event.Type {
case "checkout.session.completed":
var session stripe.CheckoutSession
err := json.Unmarshal(event.Data.Raw, &session)
if err != nil {
return err
}
userID, _ := strconv.ParseInt(session.Metadata["user_id"], 10, 64)
planID, _ := strconv.Atoi(session.Metadata["plan_id"])
// Activate subscription
p.activateSubscription(userID, planID, session.Subscription.ID)
case "invoice.payment_failed":
// Handle failed payment
p.handlePaymentFailure(event)
}
return nil
}// payment_webhook.go
func (s *Server) PaymentWebhook(ctx context.Context, req *PaymentWebhookReq) (*Bool, error) {
switch req.Provider {
case "stripe":
err := s.stripePayment.HandleWebhook(req.Payload, req.Signature)
if err != nil {
return BoolFalse, err
}
case "alipay":
err := s.alipayPayment.HandleNotify(req.Payload)
if err != nil {
return BoolFalse, err
}
}
return BoolTrue, nil
}// middleware/premium_middleware.go
func PremiumMiddleware(next HandlerFunc) HandlerFunc {
return func(ctx context.Context, req Request) (Response, error) {
userID := getUserIDFromContext(ctx)
feature := getFeatureFromRequest(req)
// Check access
hasAccess, err := subscriptionManager.CheckFeatureAccess(ctx, userID, feature)
if err != nil {
return nil, err
}
if !hasAccess {
return nil, status.Error(codes.PermissionDenied,
"This feature requires premium subscription")
}
// Check quota for usage-based features
if isQuotaBased(feature) {
allowed, remaining, err := subscriptionManager.CheckQuota(ctx, userID, feature)
if err != nil {
return nil, err
}
if !allowed {
return nil, status.Errorf(codes.ResourceExhausted,
"Quota exceeded. Upgrade to get more.")
}
// Update context with remaining quota
ctx = context.WithValue(ctx, "remaining_quota", remaining)
}
return next(ctx, req)
}
}func (s *Server) MessagesSendDocument(ctx context.Context, req *SendDocumentReq) (*Message, error) {
userID := getUserIDFromContext(ctx)
fileSize := req.File.Size
// Check file size limit
tier, _ := s.subManager.CheckUserTier(ctx, userID)
limits := s.subManager.getTierLimits(tier)
if fileSize > limits["file_size"] {
return nil, status.Errorf(codes.FailedPrecondition,
"File too large. Max size for your tier: %d MB",
limits["file_size"]/(1024*1024))
}
// Check and use quota
allowed, _, err := s.subManager.CheckQuota(ctx, userID, "files_daily")
if err != nil {
return nil, err
}
if !allowed {
return nil, status.Errorf(codes.ResourceExhausted,
"Daily file upload limit reached. Upgrade for unlimited uploads.")
}
// Use quota
s.subManager.UseQuota(ctx, userID, "files_daily", 1)
// Process document...
}// admin/analytics.go
type RevenueAnalytics struct {
db *sqlx.DB
}
func (a *RevenueAnalytics) GetRevenueReport(ctx context.Context, start, end time.Time) (*RevenueReport, error) {
query := `
SELECT
DATE(created_at) as date,
SUM(amount) as revenue,
COUNT(*) as transactions,
tier,
payment_method
FROM premium_transactions
WHERE status = 1
AND created_at BETWEEN ? AND ?
GROUP BY DATE(created_at), tier, payment_method
ORDER BY date DESC
`
var rows []RevenueRow
err := a.db.SelectContext(ctx, &rows, query, start, end)
if err != nil {
return nil, err
}
return &RevenueReport{
Rows: rows,
Total: sumRevenue(rows),
StartDate: start,
EndDate: end,
}, nil
}
func (a *RevenueAnalytics) GetUserRetention(ctx context.Context) (*RetentionReport, error) {
query := `
SELECT
tier,
COUNT(*) as total_users,
SUM(CASE WHEN expires_at > NOW() THEN 1 ELSE 0 END) as active_users,
SUM(CASE WHEN auto_renew = 1 THEN 1 ELSE 0 END) as auto_renew_users
FROM user_subscriptions
GROUP BY tier
`
var rows []RetentionRow
err := a.db.SelectContext(ctx, &rows, query)
return &RetentionReport{Rows: rows}, err
}// Client receives error and shows upgrade dialog
func handleSendFileError(err error) {
if status.Code(err) == codes.FailedPrecondition {
// Show upgrade dialog
showUpgradeDialog(
title: "File Too Large",
message: "Upgrade to Premium to send files up to 2GB",
plans: getAvailablePlans()
)
} else if status.Code(err) == codes.ResourceExhausted {
// Show quota exceeded dialog
showUpgradeDialog(
title: "Daily Limit Reached",
message: "You've reached your daily upload limit. Upgrade for unlimited uploads.",
plans: getAvailablePlans()
)
}
}func TestSubscriptionManager(t *testing.T) {
ctx := context.Background()
manager := NewSubscriptionManager(testDB, testRedis)
t.Run("CheckUserTier", func(t *testing.T) {
// Free user
tier, err := manager.CheckUserTier(ctx, 1)
assert.NoError(t, err)
assert.Equal(t, TierFree, tier)
// Premium user
tier, err = manager.CheckUserTier(ctx, 2)
assert.NoError(t, err)
assert.Equal(t, TierPremium, tier)
})
t.Run("CheckFeatureAccess", func(t *testing.T) {
// Free user can't access premium feature
hasAccess, err := manager.CheckFeatureAccess(ctx, 1, "large_files")
assert.NoError(t, err)
assert.False(t, hasAccess)
// Premium user can access
hasAccess, err = manager.CheckFeatureAccess(ctx, 2, "large_files")
assert.NoError(t, err)
assert.True(t, hasAccess)
})
t.Run("CheckQuota", func(t *testing.T) {
// Free user has limited quota
allowed, remaining, err := manager.CheckQuota(ctx, 1, "files_daily")
assert.NoError(t, err)
assert.True(t, allowed)
assert.Equal(t, int64(50), remaining)
// Premium user has unlimited
allowed, remaining, err = manager.CheckQuota(ctx, 2, "files_daily")
assert.NoError(t, err)
assert.True(t, allowed)
assert.Equal(t, int64(-1), remaining) // Unlimited
})
}© LeoYeAI, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 11 other files (references) in skills/telegram-premium-features of LeoYeAI/openclaw-master-skills.
Open the folder on GitHubat commit e5199b5
Telegram Premium Features next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Telegram Premium Features this skillLeoYeAI/openclaw-master-skills | 2.2k | — | ~4.5k | Automated safety check: Pass | MIT | |
| Billing Automationwshobson/agents | 40k | 13 repos | ~473 | Automated safety check: Pass | MIT | |
| LangBot EBA Adapter Developmentlangbot-app/LangBot | 18k | — | ~4k | Automated safety check: Pass | Apache-2.0 | |
| Fatecattradecatlabs/fatecat | 202 | — | ~1.7k | Automated safety check: Notes | MIT | |
| Tlgrtlgrcli/tlgr | 193 | — | ~1.5k | Automated safety check: Pass | MIT | |
| Add Channel Connect Buttonnovuhq/novu | 40k | — | ~1.6k | Automated safety check: Pass | Custom licence |
wshobson/agents
Covers building subscription billing: billing cycles, subscription states, invoice generation, proration, tax handling and dunning for failed payments.
langbot-app/LangBot
Guides building, migrating and testing LangBot messaging-platform adapters for the Event-Based Agents layout, with unified event and message conversion.
tradecatlabs/fatecat
FateCat 执行型测算基础设施 skill:安装并校验当前仓库,执行生产化 capability,输出 JSON / Markdown,启动 Web / API / Telegram 交付层,并在发布前运行仓库卫生与生产就绪门禁。Use when 用户要求测算、排盘、生成报告、启动 Web/API/Bot、验收 skill、导出 bundle、检查生产可用性。
tlgrcli/tlgr
Read and act on a personal Telegram account from the terminal with the tlgr CLI (MTProto user account, not a bot).
novuhq/novu
Build a new channel Connect button (e.g. An agent skill from novuhq/novu.
better-notify/better-notify
End-to-end typed notification infrastructure for Node.js — typed catalog of email, SMS, push, web push, WhatsApp, Slack, Discord, Telegram, and GitHub notifications with provider-agnostic transports.
LeoYeAI/openclaw-master-skills
Manages pipelines on a DevOps quality and efficiency platform through its OpenAPI: list workspaces and templates, create, update, run and cancel pipelines, and read run records.
LeoYeAI/openclaw-master-skills
Patches OpenClaw's Feishu extension so an edited document triggers an isolated agent session that reads the doc and replies inline, turning it into a live chat space.
LeoYeAI/openclaw-master-skills
Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation.
LeoYeAI/openclaw-master-skills
Runs a brand's AI-search visibility work end to end: diagnosing how AI platforms represent it, repositioning it, producing AI-optimized content and monitoring ongoing mentions.
LeoYeAI/openclaw-master-skills
Installs and authenticates the gws CLI, then automates Gmail, Drive, Sheets, Calendar, Docs, Chat and Tasks with ready-made recipes, persona bundles and security audits.
LeoYeAI/openclaw-master-skills
Runs four advisor roles, a fitness coach, nutritionist, data analyst and TCM practitioner, to build a health profile and track workouts, diet and wellness over time.
Works with
Categories
Complete implementation guide for Telegram/Teamgram premium features and monetization (v2.0.0). Telegram Premium Features is an agent skill from LeoYeAI/openclaw-master-skills.0).
Telegram Premium Features fits situations like: building membership systems; payment integration; subscription lifecycle; global payment solutions.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a claude-code`. Or copy the skill folder (skills/telegram-premium-features in LeoYeAI/openclaw-master-skills) into .claude/skills/telegram-premium-features in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a codex`. Or copy the skill folder (skills/telegram-premium-features in LeoYeAI/openclaw-master-skills) into .agents/skills/telegram-premium-features in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LeoYeAI/openclaw-master-skills --skill telegram-premium-features -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/telegram-premium-features, .gemini/skills/telegram-premium-features, .github/skills/telegram-premium-features and .opencode/skills/telegram-premium-features in your project.
SKILL.md names no scripts, command-line tools or credentials: Telegram Premium Features is instructions for the agent only.
SKILL.md names 3 domains. As links in the text: stripe.com, developer.paypal.com and revenuecat.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Telegram Premium Features is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.5k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.4k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Telegram Premium Features: Billing Automation (wshobson/agents, 40k stars), LangBot EBA Adapter Development (langbot-app/LangBot, 18k stars), Fatecat (tradecatlabs/fatecat, 202 stars) and Tlgr (tlgrcli/tlgr, 193 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LeoYeAI (a GitHub user) maintains it in LeoYeAI/openclaw-master-skills, which has 2,160 GitHub stars. The repository holds 1,235 skills in this directory. The repository was last updated on July 20, 2026.
Source: LeoYeAI/openclaw-master-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.