2024-01-30 20:01:27 +00:00
|
|
|
import { load } from 'cheerio';
|
|
|
|
import fetch from 'node-fetch';
|
2024-01-30 20:54:24 +00:00
|
|
|
import DB from 'better-sqlite3';
|
|
|
|
|
2024-02-01 18:49:55 +00:00
|
|
|
const db_file = process.env.DATABASE_URL.replace('sqlite3:', '');
|
2024-02-01 18:01:26 +00:00
|
|
|
const db = DB(db_file);
|
2024-01-30 20:54:24 +00:00
|
|
|
db.pragma('journal_mode = WAL');
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 18:49:55 +00:00
|
|
|
export async function fetch_guild_users(guild_id) {
|
2024-02-01 20:27:38 +00:00
|
|
|
const res = await fetch(
|
|
|
|
`https://boardgamegeek.com/xmlapi2/guild?members=1&id=` + guild_id,
|
|
|
|
);
|
2024-02-01 15:04:14 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
if (res.status === 200) {
|
|
|
|
const $page = load(await res.text());
|
|
|
|
const users = [];
|
|
|
|
$page('member').each(function (i, member) {
|
|
|
|
users.push($page(this).attr('name'));
|
|
|
|
});
|
2024-02-01 15:04:14 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
const insert = db.prepare(
|
|
|
|
'INSERT OR IGNORE INTO bgg_user (username) VALUES(@username)',
|
|
|
|
);
|
2024-02-01 15:04:14 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
users.forEach((username) => insert.run({ username }));
|
2024-02-01 15:04:14 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
return users;
|
|
|
|
}
|
2024-02-01 15:04:14 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
throw new Error('sad');
|
2024-02-01 15:04:14 +00:00
|
|
|
}
|
|
|
|
|
2024-01-30 20:01:27 +00:00
|
|
|
export function extract_user_forsale(page) {
|
2024-02-01 20:27:38 +00:00
|
|
|
const $ = load(page);
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
const games = [];
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
const data = $('item').map(function (i, item) {
|
|
|
|
const data = {};
|
|
|
|
data.bgg_id = $(this).attr('objectid');
|
|
|
|
data.name = $(this).find('name').text();
|
|
|
|
data.thumbnail = $(this).find('thumbnail').text();
|
|
|
|
data.notes = $(this).find('conditiontext').text();
|
|
|
|
const find_price = data.notes.match(/\$(\d+)/);
|
|
|
|
data.price = undefined;
|
|
|
|
if (find_price) data.price = parseInt(find_price[1]);
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
games.push(data);
|
|
|
|
});
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
return games;
|
2024-01-30 20:01:27 +00:00
|
|
|
}
|
|
|
|
|
2024-02-01 18:49:55 +00:00
|
|
|
async function fetch_user_forsale(username, n = 1) {
|
2024-02-01 20:27:38 +00:00
|
|
|
if (n > 5) throw new Error("couldn't get collection");
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
const res = await fetch(
|
|
|
|
`https://boardgamegeek.com/xmlapi2/collection?trade=1&username=${username}`,
|
|
|
|
);
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
if (res.status === 202) {
|
|
|
|
return new Promise((accept, reject) => {
|
|
|
|
setTimeout(() => {
|
|
|
|
fetch_user_forsale(username, n + 1).then(accept);
|
|
|
|
}, 2000);
|
|
|
|
});
|
|
|
|
}
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
if (res.status === 200) return extract_user_forsale(await res.text());
|
2024-01-30 20:01:27 +00:00
|
|
|
|
2024-02-01 20:27:38 +00:00
|
|
|
throw new Error("couldn't get the collection for " + username);
|
2024-01-30 20:01:27 +00:00
|
|
|
}
|
|
|
|
|
2024-01-30 20:54:24 +00:00
|
|
|
async function update_user_games(username) {
|
2024-02-01 20:27:38 +00:00
|
|
|
const games = await fetch_user_forsale(username);
|
|
|
|
|
|
|
|
const updated_at = new Date().toISOString();
|
|
|
|
|
|
|
|
// TODO only change the games that changed
|
|
|
|
// TODO only change users that got added or removed
|
|
|
|
const insert = db.prepare(
|
|
|
|
'INSERT into game (username, bgg_id, name, thumbnail, notes,price,updated_at) VALUES(@username,@bgg_id,@name,@thumbnail,@notes,@price,@updated_at)',
|
|
|
|
);
|
|
|
|
|
|
|
|
await db
|
|
|
|
.prepare('DELETE FROM game where username = @username')
|
|
|
|
.run({ username });
|
|
|
|
|
|
|
|
for (let game of games) {
|
|
|
|
console.log(game);
|
|
|
|
insert.run({
|
|
|
|
username,
|
|
|
|
updated_at,
|
|
|
|
...game,
|
|
|
|
});
|
|
|
|
}
|
2024-01-30 20:54:24 +00:00
|
|
|
}
|
2024-02-04 15:36:46 +00:00
|
|
|
await update_user_games('gamingduo2')
|
2024-02-01 20:27:38 +00:00
|
|
|
.then(() => console.log('is done'))
|
|
|
|
.catch((e) => console.error(e));
|
2024-01-30 20:54:24 +00:00
|
|
|
|
2024-02-01 15:04:14 +00:00
|
|
|
/*
|
|
|
|
const usernames = await fetch_guild_users('1610');
|
|
|
|
|
|
|
|
await Promise.all(
|
|
|
|
usernames.map( username => {
|
|
|
|
return update_user_games(username).then( () => console.log(username, 'is done')).catch( e => console.error(e));
|
|
|
|
})
|
|
|
|
)
|
|
|
|
*/
|