aboutsummaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/services')
-rw-r--r--src/services/SocialLinkingService.ts184
-rw-r--r--src/services/UserProfileService.ts40
-rw-r--r--src/services/index.ts1
3 files changed, 209 insertions, 16 deletions
diff --git a/src/services/SocialLinkingService.ts b/src/services/SocialLinkingService.ts
new file mode 100644
index 00000000..8d67d90e
--- /dev/null
+++ b/src/services/SocialLinkingService.ts
@@ -0,0 +1,184 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import {Alert} from 'react-native';
+import InAppBrowser from 'react-native-inappbrowser-reborn';
+import {
+ LINKED_SOCIALS_ENDPOINT,
+ LINK_FB_ENDPOINT,
+ LINK_FB_OAUTH,
+ LINK_IG_ENDPOINT,
+ LINK_IG_OAUTH,
+ LINK_SNAPCHAT_ENDPOINT,
+ LINK_TIKTOK_ENDPOINT,
+ LINK_TWITTER_ENDPOINT,
+ LINK_TWITTER_OAUTH,
+} from '../constants';
+
+// A list of endpoint strings for all the integrated socials
+export const integratedEndpoints: {[social: string]: [string, string]} = {
+ Instagram: [LINK_IG_OAUTH, LINK_IG_ENDPOINT],
+ Facebook: [LINK_FB_OAUTH, LINK_FB_ENDPOINT],
+ Twitter: [LINK_TWITTER_OAUTH, LINK_TWITTER_ENDPOINT],
+};
+
+export const nonIntegratedEndponits: {[social: string]: string} = {
+ Snapchat: LINK_SNAPCHAT_ENDPOINT,
+ TikTok: LINK_TIKTOK_ENDPOINT,
+};
+
+export const registerNonIntegratedSocialLink: (
+ socialType: string,
+ username: string,
+) => Promise<boolean> = async (socialType, username) => {
+ if (!(socialType in nonIntegratedEndponits)) {
+ return false;
+ }
+ try {
+ const user_token = await AsyncStorage.getItem('token');
+ const response = await fetch(nonIntegratedEndponits[socialType], {
+ method: 'POST',
+ headers: {
+ Authorization: `Token ${user_token}`,
+ },
+ body: JSON.stringify({
+ username: username,
+ }),
+ });
+ return response.status === 200;
+ } catch (error) {
+ console.log(error);
+ return false;
+ }
+};
+
+// We have already received the short-lived token (callback_data), sending it
+// to backend to exchange for and store the long-lived token.
+export const registerIntegratedSocialLink: (
+ callback_data: string,
+ user_token: string,
+ socialType: string,
+) => Promise<boolean> = async (callback_data, user_token, socialType) => {
+ if (!(socialType in integratedEndpoints)) {
+ return false;
+ }
+ const response = await fetch(integratedEndpoints[socialType][1], {
+ method: 'POST',
+ headers: {
+ Authorization: `Token ${user_token}`,
+ },
+ body: JSON.stringify({
+ callback_url: callback_data,
+ }),
+ });
+ if (!(response.status === 201)) {
+ console.log(await response.json());
+ }
+ return response.status === 201;
+};
+
+// Twitter is a special case since they use OAuth1, we will need to request
+// for a request_token before we can begin browser signin.
+export const getTwitterRequestToken: (
+ user_token: string,
+) => Promise<string> = async (user_token) => {
+ const response = await fetch(integratedEndpoints.Twitter[0], {
+ method: 'GET',
+ headers: {
+ Authorization: `Token ${user_token}`,
+ },
+ });
+ return response.url;
+};
+
+// one stop shop for handling all browser sign-in social linkings
+export const handlePressForAuthBrowser: (
+ socialType: string,
+) => Promise<boolean> = async (socialType: string) => {
+ try {
+ if (!(socialType in integratedEndpoints)) {
+ Alert.alert('Coming soon!');
+ return false;
+ }
+
+ if (!(await InAppBrowser.isAvailable())) {
+ // Okay... to open an external browser and have it link back to
+ // the app is a bit tricky, we will need to have navigation routes
+ // setup for this screen and have it hooked up.
+ // See https://github.com/proyecto26/react-native-inappbrowser#authentication-flow-using-deep-linking
+ // Though this isn't the end of the world, from the documentation,
+ // the in-app browser should be supported from iOS 11, which
+ // is about 98.5% of all iOS devices in the world.
+ // See https://support.apple.com/en-gb/HT209574
+ Alert.alert(
+ 'Sorry! Your device was unable to open a browser to let you sign-in! 😔',
+ );
+ return false;
+ }
+
+ let url = integratedEndpoints[socialType][0];
+ const user_token = await AsyncStorage.getItem('token');
+
+ if (!user_token) {
+ throw 'Unable to get user token';
+ }
+
+ // We will need to do an extra step for twitter sign-in
+ if (socialType === 'Twitter') {
+ url = await getTwitterRequestToken(user_token);
+ }
+
+ return await InAppBrowser.openAuth(url, 'taggid://callback', {
+ ephemeralWebSession: true,
+ })
+ .then(async (response) => {
+ if (response.type === 'success' && response.url) {
+ const success = await registerIntegratedSocialLink(
+ response.url,
+ user_token,
+ socialType,
+ );
+ if (!success) {
+ throw 'Unable to register with backend';
+ }
+ Alert.alert(`Successfully linked ${socialType} 🎉`);
+ return true;
+ } else {
+ throw 'Error from Oauth API';
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ Alert.alert(
+ `Something went wrong, we can't link with ${socialType} 😔`,
+ );
+ return false;
+ });
+ } catch (error) {
+ console.log(error);
+ Alert.alert(`Something went wrong, we can't link with ${socialType} 😔`);
+ }
+ return false;
+};
+
+// get all the linked socials from backend as an array
+export const getLinkedSocials: (user_id: string) => Promise<string[]> = async (
+ user_id: string,
+) => {
+ try {
+ const user_token = await AsyncStorage.getItem('token');
+ const response = await fetch(`${LINKED_SOCIALS_ENDPOINT}${user_id}/`, {
+ method: 'GET',
+ headers: {
+ Authorization: 'Token ' + user_token,
+ },
+ });
+ const body = await response.json();
+ if (response.status !== 200) {
+ console.log(body);
+ throw 'Unable to fetch from server';
+ }
+ return body.linked_socials || [];
+ } catch (error) {
+ console.log(error);
+ return [];
+ }
+};
diff --git a/src/services/UserProfileService.ts b/src/services/UserProfileService.ts
index f5523be4..31383f67 100644
--- a/src/services/UserProfileService.ts
+++ b/src/services/UserProfileService.ts
@@ -1,16 +1,18 @@
//Abstracted common profile api calls out here
+import AsyncStorage from '@react-native-community/async-storage';
import {Alert} from 'react-native';
+import RNFetchBlob from 'rn-fetch-blob';
+import {SocialAccountType} from 'src/types';
import {
- PROFILE_INFO_ENDPOINT,
AVATAR_PHOTO_ENDPOINT,
COVER_PHOTO_ENDPOINT,
+ GET_FB_POSTS_ENDPOINT,
+ GET_IG_POSTS_ENDPOINT,
+ GET_TWITTER_POSTS_ENDPOINT,
+ PROFILE_INFO_ENDPOINT,
} from '../constants';
-import AsyncStorage from '@react-native-community/async-storage';
-import RNFetchBlob from 'rn-fetch-blob';
-import {SocialAccountType} from 'src/types';
-
export const loadProfileInfo = async (
token: string,
userId: string,
@@ -83,13 +85,19 @@ export const loadCover = async (
}
};
-export const loadSocialPosts = async (
- token: string,
+const integratedSocialPostsEndpoints: {[social: string]: string} = {
+ Facebook: GET_FB_POSTS_ENDPOINT,
+ Instagram: GET_IG_POSTS_ENDPOINT,
+ Twitter: GET_TWITTER_POSTS_ENDPOINT,
+};
+
+export const loadSocialPosts: (
userId: string,
socialType: string,
- endpoint: string,
- socialAccounts: Record<string, SocialAccountType>,
-) => {
+) => Promise<SocialAccountType> = async (userId, socialType) => {
+ const token = await AsyncStorage.getItem('token');
+ const endpoint = integratedSocialPostsEndpoints[socialType];
+ const accountData: SocialAccountType = {};
try {
const response = await fetch(endpoint + `${userId}/`, {
method: 'GET',
@@ -99,16 +107,16 @@ export const loadSocialPosts = async (
});
if (response.status === 200) {
const body = await response.json();
- socialAccounts[socialType].handle = body.handle;
- socialAccounts[socialType].posts = body.posts;
- socialAccounts[socialType].profile_pic = body.profile_pic;
+ accountData.handle = body.handle;
+ accountData.posts = body.posts;
+ accountData.profile_pic = body.profile_pic;
} else {
- throw new Error(await response.json());
+ throw 'Unable to fetch posts data from ' + socialType;
}
} catch (error) {
- console.log(error);
+ console.warn(error);
}
- return socialAccounts;
+ return accountData;
};
export const loadRecentlySearchedUsers = async (callback: Function) => {
diff --git a/src/services/index.ts b/src/services/index.ts
index aa13dbe3..6d0f4314 100644
--- a/src/services/index.ts
+++ b/src/services/index.ts
@@ -1,3 +1,4 @@
export * from './UserProfileService';
+export * from './SocialLinkingService';
export * from './MomentServices';
export * from './UserFollowServices';