stfca 1.0.4 → 1.0.6
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.
- package/CHANGELOG.md +33 -0
- package/checkUpdate.js +143 -44
- package/index.js +10 -0
- package/package.json +12 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,39 @@
|
|
|
3
3
|
|
|
4
4
|
All notable changes to ST-FCA will be documented in this file.
|
|
5
5
|
|
|
6
|
+
## [1.0.5] - 2025-01-13
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- 🔄 Comprehensive update system that properly syncs all files
|
|
10
|
+
- 📂 Automatic file tree comparison between local and GitHub
|
|
11
|
+
- ➕ Smart file addition for new files in updates
|
|
12
|
+
- ♻️ Automatic modification detection and update
|
|
13
|
+
- 🗑️ Automatic deletion of removed files from old versions
|
|
14
|
+
- 🎯 No backup folder creation - cleaner updates
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Improved update mechanism to handle version jumps (e.g., 1.0.3 → 1.0.6)
|
|
18
|
+
- Enhanced file synchronization to ensure no missing files
|
|
19
|
+
- Better error handling during updates
|
|
20
|
+
- Auto-restart after successful update
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- Missing files when updating across multiple versions
|
|
24
|
+
- Outdated files not being properly replaced
|
|
25
|
+
- Orphaned files from old versions not being cleaned up
|
|
26
|
+
|
|
27
|
+
## [1.0.4] - 2025-01-13
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- 🔄 Automatic update checking on package initialization
|
|
31
|
+
- ⚡ Non-blocking update process - doesn't interrupt user's bot startup
|
|
32
|
+
- 🎯 Update check runs once per session to avoid redundant checks
|
|
33
|
+
- 💡 Silent error handling for update checks
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
- Update checker now integrated directly into login flow
|
|
37
|
+
- Improved user experience with seamless auto-updates
|
|
38
|
+
|
|
6
39
|
## [1.0.3] - 2025-01-13
|
|
7
40
|
|
|
8
41
|
### Added
|
package/checkUpdate.js
CHANGED
|
@@ -16,7 +16,7 @@ async function checkForFCAUpdate() {
|
|
|
16
16
|
const latestVersion = packageData.version;
|
|
17
17
|
const currentPackagePath = path.join(__dirname, 'package.json');
|
|
18
18
|
|
|
19
|
-
// Check if package.json exists
|
|
19
|
+
// Check if package.json exists
|
|
20
20
|
let currentVersion = '1.0.3';
|
|
21
21
|
if (fs.existsSync(currentPackagePath)) {
|
|
22
22
|
const currentPackage = JSON.parse(fs.readFileSync(currentPackagePath, 'utf-8'));
|
|
@@ -27,7 +27,7 @@ async function checkForFCAUpdate() {
|
|
|
27
27
|
console.log('\x1b[32m%s\x1b[0m', `✨ New ST-FCA version available: ${latestVersion} (current: ${currentVersion})`);
|
|
28
28
|
console.log('\x1b[33m%s\x1b[0m', '📦 Updating ST-FCA...');
|
|
29
29
|
|
|
30
|
-
//
|
|
30
|
+
// Show changelog
|
|
31
31
|
try {
|
|
32
32
|
const { data: changesData } = await axios.get(
|
|
33
33
|
'https://raw.githubusercontent.com/sheikhtamimlover/ST-FCA/main/CHANGELOG.md'
|
|
@@ -41,10 +41,17 @@ async function checkForFCAUpdate() {
|
|
|
41
41
|
// Silently ignore changelog fetch errors
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
//
|
|
45
|
-
await
|
|
44
|
+
// Perform comprehensive update
|
|
45
|
+
await performComprehensiveUpdate();
|
|
46
46
|
|
|
47
47
|
console.log('\x1b[32m%s\x1b[0m', '✅ ST-FCA updated successfully!');
|
|
48
|
+
console.log('\x1b[33m%s\x1b[0m', '🔄 Restarting to apply changes...');
|
|
49
|
+
|
|
50
|
+
// Restart the process
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}, 1000);
|
|
54
|
+
|
|
48
55
|
return true;
|
|
49
56
|
} else {
|
|
50
57
|
console.log('\x1b[32m%s\x1b[0m', `✅ ST-FCA is up to date (v${currentVersion})`);
|
|
@@ -56,54 +63,146 @@ async function checkForFCAUpdate() {
|
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
|
|
59
|
-
async function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
async function performComprehensiveUpdate() {
|
|
67
|
+
try {
|
|
68
|
+
// Step 1: Get the complete file tree from GitHub
|
|
69
|
+
console.log('\x1b[36m%s\x1b[0m', '📂 Fetching complete file structure...');
|
|
70
|
+
const fileTree = await getGitHubFileTree();
|
|
71
|
+
|
|
72
|
+
// Step 2: Get local files
|
|
73
|
+
const localFiles = getLocalFiles();
|
|
74
|
+
|
|
75
|
+
// Step 3: Download/Update all files from GitHub
|
|
76
|
+
console.log('\x1b[36m%s\x1b[0m', '⬇️ Downloading files...');
|
|
77
|
+
for (const file of fileTree) {
|
|
78
|
+
await downloadFile(file);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Step 4: Delete files that don't exist in the latest version
|
|
82
|
+
console.log('\x1b[36m%s\x1b[0m', '🗑️ Cleaning up old files...');
|
|
83
|
+
const githubFilePaths = fileTree.map(f => f.path);
|
|
84
|
+
for (const localFile of localFiles) {
|
|
85
|
+
if (!githubFilePaths.includes(localFile) && !shouldKeepFile(localFile)) {
|
|
86
|
+
deleteLocalFile(localFile);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log('\x1b[32m%s\x1b[0m', '✅ All files synchronized!');
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.log('\x1b[31m%s\x1b[0m', '❌ Update failed:', error.message);
|
|
93
|
+
throw error;
|
|
71
94
|
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function getGitHubFileTree() {
|
|
98
|
+
try {
|
|
99
|
+
const { data } = await axios.get(
|
|
100
|
+
'https://api.github.com/repos/sheikhtamimlover/ST-FCA/git/trees/main?recursive=1'
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Filter only files (not directories)
|
|
104
|
+
return data.tree
|
|
105
|
+
.filter(item => item.type === 'blob')
|
|
106
|
+
.filter(item => !item.path.startsWith('.git'))
|
|
107
|
+
.filter(item => !shouldIgnoreFile(item.path));
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.log('\x1b[31m%s\x1b[0m', '❌ Failed to fetch file tree:', error.message);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function getLocalFiles() {
|
|
115
|
+
const files = [];
|
|
72
116
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
117
|
+
function walkDir(dir, baseDir = '') {
|
|
118
|
+
const items = fs.readdirSync(dir);
|
|
119
|
+
|
|
120
|
+
for (const item of items) {
|
|
121
|
+
const fullPath = path.join(dir, item);
|
|
122
|
+
const relativePath = baseDir ? path.join(baseDir, item) : item;
|
|
76
123
|
|
|
77
|
-
|
|
78
|
-
if (fs.existsSync(targetPath)) {
|
|
79
|
-
const backupPath = path.join(backupDir, file);
|
|
80
|
-
const backupFileDir = path.dirname(backupPath);
|
|
81
|
-
if (!fs.existsSync(backupFileDir)) {
|
|
82
|
-
fs.mkdirSync(backupFileDir, { recursive: true });
|
|
83
|
-
}
|
|
84
|
-
fs.copyFileSync(targetPath, backupPath);
|
|
85
|
-
}
|
|
124
|
+
if (shouldIgnoreFile(relativePath)) continue;
|
|
86
125
|
|
|
87
|
-
|
|
88
|
-
const { data } = await axios.get(
|
|
89
|
-
`https://raw.githubusercontent.com/sheikhtamimlover/ST-FCA/main/${file}`,
|
|
90
|
-
{ responseType: 'arraybuffer' }
|
|
91
|
-
);
|
|
126
|
+
const stat = fs.statSync(fullPath);
|
|
92
127
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
128
|
+
if (stat.isDirectory()) {
|
|
129
|
+
walkDir(fullPath, relativePath);
|
|
130
|
+
} else {
|
|
131
|
+
files.push(relativePath.replace(/\\/g, '/'));
|
|
97
132
|
}
|
|
98
|
-
|
|
99
|
-
fs.writeFileSync(targetPath, Buffer.from(data));
|
|
100
|
-
console.log('\x1b[32m%s\x1b[0m', ` ✓ Updated: ${file}`);
|
|
101
|
-
} catch (error) {
|
|
102
|
-
console.log('\x1b[31m%s\x1b[0m', ` ✗ Failed to update: ${file}`, error.message);
|
|
103
133
|
}
|
|
104
134
|
}
|
|
105
135
|
|
|
106
|
-
|
|
136
|
+
walkDir(__dirname);
|
|
137
|
+
return files;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function shouldIgnoreFile(filePath) {
|
|
141
|
+
const ignorePatterns = [
|
|
142
|
+
'node_modules',
|
|
143
|
+
'.git',
|
|
144
|
+
'.env',
|
|
145
|
+
'appstate.json',
|
|
146
|
+
'fbstate.json',
|
|
147
|
+
'package-lock.json',
|
|
148
|
+
'.replit',
|
|
149
|
+
'replit.nix',
|
|
150
|
+
'.config',
|
|
151
|
+
'generated-icon.png'
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
return ignorePatterns.some(pattern => filePath.includes(pattern));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function shouldKeepFile(filePath) {
|
|
158
|
+
const keepPatterns = [
|
|
159
|
+
'node_modules',
|
|
160
|
+
'.env',
|
|
161
|
+
'appstate.json',
|
|
162
|
+
'fbstate.json',
|
|
163
|
+
'package-lock.json',
|
|
164
|
+
'.replit',
|
|
165
|
+
'replit.nix',
|
|
166
|
+
'.config'
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
return keepPatterns.some(pattern => filePath.includes(pattern));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function downloadFile(fileInfo) {
|
|
173
|
+
try {
|
|
174
|
+
const targetPath = path.join(__dirname, fileInfo.path);
|
|
175
|
+
|
|
176
|
+
// Download file content
|
|
177
|
+
const { data } = await axios.get(
|
|
178
|
+
`https://raw.githubusercontent.com/sheikhtamimlover/ST-FCA/main/${fileInfo.path}`,
|
|
179
|
+
{ responseType: 'arraybuffer' }
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// Ensure directory exists
|
|
183
|
+
const fileDir = path.dirname(targetPath);
|
|
184
|
+
if (!fs.existsSync(fileDir)) {
|
|
185
|
+
fs.mkdirSync(fileDir, { recursive: true });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Write file
|
|
189
|
+
fs.writeFileSync(targetPath, Buffer.from(data));
|
|
190
|
+
console.log('\x1b[32m%s\x1b[0m', ` ✓ ${fileInfo.path}`);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.log('\x1b[31m%s\x1b[0m', ` ✗ Failed: ${fileInfo.path}`, error.message);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function deleteLocalFile(filePath) {
|
|
197
|
+
try {
|
|
198
|
+
const fullPath = path.join(__dirname, filePath);
|
|
199
|
+
if (fs.existsSync(fullPath)) {
|
|
200
|
+
fs.unlinkSync(fullPath);
|
|
201
|
+
console.log('\x1b[33m%s\x1b[0m', ` 🗑️ Deleted: ${filePath}`);
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.log('\x1b[31m%s\x1b[0m', ` ✗ Failed to delete: ${filePath}`, error.message);
|
|
205
|
+
}
|
|
107
206
|
}
|
|
108
207
|
|
|
109
|
-
module.exports = { checkForFCAUpdate,
|
|
208
|
+
module.exports = { checkForFCAUpdate, performComprehensiveUpdate };
|
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var utils = require("./utils");
|
|
4
4
|
var cheerio = require("cheerio");
|
|
5
5
|
var log = require("npmlog");
|
|
6
|
+
var { checkForFCAUpdate } = require("./checkUpdate");
|
|
6
7
|
/*var { getThemeColors } = require("../../func/utils/log.js");
|
|
7
8
|
var logger = require("../../func/utils/log.js");
|
|
8
9
|
var { cra, cv, cb, co } = getThemeColors();*/
|
|
@@ -10,6 +11,7 @@ log.maxRecordSize = 100;
|
|
|
10
11
|
var checkVerified = null;
|
|
11
12
|
const Boolean_Option = ['online', 'selfListen', 'listenEvents', 'updatePresence', 'forceLogin', 'autoMarkDelivery', 'autoMarkRead', 'listenTyping', 'autoReconnect', 'emitReady'];
|
|
12
13
|
global.ditconmemay = false;
|
|
14
|
+
global.stfcaUpdateChecked = false;
|
|
13
15
|
|
|
14
16
|
function setOptions(globalOptions, options) {
|
|
15
17
|
Object.keys(options).map(function (key) {
|
|
@@ -407,6 +409,14 @@ function loginHelper(appState, email, password, globalOptions, callback, prCallb
|
|
|
407
409
|
|
|
408
410
|
|
|
409
411
|
function login(loginData, options, callback) {
|
|
412
|
+
// Check for updates (non-blocking, only once per session)
|
|
413
|
+
if (!global.stfcaUpdateChecked) {
|
|
414
|
+
global.stfcaUpdateChecked = true;
|
|
415
|
+
checkForFCAUpdate().catch(err => {
|
|
416
|
+
// Silently ignore update check errors to not block login
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
410
420
|
if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
|
|
411
421
|
callback = options;
|
|
412
422
|
options = {};
|
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
2
1
|
{
|
|
3
2
|
"name": "stfca",
|
|
4
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
5
4
|
"description": "Unofficial Facebook Chat API for Node.js - Enhanced by ST | Sheikh Tamim",
|
|
6
5
|
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/",
|
|
8
|
+
"index.js",
|
|
9
|
+
"utils.js",
|
|
10
|
+
"checkUpdate.js",
|
|
11
|
+
"README.md",
|
|
12
|
+
"CHANGELOG.md"
|
|
13
|
+
],
|
|
7
14
|
"scripts": {
|
|
8
15
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
16
|
"start": "node index.js"
|
|
@@ -33,11 +40,13 @@
|
|
|
33
40
|
"axios": "^1.4.0",
|
|
34
41
|
"bluebird": "^3.7.2",
|
|
35
42
|
"cheerio": "^1.0.0-rc.12",
|
|
43
|
+
"duplexify": "^4.1.3",
|
|
36
44
|
"https-proxy-agent": "^5.0.1",
|
|
37
45
|
"mqtt": "^4.3.7",
|
|
38
46
|
"npmlog": "^7.0.1",
|
|
39
47
|
"request": "^2.88.2",
|
|
40
|
-
"websocket-stream": "^5.5.2"
|
|
48
|
+
"websocket-stream": "^5.5.2",
|
|
49
|
+
"ws": "^8.18.3"
|
|
41
50
|
},
|
|
42
51
|
"engines": {
|
|
43
52
|
"node": ">=14.0.0"
|