| name | evernote-cost-tuning |
| description | Optimize Evernote integration costs and resource usage.
Use when managing API quotas, reducing storage usage,
or optimizing upload limits.
Trigger with phrases like "evernote cost", "evernote quota",
"evernote limits", "evernote upload".
|
| allowed-tools | Read, Write, Edit, Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Evernote Cost Tuning
Overview
Optimize resource usage and manage costs in Evernote integrations, focusing on upload quotas, storage efficiency, and account limits.
Prerequisites
- Understanding of Evernote account tiers
- Access to user quota information
- Monitoring infrastructure
Account Limits by Tier
| Feature | Basic | Personal | Professional |
|---|
| Monthly upload | 60 MB | 10 GB | 20 GB |
| Max note size | 25 MB | 200 MB | 200 MB |
| Notebooks | 250 | 1,000 | 1,000 |
| Tags | 100,000 | 100,000 | 100,000 |
| Saved searches | 100 | 100 | 100 |
Instructions
Step 1: Quota Monitoring
const Evernote = require('evernote');
class QuotaService {
constructor(userStore) {
this.userStore = userStore;
}
async getQuotaStatus() {
const user = await this.userStore.getUser();
const accounting = user.accounting;
const uploadLimit = accounting.uploadLimit;
const uploaded = accounting.uploaded;
const remaining = uploadLimit - uploaded;
const usagePercent = (uploaded / uploadLimit) * 100;
return {
tier: this.getTierName(user.privilege),
uploadLimit: this.formatBytes(uploadLimit),
uploaded: this.formatBytes(uploaded),
remaining: this.formatBytes(remaining),
usagePercent: usagePercent.toFixed(1) + '%',
resetsAt: (accounting.),
: .(accounting.),
: {
uploadLimit,
uploaded,
remaining
}
};
}
() {
status = .();
status.. >= fileSizeBytes;
}
() {
status = .();
.(status.. / avgFileSizeBytes);
}
() {
status = .();
(status.) >= thresholdPercent;
}
() {
tiers = {
: ,
: ,
: ,
:
};
tiers[privilege] || ;
}
() {
(!bytes) ;
units = [, , , ];
i = ;
(bytes >= && i < units. - ) {
bytes /= ;
i++;
}
;
}
() {
ms = timestamp - .();
.(, .(ms / ( * * * )));
}
}
. = ;
Step 2: Resource Optimization
const sharp = require('sharp');
const path = require('path');
class ResourceOptimizer {
constructor(options = {}) {
this.maxImageWidth = options.maxImageWidth || 1920;
this.maxImageHeight = options.maxImageHeight || 1080;
this.imageQuality = options.imageQuality || 80;
this.maxFileSizeMB = options.maxFileSizeMB || 10;
}
async optimizeImage(buffer, originalName) {
const originalSize = buffer.length;
const ext = path.extname(originalName).toLowerCase();
const format = ext === '.png' ? 'png' : 'jpeg';
let optimized = sharp(buffer)
.resize(this.maxImageWidth, this., {
: ,
:
});
(format === ) {
optimized = optimized.({ : . });
} {
optimized = optimized.({ : });
}
result = optimized.();
savings = originalSize - result.;
savingsPercent = (savings / originalSize) * ;
.();
{
: result,
originalSize,
: result.,
savings,
savingsPercent
};
}
() {
(mimeType.() && fileSizeBytes > * ) {
;
}
(fileSizeBytes > . * * ) {
;
}
;
}
() {
buffer;
}
() {
units = [, , ];
i = ;
(bytes >= && i < units. - ) {
bytes /= ;
i++;
}
;
}
}
. = ;
Step 3: Efficient Note Creation
class EfficientNoteService {
constructor(noteStore, quotaService, optimizer) {
this.noteStore = noteStore;
this.quota = quotaService;
this.optimizer = optimizer;
}
async createNoteWithQuotaCheck(note, resources = []) {
let totalSize = Buffer.byteLength(note.content, 'utf8');
for (const resource of resources) {
totalSize += resource.data.size;
}
const canUpload = await this.quota.canUpload(totalSize);
if (!canUpload) {
const status = await this.quota.getQuotaStatus();
throw new Error(
`Insufficient quota. Need ${this.formatBytes(totalSize)}, ` +
`have ${status.remaining}. Resets in ${status.daysUntilReset} days.`
);
}
optimizedResources = [];
( resource resources) {
(..(resource.., resource.)) {
optimized = ..(
resource..,
resource.?. ||
);
resource.. = optimized.;
resource.. = optimized..;
resource.. = .(optimized.);
}
optimizedResources.(resource);
}
note. = optimizedResources;
..(note);
}
() {
note = ..();
note. = title;
note. = .(content);
created = ..(note);
( resourcePath resourcePaths) {
.(created., resourcePath);
}
created;
}
() {
notes.( {
sizeA = .(a., );
sizeB = .(b., );
sizeA - sizeB;
});
results = [];
status = ..();
usedQuota = ;
( note notes) {
noteSize = .(note., );
(usedQuota + noteSize > status..) {
.();
;
}
{
result = ..(note);
results.({ : , : result });
usedQuota += noteSize;
} (error) {
results.({ : , : error. });
}
}
results;
}
() {
crypto = ();
crypto.().(buffer).();
}
() {
;
}
() {
units = [, , ];
i = ;
(bytes >= && i < units. - ) {
bytes /= ;
i++;
}
;
}
}
. = ;
Step 4: Storage Cleanup
class StorageCleanup {
constructor(noteStore) {
this.noteStore = noteStore;
}
async findLargeNotes(thresholdMB = 5) {
const filter = new Evernote.NoteStore.NoteFilter({
ascending: false,
order: Evernote.Types.NoteSortOrder.SIZE
});
const spec = new Evernote.NoteStore.NotesMetadataResultSpec({
includeTitle: true,
includeContentLength: true,
includeCreated: true,
includeNotebookGuid: true
});
const result = await this.noteStore.findNotesMetadata(filter, 0, 100, spec);
const thresholdBytes = thresholdMB * 1024 * 1024;
return result.notes.filter(
note. > thresholdBytes
);
}
() {
spec = ..({
: ,
: ,
:
});
filter = ..({});
all = ..(filter, , , spec);
byTitle = {};
( note all.) {
key = note..().();
(!byTitle[key]) {
byTitle[key] = [];
}
byTitle[key].(note);
}
duplicates = [];
( [title, notes] .(byTitle)) {
(notes. > ) {
duplicates.({
title,
: notes.,
: notes.( ({
: n.,
: (n.),
: .(n.)
}))
});
}
}
duplicates;
}
() {
cutoff = .() - (daysOld * * * * );
filter = ..({
: ,
: ...
});
spec = ..({
: ,
: ,
:
});
result = ..(filter, , , spec);
result..( note. < cutoff);
}
() {
notebooks = ..();
storage = [];
( notebook notebooks) {
filter = ..({
: notebook.
});
spec = ..({
:
});
result = ..(filter, , , spec);
avgSize = result.[]?. || ;
estimatedTotal = avgSize * result.;
storage.({
: notebook.,
: notebook.,
: result.,
: .(estimatedTotal)
});
}
storage.( b. - a.);
}
() {
units = [, , , ];
i = ;
(bytes >= && i < units. - ) {
bytes /= ;
i++;
}
;
}
}
. = ;
Step 5: Quota Alerts
class QuotaAlertService {
constructor(quotaService, options = {}) {
this.quota = quotaService;
this.thresholds = {
warning: options.warningPercent || 70,
critical: options.criticalPercent || 90
};
this.alertHandlers = [];
}
onAlert(handler) {
this.alertHandlers.push(handler);
}
async checkAndAlert() {
const status = await this.quota.getQuotaStatus();
const usagePercent = parseFloat(status.usagePercent);
if (usagePercent >= this.thresholds.critical) {
await this.sendAlert('critical', status);
} else if (usagePercent >= this.thresholds.warning) {
.(, status);
}
status;
}
() {
alert = {
level,
: .(level, status),
status,
: ()
};
( handler .) {
{
(alert);
} (error) {
.(, error);
}
}
}
() {
emoji = level === ? : ;
+
+
;
}
}
alertService = (quotaService);
alertService.( (alert) => {
({
: ,
: ,
: alert.
});
});
alertService.( (alert) => {
slack.({
: ,
: alert.
});
});
. = ;
Step 6: Usage Report
async function generateQuotaReport(quotaService, cleanupService) {
console.log('=== Evernote Quota Report ===\n');
const status = await quotaService.getQuotaStatus();
console.log('Account Tier:', status.tier);
console.log('Upload Quota:', `${status.uploaded} / ${status.uploadLimit} (${status.usagePercent})`);
console.log('Remaining:', status.remaining);
console.log('Resets:', status.resetsAt.toLocaleDateString(), `(${status.daysUntilReset} days)`);
console.log('\n--- Large Notes (>5MB) ---');
const largeNotes = await cleanupService.findLargeNotes(5);
if (largeNotes.length > 0) {
largeNotes.forEach(note => {
console.();
});
.();
} {
.();
}
.();
storage = cleanupService.();
storage.(, ).( {
.();
});
.();
usagePercent = (status.);
(usagePercent > ) {
.();
.();
.();
}
(largeNotes. > ) {
.();
.();
}
.();
}
Output
- Quota monitoring service
- Image and resource optimization
- Efficient note creation with quota checking
- Storage cleanup utilities
- Alert system for quota thresholds
- Usage reporting
Cost Optimization Checklist
## Monthly Checklist
- [ ] Check quota usage status
- [ ] Review large notes (>5MB)
- [ ] Find and merge duplicates
- [ ] Archive stale notes
- [ ] Optimize images in queue
- [ ] Set up quota alerts
Resources
Next Steps
For architecture patterns, see evernote-reference-architecture.