omnibiofex 2.8.5 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,165 +1,120 @@
1
1
  const chalk = require('chalk');
2
2
  const inquirer = require('inquirer');
3
- const { getAuthToken, isAuthenticated, getCurrentUserUid, getCurrentUserEmail } = require('../auth');
4
- const { db } = require('../firebase');
3
+ const { getAuthToken, isAuthenticated } = require('../auth');
5
4
  const { PremiumSpinner, sleep } = require('../utils/display');
6
- const { collection, query, where, orderBy, limit, getDocs, doc, updateDoc } = require('firebase/firestore');
7
5
 
8
- async function publish(missionId) {
9
- if (!isAuthenticated()) {
10
- console.error(chalk.red('✗ Not authenticated. Please run: obx login'));
11
- return;
12
- }
6
+ const GET_USER_DATA_URL = 'https://getuserdata-yyedhmslhq-uc.a.run.app';
7
+ const PUBLISH_MISSION_URL = 'https://publishmission-yyedhmslhq-uc.a.run.app';
13
8
 
14
- const uid = getCurrentUserUid();
15
- const email = getCurrentUserEmail();
16
-
17
- if (!uid) {
18
- console.error(chalk.red('✗ Could not extract user ID from token.'));
19
- console.error(chalk.gray('Please run: obx login'));
20
- return;
21
- }
9
+ async function fetchUserData(token) {
10
+ const response = await fetch(GET_USER_DATA_URL, {
11
+ headers: { 'Authorization': `Bearer ${token}` }
12
+ });
13
+ if (!response.ok) throw new Error(`Backend error: ${response.status}`);
14
+ return await response.json();
15
+ }
22
16
 
17
+ async function publish(missionId) {
18
+ if (!isAuthenticated()) { console.error(chalk.red('✗ Not authenticated')); process.exit(1); return; }
19
+
23
20
  console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
24
21
  console.log(chalk.white.bold('📤 PUBLISH RESEARCH'));
25
22
  console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
26
-
27
- console.log(chalk.gray(` 👤 User: ${chalk.white(email || 'Unknown')}`));
28
-
29
- if (!missionId) {
30
- console.log(chalk.gray('\nFetching your completed missions...\n'));
31
-
32
- const spinner = new PremiumSpinner('Loading missions from database');
33
- spinner.start();
34
23
 
35
- try {
36
- const missionsQuery = query(
37
- collection(db, 'missions'),
38
- where('uid', '==', uid),
39
- where('status', '==', 'completed'),
40
- where('isPublished', '==', false),
41
- orderBy('createdAt', 'desc'),
42
- limit(10)
43
- );
44
-
45
- const querySnapshot = await getDocs(missionsQuery);
46
- const missions = [];
47
-
48
- querySnapshot.forEach((docSnap) => {
49
- missions.push({
50
- id: docSnap.id,
51
- ...docSnap.data()
52
- });
53
- });
54
-
55
- spinner.succeed(`Found ${missions.length} unpublished missions`);
24
+ const spinner = new PremiumSpinner('Fetching missions');
25
+ spinner.start();
56
26
 
57
- if (missions.length === 0) {
58
- console.log(chalk.yellow('\n⚠️ No unpublished missions found.'));
59
- console.log(chalk.gray('Create a mission first: obx mission create\n'));
27
+ try {
28
+ const token = await getAuthToken();
29
+ const userData = await fetchUserData(token);
30
+ spinner.succeed('Missions loaded');
31
+
32
+ console.log(chalk.gray(` 👤 User: ${chalk.white(userData.user.name || userData.user.email)}`));
33
+
34
+ // Filter unpublished completed missions
35
+ const unpublished = userData.missions.filter(m =>
36
+ m.status === 'completed' && !m.isPublished
37
+ );
38
+
39
+ if (!missionId) {
40
+ if (unpublished.length === 0) {
41
+ console.log(chalk.yellow('\n⚠️ No unpublished missions.\n'));
42
+ console.log(chalk.gray(' Create one with: obx mission create\n'));
43
+ process.exit(0);
60
44
  return;
61
45
  }
62
-
63
- console.log(chalk.white('\n📋 Your Unpublished Missions:'));
46
+
47
+ console.log(chalk.white('\n📋 Unpublished Missions:'));
64
48
  console.log(chalk.gray('─'.repeat(60)));
65
49
 
66
- missions.forEach((m, i) => {
67
- const date = m.createdAt?.toDate?.().toLocaleDateString() || 'N/A';
50
+ unpublished.forEach((m, i) => {
68
51
  console.log(chalk.white(`\n${i + 1}. ${chalk.hex('#F24E1E')(m.id)}`));
69
- console.log(chalk.white(` Topic: ${(m.message || 'No topic').substring(0, 60)}${(m.message?.length || 0) > 60 ? '...' : ''}`));
70
- console.log(chalk.green(` Type: ${m.taskType || 'Research'}`));
71
- console.log(chalk.gray(` Date: ${date}`));
72
- console.log(chalk.gray(` RCC Cost: ${m.rccCost || 0}`));
52
+ console.log(chalk.white(` Topic: ${(m.message || '').substring(0, 60)}`));
73
53
  });
74
-
75
- const { selectedIndex } = await inquirer.prompt([
76
- {
77
- type: 'list',
78
- name: 'selectedIndex',
79
- message: '\nSelect mission to publish:',
80
- choices: missions.map((m, i) => ({
81
- name: `${i + 1}. ${m.id} - ${(m.message || 'No topic').substring(0, 50)}`,
82
- value: i
83
- }))
84
- }
85
- ]);
86
-
87
- missionId = missions[selectedIndex].id;
88
54
 
89
- } catch (error) {
90
- spinner.fail('Failed to load missions');
91
- console.error(chalk.red(error.message));
92
- return;
55
+ const { selectedIndex } = await inquirer.prompt([{
56
+ type: 'list', name: 'selectedIndex', message: '\nSelect mission:',
57
+ choices: unpublished.map((m, i) => ({
58
+ name: `${i + 1}. ${m.id} - ${(m.message || '').substring(0, 50)}`,
59
+ value: i
60
+ }))
61
+ }]);
62
+ missionId = unpublished[selectedIndex].id;
93
63
  }
94
- }
95
-
96
- const spinner = new PremiumSpinner('Preparing to publish research');
97
- spinner.start();
98
- await sleep(500);
99
-
100
- try {
101
- spinner.update('Fetching mission data');
102
- const missionRef = doc(db, 'missions', missionId);
103
-
104
- const missionSnap = await getDocs(query(collection(db, 'missions'), where('__name__', '==', missionId)));
105
-
106
- if (missionSnap.empty) {
107
- spinner.fail('Mission not found');
108
- console.error(chalk.red(`✗ Mission ${missionId} not found`));
109
- return;
110
- }
111
-
112
- const missionData = missionSnap.docs[0].data();
113
64
 
114
- spinner.update('Generating SEO-optimized page');
65
+ const publishSpinner = new PremiumSpinner('Publishing research');
66
+ publishSpinner.start();
115
67
  await sleep(500);
116
68
 
117
- const slug = (missionData.message || missionId)
118
- .toLowerCase()
119
- .replace(/[^a-z0-9]+/g, '-')
120
- .replace(/^-|-$/g, '')
121
- .substring(0, 60) + '-' + Date.now().toString(36);
122
-
123
- spinner.update('Adding metadata and tags');
69
+ publishSpinner.update('Generating SEO page');
70
+ await sleep(500);
71
+ publishSpinner.update('Adding metadata');
124
72
  await sleep(400);
125
-
126
- spinner.update('Submitting to Google for indexing');
73
+ publishSpinner.update('Submitting to Google');
127
74
  await sleep(600);
128
-
129
- spinner.update('Enabling revenue tracking');
75
+ publishSpinner.update('Enabling revenue tracking');
130
76
  await sleep(400);
131
77
 
132
- await updateDoc(missionRef, {
133
- isPublished: true,
134
- publishedAt: new Date(),
135
- slug: slug,
136
- views: 0,
137
- downloads: 0,
138
- citations: 0,
139
- earnings: 0,
140
- authorName: email || 'Anonymous Researcher',
141
- authorEmail: email || 'unknown@example.com'
78
+ // Call backend to publish
79
+ const response = await fetch(PUBLISH_MISSION_URL, {
80
+ method: 'POST',
81
+ headers: {
82
+ 'Content-Type': 'application/json',
83
+ 'Authorization': `Bearer ${token}`
84
+ },
85
+ body: JSON.stringify({ missionId })
142
86
  });
143
87
 
144
- spinner.succeed('Research published successfully!');
145
-
146
- const url = `https://x.omnibiofex.cloud/research/${slug}`;
147
-
88
+ if (!response.ok) {
89
+ const err = await response.json().catch(() => ({ error: `HTTP ${response.status}` }));
90
+ throw new Error(err.error || `Backend returned ${response.status}`);
91
+ }
92
+
93
+ const data = await response.json();
94
+ publishSpinner.succeed('Research published successfully!');
95
+
148
96
  console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
149
97
  console.log(chalk.white.bold('✅ PUBLICATION DETAILS'));
150
98
  console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
151
-
152
99
  console.log(chalk.white(`📄 Mission ID: ${chalk.hex('#F24E1E')(missionId)}`));
153
- console.log(chalk.white(`🔗 Public URL: ${chalk.blue.underline(url)}`));
100
+ console.log(chalk.white(`🔗 Public URL: ${chalk.blue.underline(data.url)}`));
154
101
  console.log(chalk.white(`💰 Revenue Share: ${chalk.green('80%')} of all ad revenue`));
155
102
  console.log(chalk.white(`🔍 Google Indexing: ${chalk.green('Requested')} (24 hours)`));
156
- console.log(chalk.white(`📊 Analytics: ${chalk.green('Enabled')}`));
157
-
158
- console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
159
-
103
+
104
+ console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
105
+ console.log(chalk.white.bold('💰 START EARNING'));
106
+ console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
107
+ console.log(chalk.white('\n ✓ Google indexes within 24 hours'));
108
+ console.log(chalk.white(' ✓ Readers discover through search'));
109
+ console.log(chalk.white(' ✓ You earn 80% of ad revenue'));
110
+ console.log(chalk.white(' ✓ Monthly payouts to your account\n'));
111
+ console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
112
+ process.exit(0);
113
+
160
114
  } catch (error) {
161
- spinner.fail('Failed to publish research');
115
+ spinner.fail('Failed to publish');
162
116
  console.error(chalk.red(error.message));
117
+ process.exit(1);
163
118
  }
164
119
  }
165
120