1
+ use itertools:: Itertools ;
1
2
use lazy_static:: lazy_static;
2
3
use std:: { collections:: HashSet , str:: FromStr } ;
3
4
4
- use crate :: { ChannelInfo , Day } ;
5
+ use crate :: { ChannelInfo , ChannelRemap , Day } ;
5
6
use ircjournal:: {
6
7
model:: { Message , ServerChannel } ,
7
8
Database ,
@@ -19,14 +20,16 @@ pub(crate) struct Paginated<U> {
19
20
pub ( crate ) page_count : i64 ,
20
21
}
21
22
22
- pub ( crate ) async fn channels ( db : & Database ) -> Vec < ServerChannel > {
23
+ pub ( crate ) async fn channels ( db : & Database , remap : & ChannelRemap ) -> Vec < ServerChannel > {
23
24
// language=sql
24
25
sqlx:: query!( r#"SELECT "channel" FROM all_channels()"# )
25
26
. fetch_all ( db)
26
27
. await
27
28
. unwrap_or_default ( )
28
29
. iter ( )
29
30
. filter_map ( |s| ServerChannel :: from_str ( s. channel . as_ref ( ) . unwrap ( ) ) . ok ( ) )
31
+ . map ( |sc| remap. canonical ( & sc) )
32
+ . unique ( )
30
33
. collect ( )
31
34
}
32
35
@@ -45,18 +48,19 @@ pub(crate) async fn channel_exists(db: &Database, sc: &ServerChannel) -> bool {
45
48
pub ( crate ) async fn channel_info (
46
49
db : & Database ,
47
50
sc : & ServerChannel ,
51
+ remap : & ChannelRemap ,
48
52
before : & Day ,
49
53
) -> Option < ChannelInfo > {
50
- let channel = sc . to_string ( ) ;
54
+ let channels = remap . aliases_str ( sc ) ;
51
55
// language=sql
52
56
sqlx:: query!( r#"
53
- WITH "ts" AS (SELECT min("timestamp") "first!", max("timestamp") "last!" FROM "message" WHERE "channel" = $1 )
57
+ WITH "ts" AS (SELECT min("timestamp") "first!", max("timestamp") "last!" FROM "message" WHERE "channel" = ANY($1) )
54
58
SELECT "first!", "last!", array(SELECT "nick" FROM all_nicks($1, $2)) "nicks!",
55
59
(SELECT row("message".*) FROM "message"
56
- WHERE "channel" = $1 AND "opcode" = 'topic' AND coalesce("payload", '') != '' AND "timestamp" < $3
60
+ WHERE "channel" = ANY($1) AND "opcode" = 'topic' AND coalesce("payload", '') != '' AND "timestamp" < $3
57
61
ORDER BY "timestamp" DESC LIMIT 1) "topic?:Message"
58
62
FROM "ts" GROUP BY 1, 2, 3 LIMIT 1
59
- "# , & channel , HARD_NICK_LIMIT as i64 , before. succ( ) . midnight( ) )
63
+ "# , & channels , HARD_NICK_LIMIT as i64 , before. succ( ) . midnight( ) )
60
64
. fetch_optional ( db)
61
65
. await
62
66
. unwrap ( )
@@ -72,18 +76,20 @@ pub(crate) async fn channel_info(
72
76
pub ( crate ) async fn messages_channel_day (
73
77
db : & Database ,
74
78
sc : & ServerChannel ,
79
+ remap : & ChannelRemap ,
75
80
day : & Day ,
76
81
) -> Vec < Message > {
82
+ let channels = remap. aliases_str ( sc) ;
77
83
// language=sql
78
84
sqlx:: query_as!(
79
85
Message ,
80
86
r#"
81
87
SELECT * FROM "message"
82
- WHERE "channel" = $1 AND "timestamp" >= $2 AND "timestamp" < $3
88
+ WHERE "channel" = ANY($1) AND "timestamp" >= $2 AND "timestamp" < $3
83
89
ORDER BY "timestamp"
84
90
LIMIT $4
85
91
"# ,
86
- sc . to_string ( ) ,
92
+ & channels ,
87
93
day. midnight( ) ,
88
94
day. succ( ) . midnight( ) ,
89
95
HARD_MESSAGE_LIMIT as i64
@@ -96,20 +102,22 @@ pub(crate) async fn messages_channel_day(
96
102
pub ( crate ) async fn channel_month_index (
97
103
db : & Database ,
98
104
sc : & ServerChannel ,
105
+ remap : & ChannelRemap ,
99
106
year : i32 ,
100
107
month : u32 ,
101
108
) -> HashSet < u32 > {
109
+ let channels = remap. aliases_str ( sc) ;
102
110
let from: Day = chrono:: NaiveDate :: from_ymd ( year, month, 1 ) . into ( ) ;
103
111
let to: Day = chrono:: NaiveDate :: from_ymd ( year + month as i32 / 12 , 1 + month % 12 , 1 ) . into ( ) ;
104
112
// language=sql
105
113
sqlx:: query!(
106
114
r#"
107
115
SELECT DISTINCT EXTRACT(DAY FROM "timestamp") "day!"
108
116
FROM "message"
109
- WHERE "channel" = $1 AND ("opcode" IS NULL OR "opcode" = 'me')
117
+ WHERE "channel" = ANY($1) AND ("opcode" IS NULL OR "opcode" = 'me')
110
118
AND "timestamp" >= $2 AND "timestamp" < $3
111
119
"# ,
112
- sc . to_string ( ) ,
120
+ & channels ,
113
121
from. midnight( ) ,
114
122
to. midnight( )
115
123
)
@@ -124,10 +132,12 @@ pub(crate) async fn channel_month_index(
124
132
pub ( crate ) async fn channel_search (
125
133
db : & Database ,
126
134
sc : & ServerChannel ,
135
+ remap : & ChannelRemap ,
127
136
query : & str ,
128
137
page : i64 ,
129
138
) -> Paginated < Message > {
130
139
// Try to find nick:<something> to build a non-empty nick filter.
140
+ let channels = remap. aliases_str ( sc) ;
131
141
lazy_static ! {
132
142
static ref NICK : regex:: Regex =
133
143
regex:: Regex :: new( r#"\b(nick:[A-Za-z_0-9|.`\*-]+)"# ) . unwrap( ) ;
@@ -162,14 +172,14 @@ pub(crate) async fn channel_search(
162
172
SELECT row("message".*) "message!:Message",
163
173
ts_headline('english', "line", plainto_tsquery('english', $2), U&'StartSel=\E000, StopSel=\E001') "headline!"
164
174
FROM "message"
165
- WHERE "channel" || '' = $1
175
+ WHERE "channel" || '' = ANY($1)
166
176
AND coalesce("opcode", '') = ''
167
177
AND CASE WHEN $2 = '' THEN TRUE ELSE to_tsvector('english', "nick" || ' ' || "line") @@ plainto_tsquery('english', $2) END
168
178
AND CASE WHEN $5 = '' THEN TRUE ELSE "nick" LIKE $5 END
169
179
)
170
180
SELECT *, COUNT(*) OVER () "total!"
171
181
FROM "query" t LIMIT $3 OFFSET $4
172
- "# , sc . to_string ( ) , & query, per_page, offset, nick_filter)
182
+ "# , & channels , & query, per_page, offset, nick_filter)
173
183
. fetch_all ( db)
174
184
. await
175
185
. unwrap ( ) ;
0 commit comments