Skip to content

Commit

Permalink
Merge pull request #70 from stephenyeargin/toast
Browse files Browse the repository at this point in the history
Toast recent checkins
  • Loading branch information
stephenyeargin committed Jan 9, 2024
2 parents e54f447 + 5daff12 commit 0259fba
Show file tree
Hide file tree
Showing 8 changed files with 998 additions and 26 deletions.
13 changes: 9 additions & 4 deletions README.md
Expand Up @@ -6,9 +6,12 @@ Get the latest check-ins from your Untappd friends.

## Getting Started

> [!NOTE]
> As of January 2024, the Untappd API is still not accepting new applications. :cry:
You will first need to go through the process of applying for an API key. This can take anywhere from 2-3 weeks, and you will need to explain for what you intend to use the API key. You can send a link to this page and say you want to use this package.

From here, it can be a little frustrating. [Take a look at the documentation](https://untappd.com/api/docs#authentication). It uses an OAuth1 workflow to send data back the specified endpoint, which you then need to exchange again to get an access token. A free [Runscope](http://runscope.com) account may make things easier because you can create a "bucket" to capture data coming back through the API. You will want to go through the **Server Side Documentation** workflow.
From here, it can be a little frustrating. [Take a look at the documentation](https://untappd.com/api/docs#authentication). It uses an OAuth1 workflow to send data back the specified endpoint, which you then need to exchange again to get an access token. [Postman](https://www.postman.com/) is a great tool to generate the `UNTAPPD_API_ACCESS_TOKEN` by plugging in your API credentials.

## Installation

Expand Down Expand Up @@ -37,10 +40,12 @@ Then add **hubot-untappd-friends** to your `external-scripts.json`:

- `hubot untappd` - Recent friend activity
- `hubot untappd badges` - Recent friends' badge activity
- `hubot untappd user <query>` - Get stats about a particular user
- `hubot untappd beer random` - Gets a random beer from the database
- `hubot untappd beer <query>` - Get data about a particular beer
- `hubot untappd user <username>` - Get stats about a particular user
- `hubot untappd beer random` - Retrieve a random beer
- `hubot untappd beer <query|ID>` - Get data about a particular beer
- `hubot untappd brewery <query>` - Get data about a particular brewery
- `hubot untappd toast` - Have the bot toast the most recent checkin from each user in activity feed
- `hubot untappd toast <username>` - Have the bot toast user's most recent checkin
- `hubot untappd register` - Instructions to register with the bot
- `hubot untappd approve` - Approve all pending friend requests
- `hubot untappd friends` - List the bot's friends
Expand Down
7 changes: 4 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -20,7 +20,7 @@
},
"dependencies": {
"moment": "^2.29.4",
"node-untappd": "stephenyeargin/node-untappd#v0.5-pinned"
"node-untappd": "stephenyeargin/node-untappd#be7ae9b723a6044a51c1826db7fc0539fa7fee7f"
},
"peerDependencies": {
"hubot": ">=3 || 0.0.0-development"
Expand Down
107 changes: 91 additions & 16 deletions src/untappd-friends.js
Expand Up @@ -16,6 +16,8 @@
// hubot untappd beer random - Retrieve a random beer
// hubot untappd beer <query|ID> - Get data about a particular beer
// hubot untappd brewery <query> - Get data about a particular brewery
// hubot untappd toast - Have the bot toast the most recent checkin from each user in activity feed
// hubot untappd toast <username> - Have the bot toast user's most recent checkin
// hubot untappd register - Instructions to register with the bot
// hubot untappd approve - Approve all pending friend requests
// hubot untappd friends - List the bot's friends
Expand All @@ -31,14 +33,14 @@ module.exports = (robot) => {
let maxDescriptionLength;

const countToReturn = process.env.UNTAPPD_MAX_COUNT || 5;
const maxRandomBeerId = process.env.UNTAPPD_MAX_RANDOM_ID || 5485000;
const maxRandomBeerId = process.env.UNTAPPD_MAX_RANDOM_ID || 5600000;
if (typeof process.env.UNTAPPD_MAX_DESCRIPTION_LENGTH === 'undefined') {
maxDescriptionLength = 150;
} else {
maxDescriptionLength = parseInt(process.env.UNTAPPD_MAX_DESCRIPTION_LENGTH, 10);
}

const untappd = new UntappdClient(false);
const untappd = new UntappdClient(/debug/i.test(process.env.HUBOT_LOG_LEVEL));
untappd.setClientId(process.env.UNTAPPD_API_KEY);
untappd.setClientSecret(process.env.UNTAPPD_API_SECRET);
untappd.setAccessToken(process.env.UNTAPPD_API_ACCESS_TOKEN);
Expand All @@ -56,10 +58,10 @@ module.exports = (robot) => {
const checkUntappdErrors = (err, obj, msg) => {
if (err) {
robot.logger.error(err);
msg.send(err);
msg.send(JSON.stringify(err));
return false;
}
if (obj.meta.error_detail) {
if (obj.meta?.error_detail) {
robot.logger.error(obj);
msg.send(`${obj.meta.code}: ${obj.meta.error_detail}`);
return false;
Expand Down Expand Up @@ -133,6 +135,19 @@ module.exports = (robot) => {
return `${user.first_name} ${user.last_name} (${user.user_name}): ${user.stats.total_beers} beers, ${user.stats.total_checkins} checkins, ${user.stats.total_badges} badges`;
};

// Format beer
const formatBeerResponse = (beerData) => {
let beerName = beerData.beer_name;
if (beerData.is_in_production === 0) {
beerName = `${beerName} [Out of Production]`;
}
if (beerData.beer_description && (maxDescriptionLength > 0)) {
const shortDescription = formatShortDescription(beerData.beer_description);
return `${beerName} (${beerData.beer_style} - ${beerData.beer_abv}%) by ${beerData.brewery.brewery_name} - ${shortDescription} - https://untappd.com/beer/${beerData.bid}`;
}
return `${beerName} (${beerData.beer_style} - ${beerData.beer_abv}%) by ${beerData.brewery.brewery_name} - https://untappd.com/beer/${beerData.bid}`;
};

// Get Friend Feed
const getFriendFeed = (msg) => untappd.activityFeed(
(err, obj) => {
Expand Down Expand Up @@ -186,6 +201,72 @@ module.exports = (robot) => {
{ limit: countToReturn },
);

// Toast recent checkins
const toastRecentCheckins = (msg) => {
const username = msg.match[1].trim();
const users = {};
if (username) {
untappd.userActivityFeed(
(err, obj) => {
if (!checkUntappdErrors(err, obj, msg)) {
return;
}
obj.response.checkins.items.forEach((checkin) => {
if (users[checkin.user.uid] || checkin.toasts.auth_toast) {
robot.logger.info(`Already toasted recent checkin for ${checkin.user.first_name} ${checkin.user.last_name} (${checkin.user.user_name})`);
return;
}
users[checkin.user.uid] = true;
untappd.toast(
(err2, obj2) => {
if (!checkUntappdErrors(err2, obj2, msg)) {
return;
}
if (obj2.result !== 'success') {
robot.logger.error('Failed to toast checkin.');
robot.logger.debug(obj2);
}
msg.send(`🍻 Toasted ${checkin.user.first_name} ${checkin.user.last_name} (${checkin.user.user_name})'s ${formatBeerResponse({ ...checkin.beer, brewery: checkin.brewery })}`);
},
{ CHECKIN_ID: checkin.checkin_id },
);
});
},
{ USERNAME: username, limit: 1 },
);
return;
}

untappd.activityFeed(
(err, obj) => {
if (!checkUntappdErrors(err, obj, msg)) {
return;
}
obj.response.checkins.items.forEach((checkin) => {
if (checkin.toasts.auth_toast || users[checkin.user.uid]) {
robot.logger.info(`Already toasted recent checkin for ${checkin.user.first_name} ${checkin.user.last_name} (${checkin.user.user_name})`);
return;
}
users[checkin.user.uid] = true;
untappd.toast(
(err2, obj2) => {
if (!checkUntappdErrors(err2, obj2, msg)) {
return;
}
if (obj2.result !== 'success') {
robot.logger.error('Failed to toast checkin.');
robot.logger.debug(obj2);
}
msg.send(`🍻 Toasted ${checkin.user.first_name} ${checkin.user.last_name} (${checkin.user.user_name})'s ${formatBeerResponse({ ...checkin.beer, brewery: checkin.brewery })}`);
},
{ CHECKIN_ID: checkin.checkin_id },
);
});
},
{ limit: countToReturn },
);
};

// Get Badge Feed
const getBadgeFeed = (msg) => untappd.activityFeed(
(err, obj) => {
Expand Down Expand Up @@ -299,18 +380,6 @@ module.exports = (robot) => {
);
};

const formatBeerResponse = (beerData) => {
let beerName = beerData.beer_name;
if (beerData.is_in_production === 0) {
beerName = `${beerName} [Out of Production]`;
}
if (beerData.beer_description && (maxDescriptionLength > 0)) {
const shortDescription = formatShortDescription(beerData.beer_description);
return `${beerName} (${beerData.beer_style} - ${beerData.beer_abv}%) by ${beerData.brewery.brewery_name} - ${shortDescription} - https://untappd.com/beer/${beerData.bid}`;
}
return `${beerName} (${beerData.beer_style} - ${beerData.beer_abv}%) by ${beerData.brewery.brewery_name} - https://untappd.com/beer/${beerData.bid}`;
};

// Get Random Beer
let randomAttempts = 0;
const getRandomBeer = (msg) => {
Expand Down Expand Up @@ -467,6 +536,12 @@ module.exports = (robot) => {
getFriendFeed(msg);
});

// Toast checkins
robot.respond(/untappd (?:toast|toast|prost)\s?(.*)$/i, (msg) => {
if (!checkConfiguration(msg)) { return; }
toastRecentCheckins(msg);
});

// Badges
robot.respond(/untappd badges$/i, (msg) => {
if (!checkConfiguration(msg)) { return; }
Expand Down

0 comments on commit 0259fba

Please sign in to comment.