nskd-lbr 1.1.3 → 1.1.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/README.md +5 -0
- package/package.json +23 -23
- package/src/nskd-lbr.js +22 -3
- package/src/nskd-lbr.min.js +7 -7
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ const noskid = new NskdLbr({
|
|
|
64
64
|
debug: false, // Enable debug logging
|
|
65
65
|
timeout: 10000, // Request timeout (ms)
|
|
66
66
|
strictCheck: true, // Validate local vs API data
|
|
67
|
+
allowAchievements: true, // Allow achievement-boosted certificates
|
|
67
68
|
useLegacyAPI: false, // Use legacy API format
|
|
68
69
|
|
|
69
70
|
// Logging
|
|
@@ -79,6 +80,7 @@ const noskid = new NskdLbr({
|
|
|
79
80
|
| `debug` | `boolean` | `false` | Enable console debug messages |
|
|
80
81
|
| `timeout` | `number` | `10000` | API request timeout in milliseconds |
|
|
81
82
|
| `strictCheck` | `boolean` | `true` | Compare local certificate data with API response |
|
|
83
|
+
| `allowAchievements` | `boolean` | `true` | Allow certificates that used achievement boosts |
|
|
82
84
|
| `useLegacyAPI` | `boolean` | `false` | Use legacy API format (affects username/nickname field) |
|
|
83
85
|
| `onLog` | `function` | `null` | `(message, level) => {}` - Custom logging function |
|
|
84
86
|
|
|
@@ -293,11 +295,14 @@ The library provides detailed error messages for different failure scenarios:
|
|
|
293
295
|
|
|
294
296
|
### Common Errors
|
|
295
297
|
|
|
298
|
+
### 5. Common Errors table - add new row:
|
|
299
|
+
```markdown
|
|
296
300
|
| Error Type | Cause | Solution |
|
|
297
301
|
|------------|-------|----------|
|
|
298
302
|
| `"No file provided"` | File input is empty | Check file selection |
|
|
299
303
|
| `"File must be a PNG image"` | Wrong file format | Upload a PNG certificate |
|
|
300
304
|
| `"No valid verification key found"` | Certificate missing key | Check certificate validity |
|
|
305
|
+
| `"Certificate uses achievements boost"` | Achievement boost not allowed | Set `allowAchievements: true` or use non-boosted certificate |
|
|
301
306
|
| `"Request timeout"` | Network/server issues | Check connection, increase timeout |
|
|
302
307
|
| `"Data mismatch"` | Local vs API data differs | Disable `strictCheck` or verify certificate |
|
|
303
308
|
|
package/package.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "nskd-lbr",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "A JavaScript library for working with NoSkid certificates.",
|
|
5
|
-
"main": "src/nskd-lbr.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
-
},
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/dpipstudio/noskid.today.git"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
"noskid",
|
|
15
|
-
"certificate"
|
|
16
|
-
],
|
|
17
|
-
"author": "Douxx",
|
|
18
|
-
"license": "SEE LICENSE IN LICENSE",
|
|
19
|
-
"bugs": {
|
|
20
|
-
"url": "https://github.com/dpipstudio/noskid.today/issues"
|
|
21
|
-
},
|
|
22
|
-
"homepage": "https://github.com/dpipstudio/noskid.today#readme"
|
|
23
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "nskd-lbr",
|
|
3
|
+
"version": "1.1.6",
|
|
4
|
+
"description": "A JavaScript library for working with NoSkid certificates.",
|
|
5
|
+
"main": "src/nskd-lbr.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/dpipstudio/noskid.today.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"noskid",
|
|
15
|
+
"certificate"
|
|
16
|
+
],
|
|
17
|
+
"author": "Douxx",
|
|
18
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/dpipstudio/noskid.today/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/dpipstudio/noskid.today#readme"
|
|
23
|
+
}
|
package/src/nskd-lbr.js
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
* NoSkid Certificate Library
|
|
3
3
|
* A JavaScript library for working with NoSkid certificates
|
|
4
4
|
*
|
|
5
|
-
* @version 1.1.
|
|
5
|
+
* @version 1.1.5
|
|
6
6
|
* @author Douxx <douxx@douxx.tech>
|
|
7
7
|
* @param {string} [options.apiUrl='https://check.noskid.today/'] - Logs debug messages to console
|
|
8
8
|
* @param {boolean} [options.debug=false] - Logs debug messages to console
|
|
9
9
|
* @param {boolean} [options.strictCheck=true] - Whether to validate local data against API response
|
|
10
|
+
* @param {boolean} [options.allowAchievements=true] - Whether to allow achievements boosted certificates
|
|
10
11
|
* @param {integer} [options.timeout=10000] - API request timeout in milliseconds
|
|
11
12
|
* @param {boolean} [options.useLegacyAPI=false] - Whether to use the legacy API format
|
|
12
|
-
* @param {function} [options.onLog=null] -
|
|
13
|
+
* @param {function} [options.onLog=null] - Log function for callbacks
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
class NskdLbr {
|
|
@@ -18,6 +19,7 @@ class NskdLbr {
|
|
|
18
19
|
this.debug = options.debug || false;
|
|
19
20
|
this.timeout = options.timeout || 10000;
|
|
20
21
|
this.strictCheck = options.strictCheck !== undefined ? options.strictCheck : true;
|
|
22
|
+
this.allowAchievements = options.allowAchievements !== undefined ? options.allowAchievements : true;
|
|
21
23
|
this.onLog = options.onLog || null;
|
|
22
24
|
this.useLegacyAPI = options.useLegacyAPI || false;
|
|
23
25
|
this.certificateData = null;
|
|
@@ -344,10 +346,26 @@ Certificate Details:
|
|
|
344
346
|
return {
|
|
345
347
|
valid: false,
|
|
346
348
|
message: apiData.message,
|
|
347
|
-
cached: apiData.cached || false
|
|
349
|
+
cached: apiData.cached || false,
|
|
350
|
+
strictCheck: this.strictCheck
|
|
348
351
|
};
|
|
349
352
|
}
|
|
350
353
|
|
|
354
|
+
if (apiData.data.boosted && !this.allowAchievements) {
|
|
355
|
+
this.isValid = false;
|
|
356
|
+
this.nskdLbrLog('Certificate uses achievements boost, which is not allowed by allowAchievements', 'error');
|
|
357
|
+
return {
|
|
358
|
+
valid: false,
|
|
359
|
+
message: 'Certificate uses achievements boost',
|
|
360
|
+
cached: apiData.cached || false,
|
|
361
|
+
strictCheck: this.strictCheck
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (apiData.data.boosted) {
|
|
366
|
+
this.nskdLbrLog('Certificate is achievement-boosted', 'warning');
|
|
367
|
+
}
|
|
368
|
+
|
|
351
369
|
// Compare local data with API data if available and strictCheck is enabled
|
|
352
370
|
if (this.localData && this.strictCheck) {
|
|
353
371
|
const apiUsername = this.useLegacyAPI ? apiData.data.username : (apiData.data.nickname || apiData.data.username);
|
|
@@ -378,6 +396,7 @@ Certificate Details:
|
|
|
378
396
|
valid: true,
|
|
379
397
|
message: 'Certificate verified successfully',
|
|
380
398
|
data: apiData.data,
|
|
399
|
+
query: apiData.query || this.verificationKey,
|
|
381
400
|
cached: apiData.cached || false,
|
|
382
401
|
strictCheck: this.strictCheck
|
|
383
402
|
};
|
package/src/nskd-lbr.min.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
class NskdLbr{constructor(
|
|
1
|
+
class NskdLbr{constructor(e={}){this.apiUrl=e.apiUrl||"https://check.noskid.today/",this.debug=e.debug||!1,this.timeout=e.timeout||1e4,this.strictCheck=void 0===e.strictCheck||e.strictCheck,this.allowAchievements=void 0===e.allowAchievements||e.allowAchievements,this.onLog=e.onLog||null,this.useLegacyAPI=e.useLegacyAPI||!1,this.certificateData=null,this.verificationKey=null,this.localData=null,this.isValid=!1}nskdLbrLog(e,t="info"){if(this.debug){var i=`[${(new Date).toLocaleTimeString()}] NoSkid:`;switch(t){case"error":console.error(i,e);break;case"warning":console.warn(i,e);break;case"success":console.log(`%c${i} `+e,"color: green");break;default:console.log(i,e)}}this.onLog&&"function"==typeof this.onLog&&this.onLog(e,t)}async loadFromFile(e){try{if(this.nskdLbrLog("Starting certificate verification process...","info"),!e)throw new Error("No file provided");if(!e.name.toLowerCase().endsWith(".png"))throw new Error("File must be a PNG image");this.nskdLbrLog("Processing certificate file: "+e.name,"info");var t=await this.readFileAsArrayBuffer(e),i=await this.extractTextFromPng(t);if(!i)throw new Error("Could not extract verification data from file");if(this.verificationKey=this.extractVerificationKey(i),this.verificationKey)return this.nskdLbrLog("Successfully extracted verification key","success"),this.localData=this.extractLocalData(i),this.localData&&(this.nskdLbrLog("Local certificate data extracted:","info"),this.nskdLbrLog("Username: "+this.localData.username,"info"),this.nskdLbrLog("Creation Date: "+this.localData.creationDate,"info")),await this.verifyWithAPI();throw new Error("No valid verification key found in certificate")}catch(e){throw this.nskdLbrLog("Error loading certificate: "+e.message,"error"),e}}async verifyWithKey(e){try{if(!e||"string"!=typeof e)throw new Error("Invalid verification key provided");if(/^[a-f0-9]{64}$/i.test(e))return this.verificationKey=e.toLowerCase(),this.nskdLbrLog(`Verifying certificate with key: ${this.verificationKey.substring(0,16)}...`,"info"),await this.verifyWithAPI();throw new Error("Verification key must be a 64-character hexadecimal string")}catch(e){throw this.nskdLbrLog("Error verifying certificate: "+e.message,"error"),e}}getCertificateData(){return this.certificateData?{...this.certificateData,key:this.verificationKey,localUsername:this.localData?this.localData.username:null,localCreationDate:this.localData?this.localData.creationDate:null}:null}isValidCertificate(){return this.isValid}getFormattedDetails(){var e,t;return this.certificateData?(e=this.certificateData,t=!this.useLegacyAPI&&e.nickname||e.username,`
|
|
2
2
|
Certificate Details:
|
|
3
|
-
- Certificate #: ${
|
|
4
|
-
- Username: ${
|
|
5
|
-
- Percentage: ${
|
|
6
|
-
- Creation Date: ${
|
|
7
|
-
- Country: ${
|
|
8
|
-
`.trim()):"No certificate data available"}reset(){this.certificateData=null,this.verificationKey=null,this.localData=null,this.isValid=!1,this.nskdLbrLog("Certificate data reset","info")}readFileAsArrayBuffer(a){return new Promise((e
|
|
3
|
+
- Certificate #: ${e.certificate_number}
|
|
4
|
+
- Username: ${t}
|
|
5
|
+
- Percentage: ${e.percentage}%
|
|
6
|
+
- Creation Date: ${e.creationDate}
|
|
7
|
+
- Country: ${e.country} (${e.countryCode})
|
|
8
|
+
`.trim()):"No certificate data available"}reset(){this.certificateData=null,this.verificationKey=null,this.localData=null,this.isValid=!1,this.nskdLbrLog("Certificate data reset","info")}readFileAsArrayBuffer(a){return new Promise((t,e)=>{var i=new FileReader;i.onload=e=>t(e.target.result),i.onerror=()=>e(new Error("Error reading file")),i.readAsArrayBuffer(a)})}async extractTextFromPng(i){try{var a=new Uint8Array(i);if(137!==a[0]||80!==a[1]||78!==a[2]||71!==a[3])throw new Error("Not a valid PNG file");let e=8,t=null;for(;e<a.length-12;){var r=a[e]<<24|a[e+1]<<16|a[e+2]<<8|a[e+3];if("tEXt"===String.fromCharCode(a[e+4],a[e+5],a[e+6],a[e+7])){var s=a.slice(e+8,e+8+r),o=new TextDecoder("utf-8").decode(s),c=o.indexOf("\0");if(-1!==c){var n=o.substring(0,c),l=o.substring(c+1);if("noskid-key"===n){t=l;break}}}e+=8+r+4}return t?(this.nskdLbrLog("Certificate data extracted successfully from PNG","success"),t):(this.nskdLbrLog("No 'noskid-key' text chunk found in PNG","error"),null)}catch(e){return this.nskdLbrLog("Error extracting text from PNG: "+e.message,"error"),null}}extractVerificationKey(e){try{var t=/-*BEGIN NOSKID KEY-*\s*([a-f0-9]{64})/i,i=e.match(t);return i?i[1].toLowerCase():null}catch(e){return this.nskdLbrLog("Error extracting verification key: "+e.message,"error"),null}}extractLocalData(e){try{var t,i,a,r,s,o=/-----BEGIN NOSKID KEY-----\s*([a-f0-9]+)\s*([A-Za-z0-9+/=]+)\s*([A-Za-z0-9+/=]+)\s*-----END NOSKID KEY-----/,c=e.match(o);return c?(t=c[2],a=(i=atob(t.replace(/=/g,"")).match(/CERT-\d+-(.+)/))?i[1]:null,r=c[3],{username:a,creationDate:(s=atob(r.replace(/=/g,"")).match(/CREATED-(.+)/))?s[1]:null}):null}catch(e){return this.nskdLbrLog("Error extracting local data: "+e.message,"error"),null}}async verifyWithAPI(){try{this.nskdLbrLog("Verifying certificate with server...","info");let e=new AbortController;var t=setTimeout(()=>e.abort(),this.timeout),i=await fetch(this.apiUrl+"?key="+encodeURIComponent(this.verificationKey),{signal:e.signal,headers:{"User-Agent":"NskdLbr/1.1.0"}});if(clearTimeout(t),!i.ok)throw new Error(`HTTP ${i.status}: `+i.statusText);var a=await i.json();if(!a.success)return this.isValid=!1,this.nskdLbrLog("Certificate verification failed: "+a.message,"error"),{valid:!1,message:a.message,cached:a.cached||!1,strictCheck:this.strictCheck};if(a.data.boosted&&!this.allowAchievements)return this.isValid=!1,this.nskdLbrLog("Certificate uses achievements boost, which is not allowed by allowAchievements","error"),{valid:!1,message:"Certificate uses achievements boost",cached:a.cached||!1,strictCheck:this.strictCheck};if(a.data.boosted&&this.nskdLbrLog("Certificate is achievement-boosted","warning"),this.localData&&this.strictCheck){var r=!this.useLegacyAPI&&a.data.nickname||a.data.username,s=this.compareData(this.localData,{...a.data,username:r});if(!s.valid)return this.isValid=!1,this.nskdLbrLog("Certificate data mismatch!","error"),this.nskdLbrLog("Mismatch reason: "+s.reason,"error"),this.nskdLbrLog("Note: Strict checking is enabled. Set strictCheck to false to skip local data validation.","warning"),{valid:!1,message:"Data mismatch: "+s.reason,cached:a.cached||!1,strictCheck:!0};this.nskdLbrLog("Local data validation passed","success")}else this.localData&&!this.strictCheck&&this.nskdLbrLog("Strict checking disabled - skipping local data validation","warning");return this.isValid=!0,this.certificateData=a.data,this.nskdLbrLog("Certificate is VALID!","success"),{valid:!0,message:"Certificate verified successfully",data:a.data,query:a.query||this.verificationKey,cached:a.cached||!1,strictCheck:this.strictCheck}}catch(e){if("AbortError"===e.name)throw new Error("Request timeout - server took too long to respond");throw new Error("API verification failed: "+e.message)}}compareData(e,t){return e&&t?e.username!==t.username?{valid:!1,reason:`Username mismatch: Local=${e.username}, API=`+t.username}:(e=e.creationDate.substring(0,16))!==(t=t.creationDate.substring(0,16))?{valid:!1,reason:`Creation date mismatch: Local=${e}, API=`+t}:{valid:!0}:{valid:!1,reason:"Missing data for comparison"}}}"undefined"!=typeof module&&module.exports?module.exports=NskdLbr:window.NskdLbr=NskdLbr;
|