UNPKG

rsshub

Version:
147 lines (133 loc) 5.09 kB
import { Route, ViewType } from '@/types'; import cache from '@/utils/cache'; import { ig, login } from './utils'; import logger from '@/utils/logger'; import { config } from '@/config'; import { renderItems } from '../common-utils'; import InvalidParameterError from '@/errors/types/invalid-parameter'; // loadContent pulls the desired user/tag/etc async function loadContent(category, nameOrId, tryGet) { let feedTitle, feedLink, feedDescription, feedLogo; let itemsRaw; switch (category) { case 'user': { let userInfo, username, id; if (Number.isNaN(nameOrId)) { username = nameOrId; id = await tryGet(`instagram:getIdByUsername:${username}`, () => ig.user.getIdByUsername(username), 31_536_000); // 1 year since it will never change userInfo = await tryGet(`instagram:userInfo:${id}`, () => ig.user.info(id)); } else { id = nameOrId; userInfo = await tryGet(`instagram:userInfo:${id}`, () => ig.user.info(id)); username = userInfo.username; } feedDescription = userInfo.biography; // exists in web api ?? exist in private api ?? exist in both feedLogo = userInfo.profile_pic_url_hd ?? userInfo.hd_profile_pic_url_info?.url ?? userInfo.profile_pic_url; const fullName = userInfo.full_name; feedTitle = `${fullName} (@${username}) - Instagram`; feedLink = `https://www.instagram.com/${username}`; itemsRaw = await tryGet(`instagram:feed:${id}`, () => ig.feed.user(id).items(), config.cache.routeExpire, false); break; } case 'tags': { const tag = nameOrId; feedTitle = `#${tag} - Instagram`; feedLink = `https://www.instagram.com/explore/tags/${tag}`; itemsRaw = await tryGet(`instagram:tags:${tag}`, () => ig.feed.tags(tag, 'recent').items(), config.cache.routeExpire, false); break; } default: break; } return { feedTitle, feedLink, feedDescription, feedLogo, itemsRaw, }; } export const route: Route = { path: '/:category/:key', categories: ['social-media'], view: ViewType.SocialMedia, example: '/instagram/user/stefaniejoosten', parameters: { category: { description: 'Feed category', default: 'user', options: [ { label: 'User', value: 'user', }, { label: 'Tags', value: 'tags', }, ], }, key: 'Username / Hashtag name', }, features: { requireConfig: [ { name: 'IG_PROXY', optional: true, description: '', }, { name: 'IG_USERNAME', description: 'Instagram username', }, { name: 'IG_PASSWORD', description: 'Instagram password, due to [Instagram Private API](https://github.com/dilame/instagram-private-api) restrictions, you have to setup your credentials on the server. 2FA is not supported.', }, ], requirePuppeteer: false, antiCrawler: true, supportBT: false, supportPodcast: false, supportScihub: false, }, name: 'User Profile / Hashtag - Private API', maintainers: ['oppilate', 'DIYgod'], handler, }; async function handler(ctx) { // https://github.com/dilame/instagram-private-api#feeds // const availableCategories = ["accountFollowers", "accountFollowing", "news", // "discover", "pendingFriendships", "blockedUsers", "directInbox", "directPending", // "directThread", "user", "tag", "location", "mediaComments", "reelsMedia", "reelsTray", // "timeline", "musicTrending", "musicSearch", "musicGenre", "musicMood", "usertags", "saved"]; const availableCategories = ['user', 'tags']; // Unique key for a feed category // e.g. username for user feed const { category, key } = ctx.req.param(); if (!availableCategories.includes(category)) { throw new InvalidParameterError('Such feed is not supported.'); } if (config.instagram && config.instagram.proxy) { ig.state.proxyUrl = config.instagram.proxy; } await login(ig, cache); let data; try { data = await loadContent(category, key, cache.tryGet); } catch (error) { logger.error(`Instagram error: ${error}`); throw error; } return { title: data.feedTitle, link: data.feedLink, description: data.feedDescription, item: renderItems(data.itemsRaw), icon: 'https://www.instagram.com/static/images/ico/xxhdpi_launcher.png/99cf3909d459.png', logo: data.feedLogo, image: data.feedLogo, allowEmpty: true, }; }