refs #982 Add proxy configuration for all requests from main

This commit is contained in:
AkiraFukushima 2019-10-27 17:22:44 +09:00
parent 296ec5c6c2
commit a47fbbcf6a
6 changed files with 81 additions and 37 deletions

View File

@ -1,5 +1,5 @@
import { isEmpty } from 'lodash'
import Mastodon, { Account as RemoteAccount } from 'megalodon'
import Mastodon, { Account as RemoteAccount, ProxyConfig } from 'megalodon'
import Datastore from 'nedb'
import log from 'electron-log'
import { LocalAccount } from '~/src/types/localAccount'
@ -275,14 +275,14 @@ export default class Account {
return updated
}
async refreshAccounts(): Promise<Array<LocalAccount>> {
async refreshAccounts(proxy: ProxyConfig | false): Promise<Array<LocalAccount>> {
const accounts = await this.listAccounts()
if (accounts.length < 1) {
return accounts
}
const results = await Promise.all(
accounts.map(async account => {
const refresh = await this.refresh(account)
const refresh = await this.refresh(account, proxy)
return refresh
})
)
@ -294,8 +294,8 @@ export default class Account {
* @param {LocalAccount} account is an local account
* @return {LocalAccount} updated account
*/
async refresh(account: LocalAccount): Promise<LocalAccount> {
let client = new Mastodon(account.accessToken!, account.baseURL + '/api/v1')
async refresh(account: LocalAccount, proxy: ProxyConfig | false): Promise<LocalAccount> {
let client = new Mastodon(account.accessToken!, account.baseURL + '/api/v1', 'Whalebird', proxy)
let json = {}
try {
const res = await client.get<RemoteAccount>('/accounts/verify_credentials')
@ -311,8 +311,8 @@ export default class Account {
if (!account.refreshToken) {
throw new RefreshTokenDoesNotExist()
}
const token = await Mastodon.refreshToken(account.clientId, account.clientSecret, account.refreshToken, account.baseURL)
client = new Mastodon(token.access_token, account.baseURL + '/api/v1')
const token = await Mastodon.refreshToken(account.clientId, account.clientSecret, account.refreshToken, account.baseURL, proxy)
client = new Mastodon(token.access_token, account.baseURL + '/api/v1', 'Whalebird', proxy)
const res = await client.get<RemoteAccount>('/accounts/verify_credentials')
json = {
username: res.data.username,
@ -326,8 +326,8 @@ export default class Account {
}
// Confirm the access token, and check duplicate
async fetchAccount(account: LocalAccount, accessToken: string): Promise<RemoteAccount> {
const client = new Mastodon(accessToken, account.baseURL + '/api/v1')
async fetchAccount(account: LocalAccount, accessToken: string, proxy: ProxyConfig | false): Promise<RemoteAccount> {
const client = new Mastodon(accessToken, account.baseURL + '/api/v1', 'Whalebird', proxy)
const res = await client.get<RemoteAccount>('/accounts/verify_credentials')
const query = {
baseURL: account.baseURL,

View File

@ -1,4 +1,4 @@
import Mastodon, { OAuth } from 'megalodon'
import Mastodon, { OAuth, ProxyConfig } from 'megalodon'
import Account from './account'
import { LocalAccount } from '~/src/types/localAccount'
@ -30,7 +30,7 @@ export default class Authentication {
this.clientSecret = ''
}
async getAuthorizationUrl(domain = 'mastodon.social'): Promise<string> {
async getAuthorizationUrl(domain = 'mastodon.social', proxy: ProxyConfig | false): Promise<string> {
this.setOtherInstance(domain)
const res = await Mastodon.registerApp(
appName,
@ -38,7 +38,8 @@ export default class Authentication {
scopes: scope,
website: appURL
},
this.baseURL
this.baseURL,
proxy
)
this.clientId = res.clientId
this.clientSecret = res.clientSecret
@ -69,8 +70,15 @@ export default class Authentication {
return res.url
}
async getAccessToken(code: string): Promise<string> {
const tokenData: OAuth.TokenData = await Mastodon.fetchAccessToken(this.clientId, this.clientSecret, code, this.baseURL)
async getAccessToken(code: string, proxy: ProxyConfig | false): Promise<string> {
const tokenData: OAuth.TokenData = await Mastodon.fetchAccessToken(
this.clientId,
this.clientSecret,
code,
this.baseURL,
'urn:ietf:wg:oauth:2.0:oob',
proxy
)
const search = {
baseURL: this.baseURL,
domain: this.domain,
@ -80,7 +88,7 @@ export default class Authentication {
const rec = await this.db.searchAccount(search)
const accessToken = tokenData.accessToken
const refreshToken = tokenData.refreshToken
const data = await this.db.fetchAccount(rec, accessToken)
const data = await this.db.fetchAccount(rec, accessToken, proxy)
await this.db.updateAccount(rec._id!, {
username: data.username,
accountId: data.id,

View File

@ -349,9 +349,10 @@ app.on('activate', () => {
let auth = new Authentication(accountManager)
ipcMain.on('get-auth-url', (event: IpcMainEvent, domain: string) => {
ipcMain.on('get-auth-url', async (event: IpcMainEvent, domain: string) => {
const proxy = await proxyConfiguration.forMastodon()
auth
.getAuthorizationUrl(domain)
.getAuthorizationUrl(domain, proxy)
.then(url => {
log.debug(url)
event.sender.send('response-get-auth-url', url)
@ -364,9 +365,10 @@ ipcMain.on('get-auth-url', (event: IpcMainEvent, domain: string) => {
})
})
ipcMain.on('get-access-token', (event: IpcMainEvent, code: string) => {
ipcMain.on('get-access-token', async (event: IpcMainEvent, code: string) => {
const proxy = await proxyConfiguration.forMastodon()
auth
.getAccessToken(code)
.getAccessToken(code, proxy)
.then(token => {
accountDB.findOne(
{
@ -419,9 +421,10 @@ ipcMain.on('get-local-account', (event: IpcMainEvent, id: string) => {
})
})
ipcMain.on('update-account', (event: IpcMainEvent, acct: LocalAccount) => {
ipcMain.on('update-account', async (event: IpcMainEvent, acct: LocalAccount) => {
const proxy = await proxyConfiguration.forMastodon()
accountManager
.refresh(acct)
.refresh(acct, proxy)
.then(ac => {
event.sender.send('response-update-account', ac)
})
@ -465,9 +468,10 @@ ipcMain.on('backward-account', (event: IpcMainEvent, acct: LocalAccount) => {
})
})
ipcMain.on('refresh-accounts', (event: IpcMainEvent) => {
ipcMain.on('refresh-accounts', async (event: IpcMainEvent) => {
const proxy = await proxyConfiguration.forMastodon()
accountManager
.refreshAccounts()
.refreshAccounts(proxy)
.then(accounts => {
event.sender.send('response-refresh-accounts', accounts)
})
@ -523,7 +527,8 @@ ipcMain.on('start-all-user-streamings', (event: IpcMainEvent, accounts: Array<Lo
userStreamings[id]!.stop()
userStreamings[id] = null
}
const url = await StreamingURL(acct)
const proxy = await proxyConfiguration.forMastodon()
const url = await StreamingURL(acct, proxy)
userStreamings[id] = new WebSocket(acct, url)
userStreamings[id]!.startUserStreaming(
async (update: Status) => {
@ -633,8 +638,8 @@ ipcMain.on('start-directmessages-streaming', async (event: IpcMainEvent, obj: St
directMessagesStreaming.stop()
directMessagesStreaming = null
}
const url = await StreamingURL(acct)
const proxy = await proxyConfiguration.forMastodon()
const url = await StreamingURL(acct, proxy)
directMessagesStreaming = new WebSocket(acct, url)
directMessagesStreaming.start(
'direct',
@ -682,8 +687,8 @@ ipcMain.on('start-local-streaming', async (event: IpcMainEvent, obj: StreamingSe
localStreaming.stop()
localStreaming = null
}
const url = await StreamingURL(acct)
const proxy = await proxyConfiguration.forMastodon()
const url = await StreamingURL(acct, proxy)
localStreaming = new WebSocket(acct, url)
localStreaming.start(
'public:local',
@ -731,8 +736,8 @@ ipcMain.on('start-public-streaming', async (event: IpcMainEvent, obj: StreamingS
publicStreaming.stop()
publicStreaming = null
}
const url = await StreamingURL(acct)
const proxy = await proxyConfiguration.forMastodon()
const url = await StreamingURL(acct, proxy)
publicStreaming = new WebSocket(acct, url)
publicStreaming.start(
'public',
@ -784,8 +789,8 @@ ipcMain.on('start-list-streaming', async (event: IpcMainEvent, obj: ListID & Str
listStreaming.stop()
listStreaming = null
}
const url = await StreamingURL(acct)
const proxy = await proxyConfiguration.forMastodon()
const url = await StreamingURL(acct, proxy)
listStreaming = new WebSocket(acct, url)
listStreaming.start(
`list&list=${listID}`,
@ -837,8 +842,8 @@ ipcMain.on('start-tag-streaming', async (event: IpcMainEvent, obj: Tag & Streami
tagStreaming.stop()
tagStreaming = null
}
const url = await StreamingURL(acct)
const proxy = await proxyConfiguration.forMastodon()
const url = await StreamingURL(acct, proxy)
tagStreaming = new WebSocket(acct, url)
tagStreaming.start(
`hashtag&tag=${tag}`,

View File

@ -1,3 +1,4 @@
import { ProxyConfig } from 'megalodon'
import { ProxySource, ManualProxy, ProxyProtocol } from '~/src/types/proxy'
import Preferences from './preferences'
@ -13,6 +14,35 @@ export default class ProxyConfiguration {
this.systemProxy = proxy
}
public async forMastodon(): Promise<false | ProxyConfig> {
const proxy = await this.getConfig()
if (!proxy) {
return false
} else {
let protocol = ProxyProtocol.http
if (proxy.protocol !== '') {
protocol = proxy.protocol
}
if (proxy.username.length > 0) {
return {
host: proxy.host,
port: parseInt(proxy.port, 10),
protocol: protocol,
auth: {
username: proxy.username,
password: proxy.password
}
}
} else {
return {
host: proxy.host,
port: parseInt(proxy.port, 10),
protocol: protocol
}
}
}
}
public async getConfig(): Promise<false | ManualProxy> {
const conf = await this.preferences.get()
const source = conf.proxy.source as ProxySource

View File

@ -1,12 +1,12 @@
import Mastodon, { WebSocket as SocketListener, Status, Notification, Instance, Response } from 'megalodon'
import Mastodon, { WebSocket as SocketListener, Status, Notification, Instance, Response, ProxyConfig } from 'megalodon'
import log from 'electron-log'
import { LocalAccount } from '~/src/types/localAccount'
const StreamingURL = async (account: LocalAccount): Promise<string> => {
const StreamingURL = async (account: LocalAccount, proxy: ProxyConfig | false): Promise<string> => {
if (!account.accessToken) {
throw new Error('access token is empty')
}
const client = new Mastodon(account.accessToken, account.baseURL + '/api/v1')
const client = new Mastodon(account.accessToken, account.baseURL + '/api/v1', 'Whalebird', proxy)
const res: Response<Instance> = await client.get<Instance>('/instance')
return res.data.urls.streaming_api
}

View File

@ -102,6 +102,7 @@ const mutations: MutationTree<AppState> = {
state.hideAllAttachments = hideAllAttachments
},
[MUTATION_TYPES.UPDATE_PROXY_CONFIGURATION]: (state, proxy: ManualProxy | false) => {
// TODO: use src/main/proxy.ts#forMastodon
if (!proxy) {
state.proxyConfiguration = false
} else {