UNPKG

hockeybar

Version:

A bot used to automate the updating of hockey league subreddit markdown

239 lines (229 loc) 8.76 kB
const Snoowrap = require('snoowrap'); const Joi = require('joi'); const { EventSchema, TeamSchema, SkaterSchema, GoalieSchema } = require('./schemas'); const Teams = require('./teams'); const ScheduleBuilder = require('./parsers/schedule'); const TeamStatsBuilder = require('./parsers/teamStats'); const PlayerStatsBuilder = require('./parsers/playerStats'); const GameStatsBuilder = require('./parsers/gameStats'); /** * * @example * var hockeyBar = new HockeyBar( * 'anaheim-ducks' * ,{ * clientId: process.env.CLIENT_ID, * clientSecret: process.env.CLIENT_SECRET, * userId: process.env.REDDIT_USER, * userPassword: process.env.REDDIT_PASS, * subreddit: process.env.SUBREDDIT * } * ,sidebarTemplate); */ var HockeyBar = class HockeyBar { /** * this is constructor description. * @param {string} teamName The name of your team should be all lower case with spaces replaced by a dash (-). For example if your reddit team is the New Jersey Devils, you would use 'new-jersey-devils'. * @param {{clientId: string, clientSecret: string, userId: string, userPassword: string, subreddit: string}} redditOptions This object is used to authenticate with Snoowrap a reddit API library. * @param {string} sidebarTemplate This is your subreddit sidebar template markdown. It can be supplied with the constructor or fetched after instantiation using loadSidebarTemplateFromReddit(). */ constructor(teamName, redditOptions, sidebarTemplate, includePreSeason = false) { this.team = Teams[teamName]; this.team.uri = teamName; this.subreddit = redditOptions.subreddit; console.log(`Constructing HockeyBar for the ${this.team.name}`); this.reddit = new Snoowrap({ userAgent: `${this.teamName}-hockey-bar`, clientId: redditOptions.clientId, clientSecret: redditOptions.clientSecret, username: redditOptions.userId, password: redditOptions.userPassword }); console.log('reddit client loaded...') if (sidebarTemplate === undefined) { console.log('sidebarTemplate undefined, load from subreddit wiki') } else { this.sidebarTemplate = sidebarTemplate; this.markdown = sidebarTemplate; } this.scheduleBuilder = new ScheduleBuilder(this.team, includePreSeason); this.gameStatsBuilder = new GameStatsBuilder(this.team); this.teamStatsBuilder = new TeamStatsBuilder(this.team); this.playerStatsBuilder = new PlayerStatsBuilder(this.team); } /** * This function may be called to load a markdown template from the supplied wiki page. * @param {string} wikiPage The wiki page that should be queried for the markdown template */ loadSidebarTemplateFromReddit(wikiPage) { return new Promise((resolve, reject) => { this.reddit.getSubreddit(this.subreddit).getWikiPage('sidebar').fetch().then((page) => { this.sidebarTemplate = page.content_md; this.markdown = page.content_md; console.log('sidebarTemplate set from subreddit wiki') return resolve(); }); }); } /** * This function provides the raw team schedule data that may be used to generate markdown. * @param {number} days The number of days to include in the array of events */ fetchTeamSchedule(days = 5) { return new Promise((resolve, reject) => { this.scheduleBuilder.parse(days).then((data) => { resolve(data); }); }); } /** * This function provides the raw skater data that may be used to generate markdown * @param {number} top The number of skaters to include in the array of data. */ fetchTeamSkaters(top = 5) { return new Promise((resolve, reject) => { this.playerStatsBuilder.parse(top, 1).then((data) => { resolve(data); }); }); } /** * This function provides the raw skater data that may be used to generate markdown * @param {number} top The number of skaters to include in the array of data. */ fetchTeamGoalies(top = 5) { return new Promise((resolve, reject) => { this.playerStatsBuilder.parse(top, 2).then((data) => { resolve(data); }); }); } /** * This function provides the raw skater data that may be used to generate markdown */ fetchDivisionStats() { return new Promise((resolve, reject) => { this.teamStatsBuilder.parse().then((data) => { resolve(data); }); }); } /** * This function provides the raw skater data that may be used to generate markdown */ fetchConferenceStats() { return new Promise((resolve, reject) => { this.teamStatsBuilder.parse(2).then((data) => { resolve(data); }); }); } /** * * @param {any[]} data The array returned from a fetchDataType() function. * @param {Function} markdownBuilder You may pass in a delegate function to override the default markdown building functionality. * * * @example * asMarkdown(data, () => { * var buildEventMarkdown = (event) => { * var markdown = `[${event.date}](http://some-site.com/${event.opponent.name})`; * return markdown; * }; * var eventMarkdown = ''; * for (var i = 0; i < data.length; i++) { * eventMarkdown = eventMarkdown + buildEventMarkdown(data[i]); * } * return eventMarkdown; * }) */ asMarkdown(data, markdownBuilder = () => {}) { if (data.length > 0) { let type = this.getType(data[0]); return new Promise((resolve, reject) => { switch (type) { case Types.Event: markdownBuilder = this.scheduleBuilder.buildTeamScheduleMarkdown.bind(this.scheduleBuilder); break; case Types.Skater: markdownBuilder = this.playerStatsBuilder.buildSkaterStats.bind(this.playerStatsBuilder); break; case Types.Goalie: markdownBuilder = this.playerStatsBuilder.buildGoalieStats.bind(this.playerStatsBuilder); break; default: markdownBuilder = this.teamStatsBuilder.buildStats.bind(this.teamStatsBuilder); break; } markdownBuilder(data).then(md => { resolve(md); }); }); } } /** * This function is used to replace a known substring target with generated markdown. * @param {string} replaceStr The search pattern that will be found and replaced with the markdown. * @param {string} markdown The generated markdown. */ updateTemplate(replaceStr, markdown) { return new Promise((resolve, reject) => { this.markdown = this.markdown.replace(replaceStr, markdown); resolve(); }); } /** * This function is used to write the updated sidebar template to the current subreddit. */ updateRedditSidebar() { return new Promise((resolve, reject) => { var self = this; this.reddit.getSubreddit(this.subreddit).editSettings({ description: self.markdown }).then(() => { this.markdown = this.sidebarTemplate; resolve(); }); }); } /** * */ fetchCurrentGameStats(){ return new Promise((resolve, reject) => { this.gameStatsBuilder.getCurrentGame().then(gameData => { resolve(gameData); }); }); } /** * @private * @param {Object} obj The object used to infer its type or structure. */ getType(obj) { if (obj.type === 'event') { return Types.Event; } if (obj.type === 'skater') { return Types.Skater; } if (obj.type === 'goalie') { return Types.Goalie; } if (obj.type === 'team') { return Types.Team; } } } const Types = Object.freeze({ Event: "EVENT_DATA_TYPE", Skater: "SKATER_DATA_TYPE", Goalie: "GOALIE_DATA_TYPE", Team: "TEAM_DATA_TYPE" }); module.exports = HockeyBar;