(function (root, factory) {
var api = factory();
if (typeof module === 'object' && module.exports) {
module.exports = api;
}
if (root) {
root.TaberebaLegacyMigration = api;
}
}(typeof window !== 'undefined' ? window : globalThis, function () {
'use strict';
var settingsKey = 'tabereba_settings_v1';
var backupKey = 'tabereba_settings_v1_before_legacy_migration';
function clean(value, limit) {
return String(value === null || typeof value === 'undefined' ? '' : value)
.replace(/[\u0000-\u001f\u007f]/g, '').trim().slice(0, limit);
}
function decodeInput(value) {
value = clean(value, 65536);
if (value.indexOf('%') === -1) {
return value;
}
try {
return decodeURIComponent(value.replace(/\+/g, ' '));
} catch (error) {
return value;
}
}
function decodeLegacyText(value) {
return clean(value, 4096).replace(/"/gi, '"')
.replace(/*39;|*27;|'/gi, "'")
.replace(/</gi, '<').replace(/>/gi, '>').replace(/&/gi, '&');
}
function findCookie(cookieString, cookieName) {
cookieString = String(cookieString || '');
cookieName = clean(cookieName, 100);
if (!/^[A-Za-z0-9_-]{1,100}$/.test(cookieName) || cookieString.length > 65536) {
return '';
}
var found = '';
cookieString.split(';').some(function (part) {
var separator = part.indexOf('=');
if (separator === -1 || part.slice(0, separator).trim() !== cookieName) {
return false;
}
found = part.slice(separator + 1).trim().slice(0, 65536);
return true;
});
return found;
}
function parseRowsDetailed(value) {
var rows = {};
var duplicateKeys = [];
var unsupportedKeys = [];
decodeInput(value).split('::').forEach(function (line) {
var columns = line.split(',');
var key = clean(columns.shift(), 20);
if (!/^[a-z][a-z0-9_]{0,19}$/i.test(key)) {
return;
}
if (Object.prototype.hasOwnProperty.call(rows, key)) {
duplicateKeys.push(key);
return;
}
if (['sn', 'hts', 'htp'].indexOf(key) === -1) {
unsupportedKeys.push(key);
return;
}
rows[key] = columns.map(decodeLegacyText);
});
return {rows: rows, duplicate_keys: duplicateKeys, unsupported_keys: unsupportedKeys};
}
function createHotpepperMylink(sid, pid) {
if (!/^[0-9]{1,20}$/.test(sid) || !/^[0-9]{1,20}$/.test(pid)) {
return '';
}
var destination = encodeURIComponent('https://www.hotpepper.jp/');
return ''
+ 'ホットペッパー グルメ
';
}
function emptySite(name) {
return {
site_name: clean(name, 100),
hotpepper_valuecommerce_html: '',
tabelog_valuecommerce_html: '',
gnavi_linkshare_html: '',
image_size: 'medium',
shop_label_suffix: '',
template_key: 'amazlet-2',
shop_icon_type: 'none',
custom_css_preset: 'simple',
show_catch: true,
show_address: true,
background_opacity: 100,
migration_info: {}
};
}
function validSettingsJson(value) {
try {
var parsed = typeof value === 'string' ? JSON.parse(value) : value;
return parsed && parsed.service === 'tabereba' && parsed.schema_version === 1
&& parsed.version === 1 && Array.isArray(parsed.sites)
&& parsed.sites.length >= 1 && parsed.sites.length <= 20;
} catch (error) {
return false;
}
}
function writeAndVerify(storage, key, value) {
storage.setItem(key, value);
return storage.getItem(key) === value;
}
function applyToStorage(storage, nextSettings) {
if (!validSettingsJson(nextSettings)) {
return {success: false, error: 'next_invalid'};
}
var current;
var next = JSON.stringify(nextSettings);
try {
current = storage.getItem(settingsKey) || '';
if (!validSettingsJson(current)) {
return {success: false, error: 'current_invalid'};
}
if (!writeAndVerify(storage, backupKey, current)) {
return {success: false, error: 'backup_failed'};
}
if (!writeAndVerify(storage, settingsKey, next)) {
return {success: false, error: 'settings_failed'};
}
return {success: true, error: ''};
} catch (error) {
return {success: false, error: 'storage_failed'};
}
}
function restoreFromStorage(storage) {
try {
var backup = storage.getItem(backupKey) || '';
if (!validSettingsJson(backup)) {
return {success: false, error: 'backup_invalid'};
}
if (!writeAndVerify(storage, settingsKey, backup)) {
return {success: false, error: 'settings_failed'};
}
storage.removeItem(backupKey);
return {success: storage.getItem(backupKey) === null,
error: storage.getItem(backupKey) === null ? '' : 'backup_remove_failed'};
} catch (error) {
return {success: false, error: 'storage_failed'};
}
}
function convert(value, options) {
options = options || {};
var parsed = parseRowsDetailed(value);
var rows = parsed.rows;
var names = rows.sn || [];
if (parsed.duplicate_keys.length > 0) {
return {success: false, error: 'duplicate_key', settings: null, summary: null};
}
if (parsed.unsupported_keys.length > 0) {
return {success: false, error: 'unsupported_key', settings: null, summary: null};
}
if (names.length < 1 || names.length > 5) {
return {success: false, error: 'site_count', settings: null, summary: null};
}
var migratedAt = clean(options.migratedAt || new Date().toISOString(), 40);
var sidValues = rows.hts || [];
var pidValues = rows.htp || [];
var hasAffiliateRows = Object.prototype.hasOwnProperty.call(rows, 'hts')
|| Object.prototype.hasOwnProperty.call(rows, 'htp');
var countMismatch = hasAffiliateRows
&& (sidValues.length !== names.length || pidValues.length !== names.length);
var migratedCount = 0;
var incompleteCount = 0;
var sites = names.map(function (name, index) {
var site = emptySite(name);
var sid = clean(sidValues[index], 20);
var pid = clean(pidValues[index], 20);
var hasPairValue = sid !== '' || pid !== '';
var mylink = countMismatch ? '' : createHotpepperMylink(sid, pid);
var incomplete = countMismatch ? hasAffiliateRows : (hasPairValue && mylink === '');
if (mylink) {
site.hotpepper_valuecommerce_html = mylink;
migratedCount += 1;
}
if (incomplete) {
incompleteCount += 1;
}
if (mylink || incomplete) {
site.migration_info = {
source: 'legacy_cookie',
needs_affiliate_review: true,
incomplete_valuecommerce_pairs: incomplete ? ['hotpepper'] : [],
migrated_at: migratedAt,
reviewed_at: ''
};
}
return site;
});
return {
success: true,
error: '',
settings: {service: 'tabereba', schema_version: 1, version: 1,
default_site_index: 0, active_site_index: 0, sites: sites},
summary: {site_count: sites.length, hotpepper_count: migratedCount,
incomplete_hotpepper_count: incompleteCount, count_mismatch: countMismatch}
};
}
return {settingsKey: settingsKey, backupKey: backupKey, findCookie: findCookie,
createHotpepperMylink: createHotpepperMylink, validSettingsJson: validSettingsJson,
applyToStorage: applyToStorage, restoreFromStorage: restoreFromStorage, convert: convert};
}));