Jump to content

User:Habst/matchWdWa.js

From Wikipedia, the free encyclopedia

This is the current revision of this page, as edited by Habst (talk | contribs) at 20:15, 18 July 2024 (replace hyphens). The present address (URL) is a permanent link to this version.

(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
window.wd ??= {};
window.wa ??= {};
window.wp ??= {};
window.redirs ??= {};

const wdEdit = async (qid, prop, val, cmt, refs = [], rank = 'normal') => {
  return await (await fetch(`https://www.wikidata.org/w/rest.php/wikibase/v0/entities/items/${qid}/statements`, {
    headers: { 'Content-type': 'application/json' },
    method: 'POST',
    body: JSON.stringify({
      statement: {
        rank,
        property: { id: prop },
        value: { type: 'value', content: val },
        qualifiers: [], references: refs,
      },
      tags: [], bot: false,
      comment: cmt,
    }),
  })).json();
};
wikiJsonP = async (props) => {
  let wpResult;
  window.cb = res => wpResult = res;
  const script = Object.assign(document.createElement('script'), {
    src: 'https://en.wikipedia.org/w/api.php?' + new URLSearchParams({
      action: 'query',
      format: 'json',
      callback: 'cb',
      ...props,
    })
  });
  document.body.appendChild(script);
  await new Promise(res => script.addEventListener('load', res));
  return wpResult;
};
makeWaDate = dt => {
  const words = dt.toLocaleString('en-GB', { day: '2-digit', month: 'short', year: 'numeric', timeZone: 'UTC' }).toUpperCase().split(' ');
  words.splice(1, 1, words.at(1).slice(0, 3));
  return words.join(' ');
}
normalize = s => s.replaceAll('_', ' ').replaceAll('-', ' ').split('(')[0].normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();

for (const p of ps['*'][0].a['*']) {
  if (p.waid) continue;
  const name = normalize(p.title);
  console.log(name, p.q);
  wd[p.q] ??= await (await fetch(`https://www.wikidata.org/wiki/Special:EntityData/${p.q}.json`)).json();
  let dobs = wd[p.q].entities[p.q].claims.P569?.map(c => ({
    v: new Date(c.mainsnak.datavalue.value.time.replace('+', '').split('T')[0]),
    precision: c.mainsnak.datavalue.value.precision,
  })).filter(dob => dob.precision == 11).map(d => makeWaDate(d.v)) ?? [];
  redirs[p.q] ??= await wikiJsonP({ prop: 'redirects', generator: 'redirects', formatversion: '2', titles: p.title });
  const aliases = wd[p.q].entities[p.q].aliases.en?.map(a => normalize(a.value)) ?? [];
  aliases.push(...(redirs[p.q].query?.pages.map(pg => normalize(pg.title)) ?? []));

  if (!dobs.length) {
    //console.log('no dobs', `https://en.wikipedia.org/wiki/${p.title}`);

    wp[p.title] ??= await wikiJsonP({ prop: 'extracts', exchars: '1000', titles: p.title });

    const ex = Object.values(wp[p.title].query.pages)[0].extract;
    const born = ex.replace(' in ', ')').match(/\(born ([^)]+)\)/)?.[1];
    if (born && born.split(' ').length === 3) {
      const dt = new Date(born);
      if (!p.addedDob) await wdEdit(p.q, 'P569', { time: `+${dt.toLocaleDateString('sv')}T00:00:00Z`, precision: 11, calendarmodel: 'http://www.wikidata.org/entity/Q1985727' }, 'Adding date of birth from enwiki', [{ parts: [{
        property: { id: 'P143' },
        value: { type: 'value', content: 'Q328' },
      }] }], 'preferred');
      p.addedDob = true;
      dobs = [makeWaDate(dt)];
    } else {
      console.log('no dob, no born in lede');
      continue;
    }
  }
  wa[name] ??= await (await fetch("https://graphql-prod-4607.prod.aws.worldathletics.org/graphql", {
    headers: { "x-api-key": "da2-xevhjbj7ybgcnjzrwiad2u6qqq" }, // intentionally public
    body: JSON.stringify({
      operationName: "SearchCompetitors",
      variables: { query: name },
      query: `query SearchCompetitors($query: String, $gender: GenderType, $disciplineCode: String, $environment: String, $countryCode: String) {
  searchCompetitors(query: $query, gender: $gender, disciplineCode: $disciplineCode, environment: $environment, countryCode: $countryCode) {
    aaAthleteId
    familyName
    givenName
    birthDate
    disciplines
    iaafId
    gender
    country
    urlSlug
    __typename
  }
}`
    }),
    method: "POST",
  })).json();
  let matchingName;
  const easternOrder = ['CHN', 'TPE', 'KOR'];
  const matches = wa[name].data.searchCompetitors.filter(sc => {
    if (!sc.birthDate) return false;
    const waNames = [normalize(`${sc.givenName} ${sc.familyName}`)];
    if (easternOrder.includes(sc.country)) waNames.push(normalize(`${sc.familyName} ${sc.givenName}`));
    const nameMatch = [name, ...aliases].find(n => waNames.includes(n));
    if (nameMatch) {
      if (dobs.some(dob => sc.birthDate === dob || sc.birthDate === dob.split(' ').at(-1))) {
        // allow matching year
        matchingName = nameMatch;
        return true;
      }
    }
    return false;
  });
  if (!matches.length) { console.log('no matches'); continue; }
  if (matches.length > 1) { console.log('many matches'); continue; }
  console.log('*** found match', matches[0].aaAthleteId);
  await wdEdit(p.q, 'P1146', matches[0].aaAthleteId, `Adding World Athletics ID with matching name (${matchingName}) and date of birth`);
  p.waid = matches[0].aaAthleteId;
}
const todos = ps['*'][0].a['*'].filter(p => !p.waid).map(p => `* [[${p.title}]]`);
console.log(todos.length);
todos.join('\n');