aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/account/account-follow.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/account/account-follow.ts')
-rw-r--r--server/models/account/account-follow.ts130
1 files changed, 126 insertions, 4 deletions
diff --git a/server/models/account/account-follow.ts b/server/models/account/account-follow.ts
index 7c129ab9d..6d7592326 100644
--- a/server/models/account/account-follow.ts
+++ b/server/models/account/account-follow.ts
@@ -1,12 +1,16 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import * as Sequelize from 'sequelize' 2import * as Sequelize from 'sequelize'
3 3
4import { addMethodsToModel } from '../utils' 4import { addMethodsToModel, getSort } from '../utils'
5import { AccountFollowAttributes, AccountFollowInstance, AccountFollowMethods } from './account-follow-interface' 5import { AccountFollowAttributes, AccountFollowInstance, AccountFollowMethods } from './account-follow-interface'
6import { FOLLOW_STATES } from '../../initializers/constants' 6import { FOLLOW_STATES } from '../../initializers/constants'
7 7
8let AccountFollow: Sequelize.Model<AccountFollowInstance, AccountFollowAttributes> 8let AccountFollow: Sequelize.Model<AccountFollowInstance, AccountFollowAttributes>
9let loadByAccountAndTarget: AccountFollowMethods.LoadByAccountAndTarget 9let loadByAccountAndTarget: AccountFollowMethods.LoadByAccountAndTarget
10let listFollowingForApi: AccountFollowMethods.ListFollowingForApi
11let listFollowersForApi: AccountFollowMethods.ListFollowersForApi
12let listAcceptedFollowerUrlsForApi: AccountFollowMethods.ListAcceptedFollowerUrlsForApi
13let listAcceptedFollowingUrlsForApi: AccountFollowMethods.ListAcceptedFollowingUrlsForApi
10 14
11export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { 15export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
12 AccountFollow = sequelize.define<AccountFollowInstance, AccountFollowAttributes>('AccountFollow', 16 AccountFollow = sequelize.define<AccountFollowInstance, AccountFollowAttributes>('AccountFollow',
@@ -34,7 +38,11 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
34 38
35 const classMethods = [ 39 const classMethods = [
36 associate, 40 associate,
37 loadByAccountAndTarget 41 loadByAccountAndTarget,
42 listFollowingForApi,
43 listFollowersForApi,
44 listAcceptedFollowerUrlsForApi,
45 listAcceptedFollowingUrlsForApi
38 ] 46 ]
39 addMethodsToModel(AccountFollow, classMethods) 47 addMethodsToModel(AccountFollow, classMethods)
40 48
@@ -49,7 +57,7 @@ function associate (models) {
49 name: 'accountId', 57 name: 'accountId',
50 allowNull: false 58 allowNull: false
51 }, 59 },
52 as: 'accountFollowers', 60 as: 'AccountFollower',
53 onDelete: 'CASCADE' 61 onDelete: 'CASCADE'
54 }) 62 })
55 63
@@ -58,7 +66,7 @@ function associate (models) {
58 name: 'targetAccountId', 66 name: 'targetAccountId',
59 allowNull: false 67 allowNull: false
60 }, 68 },
61 as: 'accountFollowing', 69 as: 'AccountFollowing',
62 onDelete: 'CASCADE' 70 onDelete: 'CASCADE'
63 }) 71 })
64} 72}
@@ -73,3 +81,117 @@ loadByAccountAndTarget = function (accountId: number, targetAccountId: number) {
73 81
74 return AccountFollow.findOne(query) 82 return AccountFollow.findOne(query)
75} 83}
84
85listFollowingForApi = function (id: number, start: number, count: number, sort: string) {
86 const query = {
87 distinct: true,
88 offset: start,
89 limit: count,
90 order: [ getSort(sort) ],
91 include: [
92 {
93 model: AccountFollow[ 'sequelize' ].models.Account,
94 required: true,
95 as: 'AccountFollower',
96 where: {
97 id
98 }
99 },
100 {
101 model: AccountFollow['sequelize'].models.Account,
102 as: 'AccountFollowing',
103 required: true,
104 include: [ AccountFollow['sequelize'].models.Pod ]
105 }
106 ]
107 }
108
109 return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
110 return {
111 data: rows.map(r => r.AccountFollowing),
112 total: count
113 }
114 })
115}
116
117listFollowersForApi = function (id: number, start: number, count: number, sort: string) {
118 const query = {
119 distinct: true,
120 offset: start,
121 limit: count,
122 order: [ getSort(sort) ],
123 include: [
124 {
125 model: AccountFollow[ 'sequelize' ].models.Account,
126 required: true,
127 as: 'AccountFollower',
128 include: [ AccountFollow['sequelize'].models.Pod ]
129 },
130 {
131 model: AccountFollow['sequelize'].models.Account,
132 as: 'AccountFollowing',
133 required: true,
134 where: {
135 id
136 }
137 }
138 ]
139 }
140
141 return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
142 return {
143 data: rows.map(r => r.AccountFollower),
144 total: count
145 }
146 })
147}
148
149listAcceptedFollowerUrlsForApi = function (id: number, start: number, count?: number) {
150 return createListAcceptedFollowForApiQuery('followers', id, start, count)
151}
152
153listAcceptedFollowingUrlsForApi = function (id: number, start: number, count?: number) {
154 return createListAcceptedFollowForApiQuery('following', id, start, count)
155}
156
157// ------------------------------ UTILS ------------------------------
158
159async function createListAcceptedFollowForApiQuery (type: 'followers' | 'following', id: number, start: number, count?: number) {
160 let firstJoin: string
161 let secondJoin: string
162
163 if (type === 'followers') {
164 firstJoin = 'targetAccountId'
165 secondJoin = 'accountId'
166 } else {
167 firstJoin = 'accountId'
168 secondJoin = 'targetAccountId'
169 }
170
171 const selections = [ '"Followers"."url" AS "url"', 'COUNT(*) AS "total"' ]
172 const tasks: Promise<any>[] = []
173
174 for (const selection of selections) {
175 let query = 'SELECT ' + selection + ' FROM "Account" ' +
176 'INNER JOIN "AccountFollow" ON "AccountFollow"."' + firstJoin + '" = "Account"."id" ' +
177 'INNER JOIN "Account" AS "Follows" ON "Followers"."id" = "Follows"."' + secondJoin + '" ' +
178 'WHERE "Account"."id" = $id AND "AccountFollow"."state" = \'accepted\' ' +
179 'LIMIT ' + start
180
181 if (count !== undefined) query += ', ' + count
182
183 const options = {
184 bind: { id },
185 type: Sequelize.QueryTypes.SELECT
186 }
187 tasks.push(AccountFollow['sequelize'].query(query, options))
188 }
189
190 const [ followers, [ { total } ]] = await Promise.all(tasks)
191 const urls: string[] = followers.map(f => f.url)
192
193 return {
194 data: urls,
195 total: parseInt(total, 10)
196 }
197}