summaryrefslogtreecommitdiff
path: root/chili_change_detector
blob: 030f6f2e8092742c0e6dedbb93f9887482e99e9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#! /bin/bash

check_every="37s" # Put `m' or `s' on the end because this will be used with the
		 # `sleep' command.
seen_issues_log="seen_issues_log"
atom_feed_log="atom_feed_log"
atom_url="https://labs.parabola.nu/activity.atom"
bot_ipc="/tmp/un-provoked-message-store"
# fauno wants him to deliver messages spaced out by two minutes so I need nother
# fifo
another_fifo="/tmp/pbot-ng_chili_change_detector_fifo"

# If the fifo doesn't exist then create it.
[[ -p ${another_fifo} ]] || mkfifo "${another_fifo}"

# OK this code will forward no more than two messages onto pbot-ng every two
# minutes (fauno doesn't want flood). It runs in the background. It could be
# sensible to split this out into a seperate file so it can tidily be used by
# other pbot-ng modules but I cba. This code is quite l33t actually because it
# doesn't delay the messages at all unless two messages get delivered in two
# minutes.
tail -f "${another_fifo}" | while true
do
    read smile && echo "${smile}" >> "${bot_ipc}"
    read -t 120 smile && echo "${smile}" >> "${bot_ipc}" ||
    continue
    sleep 2m
done &

declare -A bugs
declare -A old_bugs

function get_feed_make_array
{
    # Download the feed.
    feed=$( mktemp )
    header_dump=$( mktemp )

    if [[ -n ${etag} ]]
    then
	curl --user-agent "pbot-ng" -D "${header_dump}" -H "If-None-Match: \"${etag}\"" "${atom_url}" 2> /dev/null > "${feed}"
	ret_val="${?}"
    else
	curl --user-agent "pbot-ng" -D "${header_dump}" "${atom_url}" 2> /dev/null > "${feed}"
	ret_val="${?}"
    fi

    # Get the first line of the headers.
    read http_response < "${header_dump}"

    # If curl's exit status was zero and the http response was 200.
    if (( ! ret_val )) && [[ ${http_response} == *' 200 '* ]]
    then
	# Is there an ETag?
	if etag_line=$( grep 'ETag:' "${header_dump}" )
	then
	    etag_line="${etag_line#*\"}"
	    etag="${etag_line%\"*}" # Now we have the ETag.
	else
	    # It seems that the server no longer sends Etags
	    unset etag
	fi
    else
	# This indicates either a failure to download the page or that the page
	# has not changed since the last time it was downloaded.
	rm "${feed}"
	rm "${header_dump}"
	return 1
    fi

    unset bugs
    declare -A -g bugs

    # We want an array of all the bug titles and their urls.
    stage=0
    while read -r line
    do
	case "${stage}" in
	    0 )
		[[ ${line} == *'<entry>'* ]] &&
		{
		    title=""
		    url=""
		    updated=""
		    stage=1
		}

		;;
	    1 )
		case "${line}" in
		    *'<title>'*'</title>'* )
			booboo="${line#*>}"
			title="${booboo%<*}"
			;;
		    *'<link '* )
			yumyum="${line##*href=\"}"
			url="${yumyum%%\"*}"
			;;
		    *'<updated>'*'</updated>'* )
			foobar="${line#*>}"
			updated="${foobar%<*}"
			;;
		    *'</entry>'* )
			# We don't want revisions.
			if [[ -n ${title} ]] && [[ -n ${url} ]] && [[ -n ${updated} ]] && [[ "${title}" != *' - Revision '* ]]
			then
			    # Add this to the array, fixing the url if it's
			    # broken.
			    bugs["${title}🐵${updated}"]="${url/chili/labs.parabola.nu}"
			fi
			stage=0
			;;
		esac
		;;
	esac
    done < "${feed}"

    rm "${feed}"
    rm "${header_dump}"

    return 0
}

function slide_and_write
{
    # We need to make the new array the old one.
    unset old_bugs
    declare -A -g old_bugs

    for key in "${!bugs[@]}"
    do
	ii=$( sed 's/([^)]\+)//' <<< "${key}" )
	old_bugs[${ii}]=${bugs[${key}]}
    done

    # We now write this to the file. We seperate the fields with some sort of
    # cat face: 🐱
    for i in "${!old_bugs[@]}"
    do
	echo "${i}🐱 ${old_bugs[${i}]}"
    done > ${atom_feed_log}
}

if [[ -f ${atom_feed_log} ]]
then
    # Get the array that stores the info of all bug titles and their urls out of
    # the file it's stored in.
    while read -r line
    do
	old_bugs["${line%%🐱 *}"]="${line##*🐱 }"
    done < "${atom_feed_log}"
else
    # The log does not exist so we create it!
    get_feed_make_array
    slide_and_write

    # Also we need to create the log of seen issues.
    for i in "${!bugs[@]}"
    do
	ii=$( sed 's/([^)]\+)//' <<< "${i}" )
	[[ "${ii%%🐵*}" =~ \#[[:digit:]]+ ]] # match the bug number e.g. #390
        echo "${BASH_REMATCH}"
    done > "${seen_issues_log}"
fi

while true
do
    # Download the feed and make an array of the bugs in it. If it fails or
    # hasn't changed then we just wait until it's time to check again and then
    # continue with the next iteration of the loop.
    get_feed_make_array || { sleep "${check_every}" ; continue ; }

    temp_changes=$( mktemp )

    # Compare this array to the previous.  If any new have appeared since last
    # time then we check if it's in a log of seen issues, and if not, we add it,
    # and we know that this is a creation, not a change.
    for i in "${!bugs[@]}"
    do
	ii=$( sed 's/([^)]\+)//' <<< "${i}" )
	# If this bug is new since last time.
	if [[ -z ${old_bugs[${ii}]} ]]
	then
	    # Check the log of seen issues to find out if this is a creation or
	    # a change.
            [[ "${ii%%🐵*}" =~ \#[[:digit:]]+ ]] # match the bug number e.g. #390

	    if grep "${BASH_REMATCH}" "${seen_issues_log}" > /dev/null 2> /dev/null
	    then
		creation_or_change="changed"
	    else
		creation_or_change="created"

		# Add this issue to the log.
		echo "${BASH_REMATCH}" >> "${seen_issues_log}"
	    fi

	    real_title="${i%%🐵*}"
            real_title_a="${real_title%%:*}"
            real_title_b="${real_title#*:}"
            cat="${real_title_a%% - *}" # e.g. `pbot-ng'
            num="${real_title_a#* - }"
	    echo "${num} ${creation_or_change}: ( ${cat} -${real_title_b} ) ${bugs[${i}]}" >> "${temp_changes}"
	fi
    done

    if (( $( wc -l "${temp_changes}" 2> /dev/null | cut -d ' ' -f 1 ) > 12 ))
    then
	echo "More than 12 changes have been detected on the bug tracker. Ignoring." >> "${bot_ipc}"
    else
	while read line
	do
	    echo "${line}" >> "${another_fifo}"
	done < "${temp_changes}"
    fi

    rm -f "${temp_changes}"

    # Make this array the old one and write it to the file in case we need to
    # retrieve it later.
    slide_and_write

    sleep "${check_every}"
done