send recsys powered-by #6875
6 changed files with 62 additions and 19 deletions
3
flow-typed/search.js
vendored
3
flow-typed/search.js
vendored
|
@ -28,7 +28,7 @@ declare type SearchOptions = {
|
|||
|
||||
declare type SearchState = {
|
||||
options: SearchOptions,
|
||||
urisByQuery: {},
|
||||
resultsByQuery: {},
|
||||
hasReachedMaxResultsLength: {},
|
||||
searching: boolean,
|
||||
};
|
||||
|
@ -40,6 +40,7 @@ declare type SearchSuccess = {
|
|||
from: number,
|
||||
size: number,
|
||||
uris: Array<string>,
|
||||
recsys: string,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
makeSelectRecommendedClaimIds,
|
||||
makeSelectRecommendationClicks,
|
||||
} from 'redux/selectors/content';
|
||||
import { makeSelectRecommendedRecsysIdForClaimId } from 'redux/selectors/search';
|
||||
|
||||
const VERSION = '0.0.1';
|
||||
|
||||
|
@ -36,7 +37,7 @@ function createRecsys(claimId, userId, events, loadedAt, isEmbed) {
|
|||
claimId: claimId,
|
||||
pageLoadedAt: pageLoadedAt,
|
||||
pageExitedAt: pageExitedAt,
|
||||
recsysId: recsysId,
|
||||
recsysId: makeSelectRecommendedRecsysIdForClaimId(claimId)(state) || recsysId,
|
||||
recClaimIds: makeSelectRecommendedClaimIds(claimId)(state),
|
||||
recClickedVideoIdx: makeSelectRecommendationClicks(claimId)(state),
|
||||
events: events,
|
||||
|
|
|
@ -61,13 +61,14 @@ export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
|
|||
|
||||
lighthouse
|
||||
.search(queryWithOptions)
|
||||
.then((data: Array<{ name: string, claimId: string }>) => {
|
||||
.then((data: { body: Array<{ name: string, claimId: string }>, poweredBy: string }) => {
|
||||
const { body: result, poweredBy } = data;
|
||||
const uris = [];
|
||||
const actions = [];
|
||||
|
||||
data.forEach((result) => {
|
||||
if (result) {
|
||||
const { name, claimId } = result;
|
||||
result.forEach((item) => {
|
||||
if (item) {
|
||||
const { name, claimId } = item;
|
||||
const urlObj: LbryUrlObj = {};
|
||||
|
||||
if (name.startsWith('@')) {
|
||||
|
@ -94,6 +95,7 @@ export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
|
|||
from: from,
|
||||
size: size,
|
||||
uris,
|
||||
recsys: poweredBy,
|
||||
},
|
||||
});
|
||||
dispatch(batchActions(...actions));
|
||||
|
|
|
@ -17,7 +17,7 @@ const defaultState: SearchState = {
|
|||
[SEARCH_OPTIONS.MEDIA_IMAGE]: defaultSearchTypes.includes(SEARCH_OPTIONS.MEDIA_IMAGE),
|
||||
[SEARCH_OPTIONS.MEDIA_APPLICATION]: defaultSearchTypes.includes(SEARCH_OPTIONS.MEDIA_APPLICATION),
|
||||
},
|
||||
urisByQuery: {},
|
||||
resultsByQuery: {},
|
||||
hasReachedMaxResultsLength: {},
|
||||
searching: false,
|
||||
};
|
||||
|
@ -29,21 +29,23 @@ export default handleActions(
|
|||
searching: true,
|
||||
}),
|
||||
[ACTIONS.SEARCH_SUCCESS]: (state: SearchState, action: SearchSuccess): SearchState => {
|
||||
const { query, uris, from, size } = action.data;
|
||||
const { query, uris, from, size, recsys } = action.data;
|
||||
const normalizedQuery = createNormalizedSearchKey(query);
|
||||
const urisForQuery = state.resultsByQuery[normalizedQuery] && state.resultsByQuery[normalizedQuery]['uris'];
|
||||
|
||||
let newUris = uris;
|
||||
if (from !== 0 && state.urisByQuery[normalizedQuery]) {
|
||||
newUris = Array.from(new Set(state.urisByQuery[normalizedQuery].concat(uris)));
|
||||
if (from !== 0 && urisForQuery) {
|
||||
newUris = Array.from(new Set(urisForQuery.concat(uris)));
|
||||
}
|
||||
|
||||
// The returned number of urls is less than the page size, so we're on the last page
|
||||
const noMoreResults = size && uris.length < size;
|
||||
|
||||
const results = { uris: newUris, recsys };
|
||||
return {
|
||||
...state,
|
||||
searching: false,
|
||||
urisByQuery: Object.assign({}, state.urisByQuery, { [normalizedQuery]: newUris }),
|
||||
resultsByQuery: Object.assign({}, state.resultsByQuery, { [normalizedQuery]: results }),
|
||||
hasReachedMaxResultsLength: Object.assign({}, state.hasReachedMaxResultsLength, {
|
||||
[normalizedQuery]: noMoreResults,
|
||||
}),
|
||||
|
|
|
@ -4,6 +4,7 @@ import { selectShowMatureContent } from 'redux/selectors/settings';
|
|||
import {
|
||||
parseURI,
|
||||
makeSelectClaimForUri,
|
||||
makeSelectClaimForClaimId,
|
||||
makeSelectClaimIsNsfw,
|
||||
buildURI,
|
||||
isClaimNsfw,
|
||||
|
@ -28,7 +29,7 @@ export const selectIsSearching: (state: State) => boolean = createSelector(selec
|
|||
|
||||
export const selectSearchUrisByQuery: (state: State) => { [string]: Array<string> } = createSelector(
|
||||
selectState,
|
||||
(state) => state.urisByQuery
|
||||
(state) => state.resultsByQuery
|
||||
);
|
||||
|
||||
export const selectHasReachedMaxResultsLength: (state: State) => { [boolean]: Array<boolean> } = createSelector(
|
||||
|
@ -42,9 +43,9 @@ export const makeSelectSearchUris = (query: string): ((state: State) => Array<st
|
|||
if (query) {
|
||||
query = query.replace(/^lbry:\/\//i, '').replace(/\//, ' ');
|
||||
const normalizedQuery = createNormalizedSearchKey(query);
|
||||
return byQuery[normalizedQuery];
|
||||
return byQuery[normalizedQuery] && byQuery[normalizedQuery]['uris'];
|
||||
}
|
||||
return byQuery[query];
|
||||
return byQuery[query] && byQuery[query]['uris'];
|
||||
});
|
||||
|
||||
export const makeSelectHasReachedMaxResultsLength = (query: string): ((state: State) => boolean) =>
|
||||
|
@ -84,16 +85,47 @@ export const makeSelectRecommendedContentForUri = (uri: string) =>
|
|||
const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options);
|
||||
const normalizedSearchQuery = createNormalizedSearchKey(searchQuery);
|
||||
|
||||
let searchUris = searchUrisByQuery[normalizedSearchQuery];
|
||||
if (searchUris) {
|
||||
searchUris = searchUris.filter((searchUri) => searchUri !== currentUri);
|
||||
recommendedContent = searchUris;
|
||||
let searchResult = searchUrisByQuery[normalizedSearchQuery];
|
||||
if (searchResult) {
|
||||
recommendedContent = searchResult['uris'].filter((searchUri) => searchUri !== currentUri);
|
||||
}
|
||||
}
|
||||
return recommendedContent;
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectRecommendedRecsysIdForClaimId = (claimId: string) =>
|
||||
createSelector(makeSelectClaimForClaimId(claimId), selectSearchUrisByQuery, (claim, searchUrisByQuery) => {
|
||||
// TODO: DRY this out.
|
||||
let poweredBy;
|
||||
if (claim) {
|
||||
const isMature = isClaimNsfw(claim);
|
||||
const { title } = claim.value;
|
||||
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options: {
|
||||
related_to?: string,
|
||||
nsfw?: boolean,
|
||||
isBackgroundSearch?: boolean,
|
||||
} = { related_to: claim.claim_id, isBackgroundSearch: true };
|
||||
|
||||
options['nsfw'] = isMature;
|
||||
const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options);
|
||||
const normalizedSearchQuery = createNormalizedSearchKey(searchQuery);
|
||||
|
||||
let searchResult = searchUrisByQuery[normalizedSearchQuery];
|
||||
if (searchResult) {
|
||||
poweredBy = searchResult.recsys;
|
||||
} else {
|
||||
return normalizedSearchQuery;
|
||||
}
|
||||
}
|
||||
return poweredBy;
|
||||
});
|
||||
|
||||
export const makeSelectWinningUriForQuery = (query: string) => {
|
||||
const uriFromQuery = `lbry://${query}`;
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
// @flow
|
||||
export default function handleFetchResponse(response: Response): Promise<any> {
|
||||
return response.status === 200 ? Promise.resolve(response.json()) : Promise.reject(new Error(response.statusText));
|
||||
const headers = response.headers;
|
||||
const poweredBy = headers.get('x-powered-by');
|
||||
|
||||
return response.status === 200
|
||||
? response.json().then((body) => ({ body, poweredBy }))
|
||||
: Promise.reject(new Error(response.statusText));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue