← back to Eur Recrawl
login-dgtrade.mjs
55 lines
// login-dgtrade.mjs — log into the DG B2B trade portal (trade.designersguild.com),
// where the actual TRADE PRICES live. Not Cloudflare-walled. Username candidates tried
// in order; password read from /tmp/dg-newpw.txt (the just-reset pw). Saves session.
import { chromium } from 'playwright';
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
function secret(file, key) {
if (!fs.existsSync(file)) return '';
for (const line of fs.readFileSync(file, 'utf8').split('\n')) {
const m = line.match(/^([A-Z0-9_]+)\s*=\s*(.*)$/);
if (m && m[1] === key) return m[2].trim().replace(/^["']|["']$/g, '');
}
return '';
}
const SEC = path.join(os.homedir(), 'Projects/secrets-manager/.env');
// default to the EXISTING working portal password; override with PW=new to use the reset pw.
const pw = process.env.PW === 'new'
? fs.readFileSync('/tmp/dg-newpw.txt', 'utf8').trim()
: (secret(SEC, 'DESIGNERSGUILD_PORTAL_PASS') || fs.readFileSync('/tmp/dg-newpw.txt', 'utf8').trim());
const portalUser = secret(SEC, 'DESIGNERSGUILD_PORTAL_USER');
const user = process.argv[2] || portalUser || 'info@designerwallcoverings.com';
const loginUrl = 'https://trade.designersguild.com/b2b2/Content/Security/Default.aspx';
const ctx = await chromium.launchPersistentContext(path.join(process.cwd(), '.auth', 'dgtrade'), {
headless: false, channel: 'chrome', viewport: { width: 1440, height: 900 },
});
const page = ctx.pages()[0] || await ctx.newPage();
await page.goto(loginUrl, { waitUntil: 'domcontentloaded', timeout: 60000 }).catch((e) => console.log('nav', e.message));
await page.waitForTimeout(2500);
console.log(`login user (last4 of pw ...${pw.slice(-3)}):`, user);
const u = await page.$('#txtUserName');
const p = await page.$('#txtPassword');
if (u) { await u.fill(user).catch(() => {}); console.log('username filled'); } else console.log('username field not found');
if (p) { await p.fill(pw).catch(() => {}); console.log('password filled'); } else console.log('password field not found');
// "Log in" is an <a> anchor (JS postback)
const a = await page.$('a:has-text("Log in"), #btnLogin, input[type=submit]');
if (a) { await a.click().catch(() => {}); console.log('Log in clicked'); } else { await page.keyboard.press('Enter').catch(() => {}); }
await page.waitForTimeout(6000);
const info = await page.evaluate(() => {
const t = document.body ? document.body.innerText : '';
return { url: location.href, title: document.title, err: /invalid|incorrect|not recognised|failed|error/i.test(t), loggedIn: /log ?off|log ?out|sign ?out|welcome|my account|basket|catalogue/i.test(t), sample: t.replace(/\s+/g, ' ').slice(0, 200) };
});
console.log('post-login url:', info.url);
console.log('title:', info.title, '| loggedIn~', info.loggedIn, '| errText~', info.err);
console.log('page sample:', info.sample);
if (info.loggedIn && !info.err) { await ctx.storageState({ path: path.join(process.cwd(), '.auth', 'dgtrade-state.json') }).catch(() => {}); console.log('✅ session saved -> .auth/dgtrade-state.json'); }
await page.screenshot({ path: 'probe-dgtrade.png' }).catch(() => {});
await page.waitForTimeout(1500);
await ctx.close();