requesthunt
PublicRepository: resciencelab/opc-skills
Low Risk
No security issues found
Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms.
Remediation Add 'license' field to SKILL.md frontmatter (e.g., MIT, Apache-2.0)
Description
Generate user demand research reports from real user feedback. Scrape and analyze feature requests, complaints, and questions from Reddit, X, and GitHub. Use when user wants to do demand research, find feature requests, analyze user demand, or run RequestHunt queries.
Skill Files
# RequestHunt Skill Generate user demand research reports by collecting and analyzing real user feedback from Reddit, X (Twitter), and GitHub. ## Prerequisites Set API key in `~/.zshrc`: ```bash export REQUESTHUNT_API_KEY="your_api_key" ``` Get your key from: https://requesthunt.com/settings/api **Quick Check**: ```bash cd <skill_directory> python3 scripts/get_usage.py ``` ## Research Workflow This skill helps you generate comprehensive user demand research reports. Follow this workflow: ### Step 1: Define Scope Before collecting data, clarify with the user: 1. **Research Goal**: What domain/area to investigate? (e.g., AI coding assistants, project management tools) 2. **Specific Products**: Any products/competitors to focus on? (e.g., Cursor, GitHub Copilot) 3. **Platform Preference**: Which platforms to prioritize? (reddit, x, github) 4. **Time Range**: How recent should the feedback be? 5. **Report Purpose**: Product planning / competitive analysis / market research? ### Step 2: Collect Data ```bash # 1. Trigger realtime scrape for the topic python3 scripts/scrape_topic.py "ai-coding-assistant" --platforms reddit,x,github # 2. Search with expansion for more data python3 scripts/search_requests.py "code completion" --expand --limit 50 # 3. List requests filtered by topic python3 scripts/list_requests.py --topic "ai-tools" --limit 100 ``` ### Step 3: Generate Report Analyze collected data and generate a structured Markdown report: ```markdown # [Topic] User Demand Research Report ## Overview - Scope: ... - Data Sources: Reddit (X), X (Y), GitHub (Z) - Time Range: ... ## Key Findings ### 1. Top Feature Requests | Rank | Request | Sources | Representative Quote | |------|---------|---------|---------------------| ### 2. Pain Points Analysis - **Pain Point A**: ... ### 3. Competitive Comparison (if specified) | Feature | Product A | Product B | User Expectations | ### 4. Opportunities - ... ## Methodology Based on N real user feedbacks collected via RequestHunt... ``` ## Commands All commands run from the skill directory. ### List Requests ```bash python3 scripts/list_requests.py --limit 20 # Recent requests python3 scripts/list_requests.py --topic "ai-tools" --limit 10 # By topic python3 scripts/list_requests.py --platforms reddit,github # By platform python3 scripts/list_requests.py --category "Developer Tools" # By category python3 scripts/list_requests.py --sortBy top --limit 20 # Top voted ``` ### Search Requests ```bash python3 scripts/search_requests.py "authentication" --limit 20 python3 scripts/search_requests.py "oauth" --expand # With realtime expansion python3 scripts/search_requests.py "API rate limit" --expand --platforms reddit,x ``` ### Get Topics ```bash python3 scripts/get_topics.py # List all topics by category ``` ### Check Usage ```bash python3 scripts/get_usage.py # View API usage stats ``` ### Scrape Topic (Realtime) ```bash python3 scripts/scrape_topic.py "developer-tools" # Default: reddit,x python3 scripts/scrape_topic.py "ai-assistant" --platforms reddit,x,github ``` ## API Info - **Base URL**: https://requesthunt.com - **Auth**: Bearer token (API key) - **Rate Limits**: - Cached requests: 1000/month - Realtime requests: 500/month (scraping is expensive) - **Docs**: https://requesthunt.com/docs
{
"name": "requesthunt",
"version": "1.0.0",
"description": "Generate user demand research reports from real user feedback. Scrape and analyze feature requests, complaints, and questions from Reddit, X, and GitHub.",
"author": {
"name": "ReScienceLab"
},
"homepage": "https://github.com/ReScienceLab/opc-skills/tree/main/skills/requesthunt",
"repository": "https://github.com/ReScienceLab/opc-skills",
"license": "MIT",
"keywords": [
"requesthunt",
"request hunt",
"feature request",
"user demand",
"demand research"
],
"skills": [
"./SKILL.md"
],
"commands": [
"./scripts/"
]
}
# RequestHunt Example: Deep Investigation into Calendar/Scheduling Apps This is a complete conversation example showing how the requesthunt skill helps users conduct user demand research by collecting and analyzing real user feedback from Reddit, X (Twitter), and GitHub. --- ## Conversation ### User > I want to use requesthunt skill to have a deep investigation into Calendar app. ### Assistant I'll help you conduct a deep investigation into Calendar apps using RequestHunt. Let me first check the API setup and then gather user feedback data. **Checking API Usage:** ```bash python3 scripts/get_usage.py ``` ``` # RequestHunt API Usage ## Cached Requests - **Used**: 1 / 2000 - **Remaining**: 1999 ## Realtime Requests - **Used**: 64 / 500 - **Remaining**: 436 ``` API is working. Before I start collecting data, let me clarify the research scope: **Questions to define the investigation:** 1. **Specific Calendar apps to focus on?** (e.g., Google Calendar, Apple Calendar, Outlook, Calendly, Cal.com, Notion Calendar, Fantastical, etc.) 2. **Research focus?** (General calendar apps / Scheduling tools / Team calendars / Personal productivity) 3. **What are you trying to learn?** (Feature gaps / Competitive analysis / Market opportunity) 4. **Platform preference?** Reddit, X, GitHub - or all three? --- ### User > 1. cal.com and similar apps 2. Scheduling/booking tools 3. user pain points 4. all ### Assistant *Starting data collection across all platforms...* **Step 1: Scrape Topic** ```bash python3 scripts/scrape_topic.py "scheduling-tools" --platforms reddit,x,github ``` ``` # Scrape Job Started - **Job ID**: kx71s2ccqederm61w3whaaqhvd7zd6cq - **Topic**: scheduling-tools - **Platforms**: reddit, x, github - **Status**: pending ``` **Step 2: Search for Cal.com feedback** ```bash python3 scripts/search_requests.py "cal.com" --expand --platforms reddit,x,github --limit 50 ``` **Results (50 requests):** | Request | Platform | Votes | |---------|----------|-------| | Embed Cal.com Integration inside website | GitHub | 0 | | Integrate NextCloudTalk with Cal.com | GitHub | 3 | | Create Task Trigger on New Bookings (Todoist) | GitHub | 3 | | Insights API for Booking Data | GitHub | 0 | | Native Zoho Meeting Integration | GitHub | 4 | | Limit Time for Cancelling/Rescheduling | GitHub | 4 | | Add auto-accept feature for appointments | X | 0 | | Allow rotating client secret | GitHub | 0 | | Batch bookings together | GitHub | 0 | | Add MCP integration for AI workflows | GitHub | 0 | **Step 3: Search for Calendly feedback** ```bash python3 scripts/search_requests.py "calendly" --expand --platforms reddit,x,github --limit 50 ``` **Results (18 requests):** | Request | Platform | Votes | |---------|----------|-------| | Add 'blocked schedule' feature | X | **267** | | Add reminders for scheduled appointments | X | 0 | | Add location-specific time slots | Reddit | 1 | | Implement booking routing based on multiple rules | Reddit | 3 | | Implement automated reminders for no-show | Reddit | 4 | | Add ability to delete/cancel one-use links | Reddit | 2 | **Step 4: Search for appointment scheduling pain points** ```bash python3 scripts/search_requests.py "appointment scheduling" --expand --platforms reddit,x --limit 30 ``` **Key findings:** - SMS notifications for healthcare scheduling (8 votes) - Flexible appointment times for therapy apps - CRM automated follow-ups and scheduling (5 votes, 17 comments) - Voice AI appointment reminders (16 votes) **Step 5: Search for booking software feedback** ```bash python3 scripts/search_requests.py "booking software" --expand --platforms reddit,x --limit 30 ``` **Key findings:** - GP booking system usability overhaul (259 votes) - Simple booking system for meeting rooms (20 votes, 41 comments) - Price drop alerts for bookings (18 votes) **Step 6: Search for scheduling pain points** ```bash python3 scripts/search_requests.py "scheduling pain" --expand --platforms reddit,x --limit 30 ``` **Key findings:** - NomadTime: suggest optimal meeting times across timezones - Streamline scheduling to reduce back-and-forth - Gang scheduling support for Kubernetes (28 votes) **Step 7: Search for no-show management** ```bash python3 scripts/search_requests.py "no-show booking" --expand --platforms reddit,x --limit 20 ``` **Key findings:** - Automated reminder sequences (6 votes) - No-show prediction models - Over-booking systems to accommodate no-shows - Improve refund process for no-show situations --- ## Generated Research Report ### Executive Summary Users of scheduling/booking tools like Cal.com and Calendly experience significant friction around **time slot management**, **no-show prevention**, **integration limitations**, and **booking workflow inflexibility**. The most critical pain points revolve around meetings being scattered throughout the day (destroying focus time), last-minute cancellations/rescheduling, and limited customization options. --- ### Top 10 Pain Points #### 1. Scattered Meetings Destroying Focus Time (HIGH PRIORITY) **Votes: 267** (X) Users are frustrated that scheduling tools allow bookings scattered throughout the day, fragmenting their work time. > "I have a large window for meetings, and what often happens is someone will book at 13:00, another one at 15:00 and then at 16:00. Each meeting is 30 minutes and instead of having all of them one after the other I have to wait." — @ilan-grif (GitHub) > "User requests a feature in Calendly that allows booking only before or after existing meetings, creating blocks of time for focused work." — @JoshConstine (X, 267 likes) **Opportunity**: Smart batching algorithm that groups meetings together automatically. --- #### 2. Last-Minute Cancellations & Rescheduling (HIGH PRIORITY) **Votes: 4** (GitHub) > "There is a Minimum Limit (for event) that can be set up so people cannot book last minute meetings. Currently, there is no option for cancellation/rescheduling limits." **Opportunity**: Cancellation/rescheduling policies with time limits and fees. --- #### 3. No-Show Management (HIGH PRIORITY) **Votes: 6** (X) > "User wants to automate sending reminders to clients marked as no-show until they reschedule their appointment." **Opportunity**: AI-powered no-show prediction + aggressive reminder sequences + overbooking options. --- #### 4. Integration Gaps (MEDIUM-HIGH) | Missing Integration | Votes | |--------------------|-------| | Nextcloud Talk | 3 | | Zoho Meeting | 4 | | iDEAL payment (Stripe) | 0 | | Todoist task creation | 3 | | MCP for AI workflows | 0 | --- #### 5. Booking Slot Inflexibility (MEDIUM) > "When external calendar events create gaps in my availability, Cal.com offers booking slots that start at non-standard times based on when those gaps begin—rather than respecting my preferred scheduling intervals." --- #### 6. Post-Booking Editing Issues (MEDIUM) > "Allow users to edit booking details, such as correcting email addresses, after a booking has been made instead of requiring cancellation and rebooking." --- #### 7. Analytics & Insights (MEDIUM) **Votes: 257** (X) > "Introduce a built-in analytics dashboard that gives users clear insights into their scheduling activity." > "Meeting cost calculator based on attendee time" — 257 votes on X --- #### 8. Notification & Reminder Gaps (MEDIUM) | Request | Votes | |---------|-------| | Voice AI reminders | 16 | | SMS notifications | 8 | | ntfy.sh support | 0 | --- #### 9. Team & Routing Complexity (MEDIUM) > "Currently, when an Event Type is set to 'Requires Confirmation,' the admin is blocked from approving a booking request if a conflicting event exists in that slot." --- #### 10. Embed & Localization Issues (LOWER) > "Embedded calendars use browser language, not site language." --- ### Feature Priority Matrix | Priority | Feature | Impact | |----------|---------|--------| | **Must-Have** | Meeting batching/adjacency booking | Preserve focus time | | **Must-Have** | Cancellation/reschedule time limits | Reduce last-minute changes | | **Must-Have** | No-show automation | Reminder sequences + prediction | | **Must-Have** | Post-booking editing | Fix mistakes without rebooking | | **Should-Have** | Native analytics dashboard | Booking insights | | **Should-Have** | Broader integrations | Zoho, Nextcloud, iDEAL | | **Should-Have** | Advanced routing rules | Multi-factor booking assignment | | **Nice-to-Have** | AI scheduling assistant | MCP integration | | **Nice-to-Have** | Meeting cost calculator | Time = money awareness | --- ### Top Voted Requests (Appendix) | Request | Platform | Votes | |---------|----------|-------| | Google Meet refund request for late meetings | X | **1,829** | | Production-ready meeting bot API | X | 332 | | Block scheduling (only book adjacent) | X | 267 | | GP booking system usability overhaul | X | 259 | | Meeting cost calculator | X | 257 | | Big calendar component for MUI | GitHub | 194 | --- ### Methodology This report analyzed **150+ real user feedback items** collected via RequestHunt from: - **Reddit**: r/calendly, r/smallbusiness, r/productivity, r/CRM, r/remotework - **X (Twitter)**: Direct feature requests and complaints - **GitHub**: Cal.com issues repository and related projects **API Usage:** - 7 search queries with realtime expansion - 1 topic scrape job - Total: ~75 realtime requests consumed --- ## Key Takeaways 1. **scrape_topic.py** triggers background scraping for a topic across platforms 2. **search_requests.py --expand** fetches fresh data in realtime (uses quota) 3. **Multiple search terms** help capture different aspects of the same problem 4. **Quantitative data** (votes, comments) helps prioritize findings 5. **Final report** synthesizes patterns into actionable insights
# Scheduling/Booking Tools User Demand Research Report ## Overview - **Scope**: Cal.com, Calendly, and similar scheduling/booking tools - **Focus**: User pain points and feature gaps - **Data Sources**: Reddit, X (Twitter), GitHub - **Feedback Collected**: 150+ real user requests and complaints - **Date**: January 2026 --- ## Executive Summary Users of scheduling/booking tools like Cal.com and Calendly experience significant friction around **time slot management**, **no-show prevention**, **integration limitations**, and **booking workflow inflexibility**. The most critical pain points revolve around meetings being scattered throughout the day (destroying focus time), last-minute cancellations/rescheduling, and limited customization options. --- ## Key Pain Points ### 1. Scattered Meetings Destroying Focus Time (High Priority) Users are frustrated that scheduling tools allow bookings scattered throughout the day, fragmenting their work time. | Issue | Sources | Votes | |-------|---------|-------| | Meetings get spread out (13:00, 15:00, 16:00) instead of batched | GitHub | 0 | | Need "blocked schedule" - only book before/after existing meetings | X | **267** | | Adjacency-only booking to preserve deep work blocks | GitHub | 0 | **Representative Quotes:** > "I have a large window for meetings, and what often happens is someone will book at 13:00, another one at 15:00 and then at 16:00. Each meeting is 30 minutes and instead of having all of them one after the other I have to wait." — @ilan-grif (GitHub) > "User requests a feature in Calendly that allows booking only before or after existing meetings, creating blocks of time for focused work." — @JoshConstine (X, 267 likes) **Opportunity**: Smart batching algorithm that groups meetings together automatically. --- ### 2. Last-Minute Cancellations & Rescheduling (High Priority) Users lack control over when attendees can cancel or reschedule. | Issue | Sources | Votes | |-------|---------|-------| | No limit for cancellation/rescheduling meetings | GitHub | 4 | | Need auto-accept with disabled cancel/reschedule options | X | 0 | | Automated reminders for no-show appointments | Reddit | 4 | **Representative Quotes:** > "There is a Minimum Limit (for event) that can be set up so people cannot book last minute meetings. Currently, there is no option for cancellation/rescheduling limits, which leads to frustration when users can reschedule or cancel last minute." — @barjoy01 (GitHub) **Opportunity**: Cancellation/rescheduling policies with time limits and fees. --- ### 3. No-Show Management (High Priority) No-shows waste time and revenue, but tools lack proactive prevention. | Issue | Sources | Votes | |-------|---------|-------| | Need automated reminder sequences | X | 6 | | Automated reminders until no-shows reschedule | Reddit | 4 | | No-show prediction models | X | 0 | | Over-booking systems to accommodate anticipated no-shows | X | 0 | **Representative Quotes:** > "User wants to automate sending reminders to clients marked as no-show until they reschedule their appointment, improving follow-up efficiency." — @jprime4 (Reddit) **Opportunity**: AI-powered no-show prediction + aggressive reminder sequences + overbooking options. --- ### 4. Integration Gaps (Medium-High Priority) Users need more native integrations with their existing tools. | Missing Integration | Sources | Votes | |--------------------|---------|-------| | Nextcloud Talk video conferencing | GitHub | 3 | | Zoho Meeting | GitHub | 4 | | iDEAL payment method (Stripe) | GitHub | 0 | | Todoist task creation on booking | GitHub | 3 | | MCP (Model Context Protocol) for AI workflows | GitHub | 0 | | Google Calendar sync issues | X | 1 | **Representative Quotes:** > "For users who self-host their infrastructure using Nextcloud, this means they cannot automatically generate video conference links for their scheduled meetings." — @onerpsystems (GitHub) **Opportunity**: Broader integration ecosystem, especially for self-hosted and European tools. --- ### 5. Booking Slot Inflexibility (Medium Priority) Time slot generation doesn't adapt well to real-world scenarios. | Issue | Sources | Votes | |-------|---------|-------| | Non-standard slot times when gaps exist | GitHub | 0 | | Calendar shows default times (9-5) even with custom settings | GitHub | 3 | | Need location-specific time slots | Reddit | 1 | | Booking slots start at odd times based on external calendar gaps | GitHub | 0 | **Representative Quotes:** > "When external calendar events create gaps in my availability, Cal.com offers booking slots that start at non-standard times based on when those gaps begin—rather than respecting my preferred scheduling intervals." — @ostahl8 (GitHub) **Opportunity**: Smarter slot generation that respects user preferences even with external conflicts. --- ### 6. Post-Booking Editing Issues (Medium Priority) Users cannot easily fix mistakes after booking. | Issue | Sources | Votes | |-------|---------|-------| | Cannot edit booking details (email typos) after creation | GitHub | 0 | | Cannot delete or cancel one-use links | Reddit | 2 | | Cannot update location to Google Meet/Zoom after booking | GitHub | 0 | **Representative Quotes:** > "Allow users to edit booking details, such as correcting email addresses, after a booking has been made instead of requiring cancellation and rebooking." — @mrkylegp (GitHub) **Opportunity**: Post-booking editing capabilities with audit trail. --- ### 7. Analytics & Insights (Medium Priority) Users want better visibility into their scheduling patterns. | Issue | Sources | Votes | |-------|---------|-------| | Need built-in analytics dashboard | GitHub | 0 | | Insights API for programmatic access | GitHub | 0 | | Booking completed webhooks for stats | GitHub | 0 | | Meeting cost calculator based on attendee time | X | **257** | **Representative Quotes:** > "Introduce a built-in analytics dashboard that gives users clear insights into their scheduling activity, displaying key metrics such as total bookings, cancellation rates, or event type usage." — @lohithg-15 (GitHub) **Opportunity**: Native analytics with conversion funnels, no-show rates, and time utilization metrics. --- ### 8. Notification & Reminder Gaps (Medium Priority) Current notification systems are insufficient. | Issue | Sources | Votes | |-------|---------|-------| | Notifications via ntfy.sh (self-hosted) | GitHub | 0 | | SMS notifications for healthcare | X | 8 | | Voice AI appointment reminders | X | 16 | | Reminders for scheduled appointments | X | 0 | **Representative Quotes:** > "User expresses frustration over the lack of notifications in the product, which they find to be an organizational hazard." — @justin-hackin (GitHub) **Opportunity**: Multi-channel notifications (SMS, push, voice AI, self-hosted options). --- ### 9. Team & Routing Complexity (Medium Priority) Business users need more sophisticated routing logic. | Issue | Sources | Votes | |-------|---------|-------| | Booking routing based on multiple rules (HubSpot) | Reddit | 3 | | Team visibility for reservations | Reddit | 2 | | Admin override for high-priority bookings | GitHub | 0 | **Representative Quotes:** > "Currently, when an Event Type is set to 'Requires Confirmation,' the admin is blocked from approving a booking request if a conflicting event exists in that slot. An admin should be able to approve high-priority clients without changing the event settings temporarily." — @scopecreepsoap (GitHub) **Opportunity**: Advanced routing rules + priority override system. --- ### 10. Embed & Localization Issues (Lower Priority) Embedded calendars have UX issues. | Issue | Sources | Votes | |-------|---------|-------| | Embedded calendars use browser language, not site language | GitHub | 0 | | Pop-up loading slows down pages | GitHub | 0 | | Mobile feature parity issues | GitHub | 0 | **Opportunity**: Better embed customization and mobile experience. --- ## Competitive Landscape ### Cal.com vs Calendly - User Preferences | Feature | Cal.com | Calendly | User Preference | |---------|---------|----------|-----------------| | Open source | Yes | No | Cal.com (self-hosters) | | Pricing | Generous free tier | Limited free tier | Cal.com | | Integrations | Growing | Mature | Calendly | | Enterprise features | Developing | Mature | Calendly | | Customization | Higher | Lower | Cal.com | ### Emerging Competitors Mentioned - **Custom solutions**: Users building their own due to specific needs - **Setmore**: Mentioned as lacking flexibility for service packages - **10to8**: Criticized for half-hour scheduling assumptions --- ## Feature Request Summary by Priority ### Must-Have (Immediate Impact) 1. **Meeting batching/adjacency booking** - Preserve focus time 2. **Cancellation/reschedule time limits** - Reduce last-minute changes 3. **No-show automation** - Reminder sequences + prediction 4. **Post-booking editing** - Fix mistakes without rebooking ### Should-Have (Competitive Advantage) 5. **Native analytics dashboard** - Booking insights 6. **Broader integrations** - Zoho, Nextcloud, iDEAL 7. **Advanced routing rules** - Multi-factor booking assignment 8. **Multi-channel notifications** - SMS, voice AI, ntfy.sh ### Nice-to-Have (Differentiation) 9. **AI scheduling assistant** - MCP integration 10. **Meeting cost calculator** - Time = money awareness 11. **Travel time/mileage calculations** - Mobile service providers --- ## Methodology This report analyzed **150+ real user feedback items** collected via RequestHunt from: - **Reddit**: r/calendly, r/smallbusiness, r/productivity, r/CRM, r/remotework - **X (Twitter)**: Direct feature requests and complaints - **GitHub**: Cal.com issues repository and related projects Data collection focused on: - Feature requests with explicit pain points - Complaints about existing functionality - Comparison discussions between tools - User workarounds indicating gaps --- ## Appendix: Top Voted Requests | Request | Platform | Votes | |---------|----------|-------| | Block scheduling (only book adjacent to meetings) | X | 267 | | Meeting cost calculator for invitees | X | 257 | | GP booking system usability overhaul | X | 259 | | Production-ready meeting bot API | X | 332 | | Google Meet refund request for late meetings | X | 1,829 | | Big calendar component for MUI | GitHub | 194 | --- *Report generated using RequestHunt API - analyzing real user feedback from Reddit, X, and GitHub.*
#!/usr/bin/env python3
"""Get available topics from RequestHunt API."""
import json
import os
import sys
import urllib.request
import urllib.error
API_BASE = "https://requesthunt.com"
def get_api_key():
key = os.environ.get("REQUESTHUNT_API_KEY")
if not key:
print("Error: REQUESTHUNT_API_KEY environment variable not set", file=sys.stderr)
print("Get your key from: https://requesthunt.com/settings/api", file=sys.stderr)
sys.exit(1)
return key
def get_topics():
api_key = get_api_key()
url = f"{API_BASE}/api/v1/topics"
req = urllib.request.Request(url)
req.add_header("Authorization", f"Bearer {api_key}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req) as response:
data = json.loads(response.read().decode())
return data
except urllib.error.HTTPError as e:
error_body = e.read().decode()
try:
error_data = json.loads(error_body)
print(f"Error {e.code}: {error_data.get('error', {}).get('message', error_body)}", file=sys.stderr)
except:
print(f"Error {e.code}: {error_body}", file=sys.stderr)
sys.exit(1)
def main():
import argparse
parser = argparse.ArgumentParser(description="Get available topics from RequestHunt")
parser.add_argument("--json", action="store_true", help="Output raw JSON")
args = parser.parse_args()
result = get_topics()
if args.json:
print(json.dumps(result, indent=2))
return
categories = result.get("data", [])
print("# Available Topics\n")
for category in categories:
cat_name = category.get("name", "Unknown")
topics = category.get("topics", [])
print(f"## {cat_name}\n")
for topic in topics:
if isinstance(topic, dict):
name = topic.get("name", "")
slug = topic.get("slug", "")
print(f"- **{name}** (`{slug}`)")
else:
print(f"- `{topic}`")
print()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Get API usage stats from RequestHunt."""
import json
import os
import sys
import urllib.request
import urllib.error
API_BASE = "https://requesthunt.com"
def get_api_key():
key = os.environ.get("REQUESTHUNT_API_KEY")
if not key:
print("Error: REQUESTHUNT_API_KEY environment variable not set", file=sys.stderr)
print("Get your key from: https://requesthunt.com/settings/api", file=sys.stderr)
sys.exit(1)
return key
def get_usage():
api_key = get_api_key()
url = f"{API_BASE}/api/v1/usage"
req = urllib.request.Request(url)
req.add_header("Authorization", f"Bearer {api_key}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req) as response:
data = json.loads(response.read().decode())
return data
except urllib.error.HTTPError as e:
error_body = e.read().decode()
try:
error_data = json.loads(error_body)
print(f"Error {e.code}: {error_data.get('error', {}).get('message', error_body)}", file=sys.stderr)
except:
print(f"Error {e.code}: {error_body}", file=sys.stderr)
sys.exit(1)
def main():
import argparse
parser = argparse.ArgumentParser(description="Get API usage stats from RequestHunt")
parser.add_argument("--json", action="store_true", help="Output raw JSON")
args = parser.parse_args()
result = get_usage()
if args.json:
print(json.dumps(result, indent=2))
return
data = result.get("data", {})
print("# RequestHunt API Usage\n")
cached = data.get("cached", {})
realtime = data.get("realtime", {})
print("## Cached Requests")
print(f"- **Used**: {cached.get('used', 0)} / {cached.get('limit', 0)}")
print(f"- **Remaining**: {cached.get('remaining', 0)}")
print(f"- **Resets at**: {cached.get('resetsAt', 'N/A')}")
print()
print("## Realtime Requests")
print(f"- **Used**: {realtime.get('used', 0)} / {realtime.get('limit', 0)}")
print(f"- **Remaining**: {realtime.get('remaining', 0)}")
print(f"- **Resets at**: {realtime.get('resetsAt', 'N/A')}")
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""List feature requests from RequestHunt API."""
import argparse
import json
import os
import sys
import urllib.request
import urllib.error
API_BASE = "https://requesthunt.com"
def get_api_key():
key = os.environ.get("REQUESTHUNT_API_KEY")
if not key:
print("Error: REQUESTHUNT_API_KEY environment variable not set", file=sys.stderr)
print("Get your key from: https://requesthunt.com/settings/api", file=sys.stderr)
sys.exit(1)
return key
def list_requests(limit=20, topic=None, platforms=None, category=None, sort_by="new", cursor=None):
api_key = get_api_key()
params = [f"limit={limit}"]
if topic:
params.append(f"topic={urllib.parse.quote(topic)}")
if platforms:
params.append(f"platforms={platforms}")
if category:
params.append(f"category={urllib.parse.quote(category)}")
if sort_by:
params.append(f"sortBy={sort_by}")
if cursor:
params.append(f"cursor={urllib.parse.quote(cursor)}")
url = f"{API_BASE}/api/v1/requests?{'&'.join(params)}"
req = urllib.request.Request(url)
req.add_header("Authorization", f"Bearer {api_key}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req) as response:
data = json.loads(response.read().decode())
return data
except urllib.error.HTTPError as e:
error_body = e.read().decode()
try:
error_data = json.loads(error_body)
print(f"Error {e.code}: {error_data.get('error', {}).get('message', error_body)}", file=sys.stderr)
except:
print(f"Error {e.code}: {error_body}", file=sys.stderr)
sys.exit(1)
def format_request(req):
"""Format a single request for display."""
lines = []
lines.append(f"## {req.get('title', 'Untitled')}")
lines.append(f"**Platform**: {req.get('sourcePlatform', 'unknown')} | **Votes**: {req.get('votes', 0)} | **Comments**: {req.get('commentCount', 0)}")
if req.get('topic'):
lines.append(f"**Topic**: {req['topic']}")
if req.get('description'):
desc = req['description'][:300] + "..." if len(req.get('description', '')) > 300 else req.get('description', '')
lines.append(f"\n{desc}")
if req.get('sourceUrl'):
lines.append(f"\n[Source]({req['sourceUrl']})")
if req.get('authorName'):
author = req['authorName']
if req.get('authorHandle'):
author += f" (@{req['authorHandle']})"
lines.append(f"*— {author}*")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="List feature requests from RequestHunt")
parser.add_argument("--limit", type=int, default=20, help="Number of results (max 100)")
parser.add_argument("--topic", help="Filter by topic slug")
parser.add_argument("--platforms", help="Filter by platforms (comma-separated: reddit,x,github,requesthunt)")
parser.add_argument("--category", help="Filter by category")
parser.add_argument("--sortBy", choices=["new", "top"], default="new", help="Sort order")
parser.add_argument("--cursor", help="Pagination cursor")
parser.add_argument("--json", action="store_true", help="Output raw JSON")
args = parser.parse_args()
# Import urllib.parse here to avoid issues if not needed
import urllib.parse
result = list_requests(
limit=min(args.limit, 100),
topic=args.topic,
platforms=args.platforms,
category=args.category,
sort_by=args.sortBy,
cursor=args.cursor
)
if args.json:
print(json.dumps(result, indent=2))
return
requests = result.get("data", [])
meta = result.get("meta", {})
print(f"# Feature Requests ({len(requests)} results)\n")
for req in requests:
print(format_request(req))
print("\n---\n")
if meta.get("hasMore"):
print(f"\n*More results available. Use --cursor \"{meta.get('cursor')}\" to continue.*")
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Start a realtime scrape job for a topic on RequestHunt."""
import argparse
import json
import os
import sys
import urllib.request
import urllib.error
API_BASE = "https://requesthunt.com"
def get_api_key():
key = os.environ.get("REQUESTHUNT_API_KEY")
if not key:
print("Error: REQUESTHUNT_API_KEY environment variable not set", file=sys.stderr)
print("Get your key from: https://requesthunt.com/settings/api", file=sys.stderr)
sys.exit(1)
return key
def scrape_topic(topic, platforms=None):
api_key = get_api_key()
url = f"{API_BASE}/api/v1/scrape"
body = {
"topic": topic,
"platforms": platforms or ["reddit", "x"]
}
data = json.dumps(body).encode("utf-8")
req = urllib.request.Request(url, data=data, method="POST")
req.add_header("Authorization", f"Bearer {api_key}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode())
return result
except urllib.error.HTTPError as e:
error_body = e.read().decode()
try:
error_data = json.loads(error_body)
print(f"Error {e.code}: {error_data.get('error', {}).get('message', error_body)}", file=sys.stderr)
except:
print(f"Error {e.code}: {error_body}", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="Start a realtime scrape job for a topic")
parser.add_argument("topic", help="Topic to scrape (e.g., 'ai-tools', 'developer-tools')")
parser.add_argument("--platforms", default="reddit,x", help="Platforms to scrape (comma-separated: reddit,x,github)")
parser.add_argument("--json", action="store_true", help="Output raw JSON")
args = parser.parse_args()
platforms = [p.strip() for p in args.platforms.split(",")]
# Validate platforms
valid_platforms = ["reddit", "x", "github"]
for p in platforms:
if p not in valid_platforms:
print(f"Error: Invalid platform '{p}'. Valid: {', '.join(valid_platforms)}", file=sys.stderr)
sys.exit(1)
result = scrape_topic(args.topic, platforms)
if args.json:
print(json.dumps(result, indent=2))
return
data = result.get("data", {})
print("# Scrape Job Started\n")
print(f"- **Job ID**: {data.get('jobId', 'N/A')}")
print(f"- **Topic**: {data.get('topic', args.topic)}")
print(f"- **Platforms**: {', '.join(data.get('platforms', platforms))}")
print(f"- **Status**: {data.get('status', 'pending')}")
print()
print("*The scrape job is running in the background. New requests will appear in search results shortly.*")
# Show usage info if available
usage = result.get("usage", {})
if usage:
realtime = usage.get("realtime", {})
print(f"\n**Realtime quota**: {realtime.get('used', 0)}/{realtime.get('limit', 0)} (remaining: {realtime.get('remaining', 0)})")
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Search feature requests from RequestHunt API with optional realtime expansion."""
import argparse
import json
import os
import sys
import urllib.request
import urllib.error
API_BASE = "https://requesthunt.com"
def get_api_key():
key = os.environ.get("REQUESTHUNT_API_KEY")
if not key:
print("Error: REQUESTHUNT_API_KEY environment variable not set", file=sys.stderr)
print("Get your key from: https://requesthunt.com/settings/api", file=sys.stderr)
sys.exit(1)
return key
def search_requests(query, limit=20, expand=False, platforms=None):
api_key = get_api_key()
url = f"{API_BASE}/api/v1/requests/search"
body = {
"query": query,
"limit": limit,
"expand": expand
}
if platforms:
body["platforms"] = platforms.split(",")
data = json.dumps(body).encode("utf-8")
req = urllib.request.Request(url, data=data, method="POST")
req.add_header("Authorization", f"Bearer {api_key}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode())
return result
except urllib.error.HTTPError as e:
error_body = e.read().decode()
try:
error_data = json.loads(error_body)
print(f"Error {e.code}: {error_data.get('error', {}).get('message', error_body)}", file=sys.stderr)
except:
print(f"Error {e.code}: {error_body}", file=sys.stderr)
sys.exit(1)
def format_request(req, score=None):
"""Format a single request for display."""
lines = []
title = req.get('title', 'Untitled')
if score is not None:
title += f" (relevance: {score:.2f})"
lines.append(f"## {title}")
lines.append(f"**Platform**: {req.get('sourcePlatform', 'unknown')} | **Votes**: {req.get('votes', 0)} | **Comments**: {req.get('commentCount', 0)}")
if req.get('topic'):
lines.append(f"**Topic**: {req['topic']}")
if req.get('description'):
desc = req['description'][:300] + "..." if len(req.get('description', '')) > 300 else req.get('description', '')
lines.append(f"\n{desc}")
if req.get('sourceUrl'):
lines.append(f"\n[Source]({req['sourceUrl']})")
if req.get('authorName'):
author = req['authorName']
if req.get('authorHandle'):
author += f" (@{req['authorHandle']})"
lines.append(f"*— {author}*")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="Search feature requests from RequestHunt")
parser.add_argument("query", help="Search query")
parser.add_argument("--limit", type=int, default=20, help="Number of results (max 100)")
parser.add_argument("--expand", action="store_true", help="Enable realtime expansion (scrapes fresh data)")
parser.add_argument("--platforms", help="Platforms for realtime scraping (comma-separated: reddit,x,github)")
parser.add_argument("--json", action="store_true", help="Output raw JSON")
args = parser.parse_args()
result = search_requests(
query=args.query,
limit=min(args.limit, 100),
expand=args.expand,
platforms=args.platforms
)
if args.json:
print(json.dumps(result, indent=2))
return
data = result.get("data", {})
results = data.get("results", [])
meta = result.get("meta", {})
print(f"# Search Results for \"{args.query}\" ({len(results)} results)\n")
if args.expand:
print("*Realtime expansion enabled - fresh data scraped*\n")
if meta.get("expandedPlatforms"):
print(f"*Expanded from: {', '.join(meta['expandedPlatforms'])}*\n")
for item in results:
req = item.get("request", item)
score = item.get("score")
print(format_request(req, score))
print("\n---\n")
# Show timing info if available
if meta.get("searchTimeMs"):
print(f"\n*Search completed in {meta['searchTimeMs']}ms*")
if __name__ == "__main__":
main()