]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/account/account-follow.ts
Fix update host script
[github/Chocobozzz/PeerTube.git] / server / models / account / account-follow.ts
CommitLineData
7a7724e6 1import { values } from 'lodash'
e4f97bab
C
2import * as Sequelize from 'sequelize'
3
51548b31 4import { addMethodsToModel, getSort } from '../utils'
7a7724e6
C
5import { AccountFollowAttributes, AccountFollowInstance, AccountFollowMethods } from './account-follow-interface'
6import { FOLLOW_STATES } from '../../initializers/constants'
e4f97bab
C
7
8let AccountFollow: Sequelize.Model<AccountFollowInstance, AccountFollowAttributes>
7a7724e6 9let loadByAccountAndTarget: AccountFollowMethods.LoadByAccountAndTarget
51548b31
C
10let listFollowingForApi: AccountFollowMethods.ListFollowingForApi
11let listFollowersForApi: AccountFollowMethods.ListFollowersForApi
12let listAcceptedFollowerUrlsForApi: AccountFollowMethods.ListAcceptedFollowerUrlsForApi
13let listAcceptedFollowingUrlsForApi: AccountFollowMethods.ListAcceptedFollowingUrlsForApi
efc32059 14let listAcceptedFollowerSharedInboxUrls: AccountFollowMethods.ListAcceptedFollowerSharedInboxUrls
e4f97bab
C
15
16export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
17 AccountFollow = sequelize.define<AccountFollowInstance, AccountFollowAttributes>('AccountFollow',
7a7724e6
C
18 {
19 state: {
20 type: DataTypes.ENUM(values(FOLLOW_STATES)),
21 allowNull: false
22 }
23 },
e4f97bab
C
24 {
25 indexes: [
26 {
350e31d6
C
27 fields: [ 'accountId' ]
28 },
29 {
30 fields: [ 'targetAccountId' ]
e4f97bab
C
31 },
32 {
350e31d6 33 fields: [ 'accountId', 'targetAccountId' ],
e4f97bab
C
34 unique: true
35 }
36 ]
37 }
38 )
39
40 const classMethods = [
350e31d6 41 associate,
51548b31
C
42 loadByAccountAndTarget,
43 listFollowingForApi,
44 listFollowersForApi,
45 listAcceptedFollowerUrlsForApi,
efc32059
C
46 listAcceptedFollowingUrlsForApi,
47 listAcceptedFollowerSharedInboxUrls
e4f97bab
C
48 ]
49 addMethodsToModel(AccountFollow, classMethods)
50
51 return AccountFollow
52}
53
54// ------------------------------ STATICS ------------------------------
55
56function associate (models) {
57 AccountFollow.belongsTo(models.Account, {
58 foreignKey: {
59 name: 'accountId',
60 allowNull: false
61 },
51548b31 62 as: 'AccountFollower',
e4f97bab
C
63 onDelete: 'CASCADE'
64 })
65
66 AccountFollow.belongsTo(models.Account, {
67 foreignKey: {
68 name: 'targetAccountId',
69 allowNull: false
70 },
51548b31 71 as: 'AccountFollowing',
e4f97bab
C
72 onDelete: 'CASCADE'
73 })
74}
7a7724e6
C
75
76loadByAccountAndTarget = function (accountId: number, targetAccountId: number) {
77 const query = {
78 where: {
79 accountId,
80 targetAccountId
81 }
82 }
83
84 return AccountFollow.findOne(query)
85}
51548b31
C
86
87listFollowingForApi = function (id: number, start: number, count: number, sort: string) {
88 const query = {
89 distinct: true,
90 offset: start,
91 limit: count,
92 order: [ getSort(sort) ],
93 include: [
94 {
95 model: AccountFollow[ 'sequelize' ].models.Account,
96 required: true,
97 as: 'AccountFollower',
98 where: {
99 id
100 }
101 },
102 {
103 model: AccountFollow['sequelize'].models.Account,
104 as: 'AccountFollowing',
105 required: true,
60862425 106 include: [ AccountFollow['sequelize'].models.Server ]
51548b31
C
107 }
108 ]
109 }
110
111 return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
112 return {
113 data: rows.map(r => r.AccountFollowing),
114 total: count
115 }
116 })
117}
118
119listFollowersForApi = function (id: number, start: number, count: number, sort: string) {
120 const query = {
121 distinct: true,
122 offset: start,
123 limit: count,
124 order: [ getSort(sort) ],
125 include: [
126 {
127 model: AccountFollow[ 'sequelize' ].models.Account,
128 required: true,
129 as: 'AccountFollower',
60862425 130 include: [ AccountFollow['sequelize'].models.Server ]
51548b31
C
131 },
132 {
133 model: AccountFollow['sequelize'].models.Account,
134 as: 'AccountFollowing',
135 required: true,
136 where: {
137 id
138 }
139 }
140 ]
141 }
142
143 return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
144 return {
145 data: rows.map(r => r.AccountFollower),
146 total: count
147 }
148 })
149}
150
efc32059
C
151listAcceptedFollowerUrlsForApi = function (accountIds: number[], start?: number, count?: number) {
152 return createListAcceptedFollowForApiQuery('followers', accountIds, start, count)
51548b31
C
153}
154
efc32059
C
155listAcceptedFollowerSharedInboxUrls = function (accountIds: number[]) {
156 return createListAcceptedFollowForApiQuery('followers', accountIds, undefined, undefined, 'sharedInboxUrl')
157}
158
159listAcceptedFollowingUrlsForApi = function (accountIds: number[], start?: number, count?: number) {
160 return createListAcceptedFollowForApiQuery('following', accountIds, start, count)
51548b31
C
161}
162
163// ------------------------------ UTILS ------------------------------
164
efc32059
C
165async function createListAcceptedFollowForApiQuery (
166 type: 'followers' | 'following',
167 accountIds: number[],
168 start?: number,
169 count?: number,
170 columnUrl = 'url'
171) {
51548b31
C
172 let firstJoin: string
173 let secondJoin: string
174
175 if (type === 'followers') {
176 firstJoin = 'targetAccountId'
177 secondJoin = 'accountId'
178 } else {
179 firstJoin = 'accountId'
180 secondJoin = 'targetAccountId'
181 }
182
efc32059 183 const selections = [ '"Follows"."' + columnUrl + '" AS "url"', 'COUNT(*) AS "total"' ]
51548b31
C
184 const tasks: Promise<any>[] = []
185
186 for (const selection of selections) {
8e10cf1a
C
187 let query = 'SELECT ' + selection + ' FROM "Accounts" ' +
188 'INNER JOIN "AccountFollows" ON "AccountFollows"."' + firstJoin + '" = "Accounts"."id" ' +
189 'INNER JOIN "Accounts" AS "Follows" ON "AccountFollows"."' + secondJoin + '" = "Follows"."id" ' +
d7d5611c 190 'WHERE "Accounts"."id" = ANY ($accountIds) AND "AccountFollows"."state" = \'accepted\' '
51548b31 191
8e10cf1a 192 if (start !== undefined) query += 'LIMIT ' + start
51548b31
C
193 if (count !== undefined) query += ', ' + count
194
195 const options = {
d7d5611c 196 bind: { accountIds },
51548b31
C
197 type: Sequelize.QueryTypes.SELECT
198 }
199 tasks.push(AccountFollow['sequelize'].query(query, options))
200 }
201
202 const [ followers, [ { total } ]] = await Promise.all(tasks)
203 const urls: string[] = followers.map(f => f.url)
204
205 return {
206 data: urls,
207 total: parseInt(total, 10)
208 }
209}