mirror of
https://github.com/yang991178/fluent-reader.git
synced 2025-02-26 16:37:46 +01:00
require api key for inoreader
This commit is contained in:
parent
a2087cec7a
commit
f794816469
@ -64,6 +64,7 @@ class GReaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReaderC
|
|||||||
endpoint: this.state.endpoint,
|
endpoint: this.state.endpoint,
|
||||||
fetchLimit: this.state.fetchLimit
|
fetchLimit: this.state.fetchLimit
|
||||||
} as GReaderConfigs
|
} as GReaderConfigs
|
||||||
|
if (this.state.password) configs.password = this.state.password
|
||||||
} else {
|
} else {
|
||||||
configs = {
|
configs = {
|
||||||
type: SyncService.GReader,
|
type: SyncService.GReader,
|
||||||
|
@ -4,7 +4,7 @@ import { ServiceConfigsTabProps } from "../service"
|
|||||||
import { GReaderConfigs } from "../../../scripts/models/services/greader"
|
import { GReaderConfigs } from "../../../scripts/models/services/greader"
|
||||||
import { SyncService } from "../../../schema-types"
|
import { SyncService } from "../../../schema-types"
|
||||||
import { Stack, Label, TextField, PrimaryButton, DefaultButton, Checkbox,
|
import { Stack, Label, TextField, PrimaryButton, DefaultButton, Checkbox,
|
||||||
MessageBar, MessageBarType, Dropdown, IDropdownOption, MessageBarButton } from "@fluentui/react"
|
MessageBar, MessageBarType, Dropdown, IDropdownOption, MessageBarButton, Link } from "@fluentui/react"
|
||||||
import DangerButton from "../../utils/danger-button"
|
import DangerButton from "../../utils/danger-button"
|
||||||
|
|
||||||
type GReaderConfigsTabState = {
|
type GReaderConfigsTabState = {
|
||||||
@ -12,8 +12,10 @@ type GReaderConfigsTabState = {
|
|||||||
endpoint: string
|
endpoint: string
|
||||||
username: string
|
username: string
|
||||||
password: string
|
password: string
|
||||||
|
apiId: string
|
||||||
|
apiKey: string
|
||||||
|
removeAd: boolean
|
||||||
fetchLimit: number
|
fetchLimit: number
|
||||||
importGroups: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const endpointOptions: IDropdownOption[] = [
|
const endpointOptions: IDropdownOption[] = [
|
||||||
@ -33,8 +35,10 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
endpoint: configs.endpoint || "https://www.inoreader.com",
|
endpoint: configs.endpoint || "https://www.inoreader.com",
|
||||||
username: configs.username || "",
|
username: configs.username || "",
|
||||||
password: "",
|
password: "",
|
||||||
|
apiId: configs.inoreaderId || "",
|
||||||
|
apiKey: configs.inoreaderKey || "",
|
||||||
|
removeAd: configs.removeInoreaderAd === undefined ? true : configs.removeInoreaderAd,
|
||||||
fetchLimit: configs.fetchLimit || 250,
|
fetchLimit: configs.fetchLimit || 250,
|
||||||
importGroups: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +66,8 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
}
|
}
|
||||||
|
|
||||||
validateForm = () => {
|
validateForm = () => {
|
||||||
return this.state.existing || (this.state.username && this.state.password)
|
return (this.state.existing || (this.state.username && this.state.password))
|
||||||
|
&& this.state.apiId && this.state.apiKey
|
||||||
}
|
}
|
||||||
|
|
||||||
save = async () => {
|
save = async () => {
|
||||||
@ -71,18 +76,25 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
configs = {
|
configs = {
|
||||||
...this.props.configs,
|
...this.props.configs,
|
||||||
endpoint: this.state.endpoint,
|
endpoint: this.state.endpoint,
|
||||||
fetchLimit: this.state.fetchLimit
|
fetchLimit: this.state.fetchLimit,
|
||||||
|
inoreaderId: this.state.apiId,
|
||||||
|
inoreaderKey: this.state.apiKey,
|
||||||
|
removeInoreaderAd: this.state.removeAd,
|
||||||
} as GReaderConfigs
|
} as GReaderConfigs
|
||||||
|
if (this.state.password) configs.password = this.state.password
|
||||||
} else {
|
} else {
|
||||||
configs = {
|
configs = {
|
||||||
type: SyncService.Inoreader,
|
type: SyncService.Inoreader,
|
||||||
endpoint: this.state.endpoint,
|
endpoint: this.state.endpoint,
|
||||||
username: this.state.username,
|
username: this.state.username,
|
||||||
password: this.state.password,
|
password: this.state.password,
|
||||||
|
inoreaderId: this.state.apiId,
|
||||||
|
inoreaderKey: this.state.apiKey,
|
||||||
|
removeInoreaderAd: this.state.removeAd,
|
||||||
fetchLimit: this.state.fetchLimit,
|
fetchLimit: this.state.fetchLimit,
|
||||||
|
importGroups: true,
|
||||||
useInt64: true
|
useInt64: true
|
||||||
}
|
}
|
||||||
if (this.state.importGroups) configs.importGroups = true
|
|
||||||
}
|
}
|
||||||
this.props.blockActions()
|
this.props.blockActions()
|
||||||
configs = await this.props.reauthenticate(configs) as GReaderConfigs
|
configs = await this.props.reauthenticate(configs) as GReaderConfigs
|
||||||
@ -97,6 +109,8 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createKey = () => window.utils.openExternal(this.state.endpoint + "/all_articles#preferences-developer")
|
||||||
|
|
||||||
remove = async () => {
|
remove = async () => {
|
||||||
this.props.exit()
|
this.props.exit()
|
||||||
await this.props.remove()
|
await this.props.remove()
|
||||||
@ -106,8 +120,9 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
return <>
|
return <>
|
||||||
<MessageBar messageBarType={MessageBarType.severeWarning}
|
<MessageBar messageBarType={MessageBarType.severeWarning}
|
||||||
isMultiline={false}
|
isMultiline={false}
|
||||||
actions={<MessageBarButton text={intl.get("rules.help")} onClick={openSupport} />}>
|
actions={<MessageBarButton text={intl.get("create")} onClick={this.createKey} />}>
|
||||||
{intl.get("service.rateLimitWarning")}
|
{intl.get("service.rateLimitWarning")}
|
||||||
|
<Link onClick={openSupport} style={{marginLeft: 6}}>{intl.get("rules.help")}</Link>
|
||||||
</MessageBar>
|
</MessageBar>
|
||||||
{!this.state.existing && (
|
{!this.state.existing && (
|
||||||
<MessageBar messageBarType={MessageBarType.warning}>{intl.get("service.overwriteWarning")}</MessageBar>
|
<MessageBar messageBarType={MessageBarType.warning}>{intl.get("service.overwriteWarning")}</MessageBar>
|
||||||
@ -155,6 +170,32 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
onChange={this.handleInputChange} />
|
onChange={this.handleInputChange} />
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Stack className="login-form" horizontal>
|
||||||
|
<Stack.Item>
|
||||||
|
<Label>API ID</Label>
|
||||||
|
</Stack.Item>
|
||||||
|
<Stack.Item grow>
|
||||||
|
<TextField
|
||||||
|
onGetErrorMessage={this.checkNotEmpty}
|
||||||
|
validateOnLoad={false}
|
||||||
|
name="apiId"
|
||||||
|
value={this.state.apiId}
|
||||||
|
onChange={this.handleInputChange} />
|
||||||
|
</Stack.Item>
|
||||||
|
</Stack>
|
||||||
|
<Stack className="login-form" horizontal>
|
||||||
|
<Stack.Item>
|
||||||
|
<Label>API Key</Label>
|
||||||
|
</Stack.Item>
|
||||||
|
<Stack.Item grow>
|
||||||
|
<TextField
|
||||||
|
onGetErrorMessage={this.checkNotEmpty}
|
||||||
|
validateOnLoad={false}
|
||||||
|
name="apiKey"
|
||||||
|
value={this.state.apiKey}
|
||||||
|
onChange={this.handleInputChange} />
|
||||||
|
</Stack.Item>
|
||||||
|
</Stack>
|
||||||
<Stack className="login-form" horizontal>
|
<Stack className="login-form" horizontal>
|
||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
<Label>{intl.get("service.fetchLimit")}</Label>
|
<Label>{intl.get("service.fetchLimit")}</Label>
|
||||||
@ -166,10 +207,10 @@ class InoreaderConfigsTab extends React.Component<ServiceConfigsTabProps, GReade
|
|||||||
onChange={this.onFetchLimitOptionChange} />
|
onChange={this.onFetchLimitOptionChange} />
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
</Stack>
|
</Stack>
|
||||||
{!this.state.existing && <Checkbox
|
<Checkbox
|
||||||
label={intl.get("service.importGroups")}
|
label={intl.get("service.removeAd")}
|
||||||
checked={this.state.importGroups}
|
checked={this.state.removeAd}
|
||||||
onChange={(_, c) => this.setState({importGroups: c})} />}
|
onChange={(_, c) => this.setState({removeAd: c})} />
|
||||||
<Stack horizontal style={{marginTop: 32}}>
|
<Stack horizontal style={{marginTop: 32}}>
|
||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
|
@ -191,7 +191,8 @@
|
|||||||
"suggest": "Suggest a new service",
|
"suggest": "Suggest a new service",
|
||||||
"overwriteWarning": "Local sources will be deleted if they exist in the service.",
|
"overwriteWarning": "Local sources will be deleted if they exist in the service.",
|
||||||
"groupsWarning": "Groups aren't automatically synced with the service.",
|
"groupsWarning": "Groups aren't automatically synced with the service.",
|
||||||
"rateLimitWarning": "If connection errors persist, the app may have been rate limited by the service.",
|
"rateLimitWarning": "To avoid rate limiting, you need to create your own API Key.",
|
||||||
|
"removeAd": "Remove Ad",
|
||||||
"endpoint": "Endpoint",
|
"endpoint": "Endpoint",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
|
@ -189,7 +189,8 @@
|
|||||||
"suggest": "建议一项新服务",
|
"suggest": "建议一项新服务",
|
||||||
"overwriteWarning": "若本地与服务端存在URL相同的订阅源,则本地订阅源将被删除",
|
"overwriteWarning": "若本地与服务端存在URL相同的订阅源,则本地订阅源将被删除",
|
||||||
"groupsWarning": "分组不会自动与服务端保持同步",
|
"groupsWarning": "分组不会自动与服务端保持同步",
|
||||||
"rateLimitWarning": "若反复出现错误,则原因可能是应用被服务限流",
|
"rateLimitWarning": "为避免限流,您需要新建自己的 API Key",
|
||||||
|
"removeAd": "移除广告",
|
||||||
"endpoint": "端点",
|
"endpoint": "端点",
|
||||||
"username": "用户名",
|
"username": "用户名",
|
||||||
"password": "密码",
|
"password": "密码",
|
||||||
|
@ -189,7 +189,8 @@
|
|||||||
"suggest": "建議一項新服務",
|
"suggest": "建議一項新服務",
|
||||||
"overwriteWarning": "若本地與服務端存在URL相同的訂閱源,則本地訂閱源將被刪除",
|
"overwriteWarning": "若本地與服務端存在URL相同的訂閱源,則本地訂閱源將被刪除",
|
||||||
"groupsWarning": "分組不會自動與服務端保持同步",
|
"groupsWarning": "分組不會自動與服務端保持同步",
|
||||||
"rateLimitWarning": "若反覆出現錯誤,則原因可能是應用被服務限流",
|
"rateLimitWarning": "為避免限流,您需要新建自己的 API Key",
|
||||||
|
"removeAd": "移除廣告",
|
||||||
"endpoint": "端點",
|
"endpoint": "端點",
|
||||||
"username": "使用者名稱",
|
"username": "使用者名稱",
|
||||||
"password": "密碼",
|
"password": "密碼",
|
||||||
|
@ -23,14 +23,22 @@ export interface GReaderConfigs extends ServiceConfigs {
|
|||||||
lastId?: string
|
lastId?: string
|
||||||
auth?: string
|
auth?: string
|
||||||
useInt64: boolean // The Old Reader uses ids longer than 64 bits
|
useInt64: boolean // The Old Reader uses ids longer than 64 bits
|
||||||
|
inoreaderId?: string
|
||||||
|
inoreaderKey?: string
|
||||||
|
removeInoreaderAd?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchAPI(configs: GReaderConfigs, params: string, method="GET", body:BodyInit=null) {
|
async function fetchAPI(configs: GReaderConfigs, params: string, method="GET", body:BodyInit=null) {
|
||||||
const headers = new Headers()
|
const headers = new Headers()
|
||||||
if (configs.auth !== null) headers.set("Authorization", configs.auth)
|
if (configs.auth !== null) headers.set("Authorization", configs.auth)
|
||||||
if (configs.type == SyncService.Inoreader) {
|
if (configs.type == SyncService.Inoreader) {
|
||||||
headers.set("AppId", "999999298")
|
if (configs.inoreaderId) {
|
||||||
headers.set("AppKey", "KPbKYXTfgrKbwmroOeYC7mcW21ZRwF5Y")
|
headers.set("AppId", configs.inoreaderId)
|
||||||
|
headers.set("AppKey", configs.inoreaderKey)
|
||||||
|
} else {
|
||||||
|
headers.set("AppId", "999999298")
|
||||||
|
headers.set("AppKey", "KPbKYXTfgrKbwmroOeYC7mcW21ZRwF5Y")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return await fetch(configs.endpoint + params, {
|
return await fetch(configs.endpoint + params, {
|
||||||
method: method,
|
method: method,
|
||||||
@ -189,13 +197,18 @@ export const gReaderServiceHooks: ServiceHooks = {
|
|||||||
const source = fidMap.get(i.origin.streamId)
|
const source = fidMap.get(i.origin.streamId)
|
||||||
if (source === undefined) return
|
if (source === undefined) return
|
||||||
const dom = domParser.parseFromString(i.summary.content, "text/html")
|
const dom = domParser.parseFromString(i.summary.content, "text/html")
|
||||||
|
if (configs.type == SyncService.Inoreader && configs.removeInoreaderAd !== false) {
|
||||||
|
if (dom.documentElement.textContent.trim().startsWith("Ads from Inoreader")) {
|
||||||
|
dom.body.firstChild.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
const item = {
|
const item = {
|
||||||
source: source.sid,
|
source: source.sid,
|
||||||
title: i.title,
|
title: i.title,
|
||||||
link: i.canonical[0].href,
|
link: i.canonical[0].href,
|
||||||
date: new Date(i.published * 1000),
|
date: new Date(i.published * 1000),
|
||||||
fetchedDate: new Date(parseInt(i.crawlTimeMsec)),
|
fetchedDate: new Date(parseInt(i.crawlTimeMsec)),
|
||||||
content: i.summary.content,
|
content: dom.body.innerHTML,
|
||||||
snippet: dom.documentElement.textContent.trim(),
|
snippet: dom.documentElement.textContent.trim(),
|
||||||
creator: i.author,
|
creator: i.author,
|
||||||
hasRead: false,
|
hasRead: false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user