Compare commits

...

3 Commits

Author SHA1 Message Date
DebaucheryLibrarian 95f3b1c03a Added rudimentary notifications for set alerts. 2021-04-17 01:10:45 +02:00
DebaucheryLibrarian 0773a8019c Updated release search regex to exclude underscores. 2021-04-15 16:56:44 +02:00
DebaucheryLibrarian 1116e09af5 Added Discord link to footer. 2021-04-15 16:11:16 +02:00
9 changed files with 154 additions and 4 deletions

View File

@ -6,20 +6,32 @@
:to="{ name: 'stats' }"
class="segment footer-link nolink"
>stats</router-link>
<a
v-if="config.discord"
:href="config.discord"
target="_blank"
rel="noopener noreferrer"
class="segment footer-link nolink discord"
><Icon icon="discord" /></a>
</footer>
</template>
<style lang="scss" scoped>
.footer {
display: flex;
justify-content: center;
align-items: center;
background: var(--background-dim);
color: var(--shadow);
font-size: .8rem;
font-weight: bold;
text-align: center;
box-shadow: inset -3px 0 3px var(--shadow-hint);
}
.segment {
display: inline-flex;
align-items: center;
padding: .5rem;
&:not(:last-child) {
@ -32,6 +44,17 @@
&:hover {
color: var(--primary);
.icon {
fill: var(--primary);
}
}
}
.discord {
.icon {
fill: var(--shadow);
width: 4rem;
}
}
</style>

View File

@ -49,6 +49,7 @@ export default {
<style lang="scss" scoped>
.menu-item {
color: var(--text);
display: block;
}

View File

@ -92,7 +92,10 @@
</ul>
</div>
<div class="alert-section alert-trigger">
<div
v-if="alert.entity"
class="alert-section alert-trigger"
>
<h4 class="alert-heading">Channel</h4>
<Entity

33
assets/img/icons/discord.svg Executable file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 725.59998 198.3"
version="1.1"
id="svg6"
width="725.59998"
height="198.3">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<path
d="m 105.9,83.2 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0,-6.1 -4.6,-11 -10.2,-11 z m -36.5,0 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0.1,-6.1 -4.5,-11 -10.2,-11 z"
id="path2" />
<path
d="M 154.5,0 H 20.5 C 9.2,0 0,9.2 0,20.5 v 134 C 0,165.8 9.2,175 20.5,175 h 113.4 l -5.3,-18.3 12.8,11.8 12.1,11.1 21.6,18.7 V 20.5 C 175,9.2 165.8,0 154.5,0 Z m -38.6,129.5 c 0,0 -3.6,-4.3 -6.6,-8 13.1,-3.7 18.1,-11.8 18.1,-11.8 -4.1,2.7 -8,4.6 -11.5,5.9 -5,2.1 -9.8,3.4 -14.5,4.3 -9.6,1.8 -18.4,1.3 -25.9,-0.1 -5.7,-1.1 -10.6,-2.6 -14.7,-4.3 -2.3,-0.9 -4.8,-2 -7.3,-3.4 -0.3,-0.2 -0.6,-0.3 -0.9,-0.5 -0.2,-0.1 -0.3,-0.2 -0.4,-0.2 -1.8,-1 -2.8,-1.7 -2.8,-1.7 0,0 4.8,7.9 17.5,11.7 -3,3.8 -6.7,8.2 -6.7,8.2 C 38.1,128.9 29.7,114.5 29.7,114.5 29.7,82.6 44.1,56.7 44.1,56.7 58.5,46 72.1,46.3 72.1,46.3 l 1,1.2 c -18,5.1 -26.2,13 -26.2,13 0,0 2.2,-1.2 5.9,-2.8 10.7,-4.7 19.2,-5.9 22.7,-6.3 0.6,-0.1 1.1,-0.2 1.7,-0.2 6.1,-0.8 13,-1 20.2,-0.2 9.5,1.1 19.7,3.9 30.1,9.5 0,0 -7.9,-7.5 -24.9,-12.6 l 1.4,-1.6 c 0,0 13.7,-0.3 28,10.4 0,0 14.4,25.9 14.4,57.8 0,-0.1 -8.4,14.3 -30.5,15 z m 151,-86.7 H 233.7 V 80.1 L 255.8,100 V 63.8 h 11.8 c 7.5,0 11.2,3.6 11.2,9.4 v 27.7 c 0,5.8 -3.5,9.7 -11.2,9.7 h -34 v 21.1 h 33.2 c 17.8,0.1 34.5,-8.8 34.5,-29.2 V 72.7 C 301.4,51.9 284.7,42.8 266.9,42.8 Z m 174,59.7 V 71.9 c 0,-11 19.8,-13.5 25.8,-2.5 L 485,62 C 477.8,46.2 464.7,41.6 453.8,41.6 436,41.6 418.4,51.9 418.4,71.9 v 30.6 c 0,20.2 17.6,30.3 35,30.3 11.2,0 24.6,-5.5 32,-19.9 l -19.6,-9 c -4.8,12.3 -24.9,9.3 -24.9,-1.4 z M 380.4,76.1 c -6.9,-1.5 -11.5,-4 -11.8,-8.3 0.4,-10.3 16.3,-10.7 25.6,-0.8 l 14.7,-11.3 c -9.2,-11.2 -19.6,-14.2 -30.3,-14.2 -16.3,0 -32.1,9.2 -32.1,26.6 0,16.9 13,26 27.3,28.2 7.3,1 15.4,3.9 15.2,8.9 -0.6,9.5 -20.2,9 -29.1,-1.8 l -14.2,13.3 c 8.3,10.7 19.6,16.1 30.2,16.1 16.3,0 34.4,-9.4 35.1,-26.6 C 412,84.5 396.2,79 380.4,76.1 Z m -67,55.5 h 22.4 V 42.8 H 313.4 Z M 691.1,42.8 H 657.9 V 80.1 L 680,100 V 63.8 h 11.8 c 7.5,0 11.2,3.6 11.2,9.4 v 27.7 c 0,5.8 -3.5,9.7 -11.2,9.7 h -34 v 21.1 h 33.3 c 17.8,0.1 34.5,-8.8 34.5,-29.2 V 72.7 c 0,-20.8 -16.7,-29.9 -34.5,-29.9 z M 528.2,41.6 c -18.4,0 -36.7,10 -36.7,30.5 v 30.3 c 0,20.3 18.4,30.5 36.9,30.5 18.4,0 36.7,-10.2 36.7,-30.5 V 72.1 c 0,-20.4 -18.5,-30.5 -36.9,-30.5 z m 14.4,60.8 c 0,6.4 -7.2,9.7 -14.3,9.7 -7.2,0 -14.4,-3.1 -14.4,-9.7 V 72.1 c 0,-6.5 7,-10 14,-10 7.3,0 14.7,3.1 14.7,10 z M 645.5,72.1 C 645,51.3 630.8,42.9 612.5,42.9 H 577 v 88.8 h 22.7 v -28.2 h 4 l 20.6,28.2 h 28 l -24.2,-30.5 c 10.7,-3.4 17.4,-12.7 17.4,-29.1 z m -32.6,12 H 599.7 V 63.8 h 13.2 c 14.1,0 14.1,20.3 0,20.3 z"
id="path4" />
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -35,4 +35,5 @@ export default {
'squirting',
'swallowing',
],
discord: 'https://discord.gg/6mjHTYG',
};

View File

@ -1241,6 +1241,33 @@ exports.up = knex => Promise.resolve()
table.unique(['alert_id', 'stash_id']);
}))
.then(() => knex.schema.createTable('notifications', (table) => {
table.increments('id');
table.integer('user_id')
.notNullable()
.references('id')
.inTable('users')
.onDelete('cascade');
table.integer('scene_id')
.references('id')
.inTable('releases')
.onDelete('cascade');
table.integer('alert_id')
.references('id')
.inTable('alerts')
.onDelete('set null');
table.boolean('seen')
.notNullable()
.defaultTo(false);
table.datetime('created_at')
.notNullable()
.defaultTo(knex.fn.now());
}))
// SEARCH
.then(() => { // eslint-disable-line arrow-body-style
// allow vim fold
@ -1277,7 +1304,7 @@ exports.up = knex => Promise.resolve()
SELECT releases.id, ranks.rank FROM (
SELECT
releases_search.release_id,
ts_rank(releases_search.document, to_tsquery('english', array_to_string(array(SELECT * FROM regexp_matches(query, '\\w+', 'g')), '|'))) AS rank
ts_rank(releases_search.document, to_tsquery('english', array_to_string(array(SELECT * FROM regexp_matches(query, '[A-Za-zÀ-ÖØ-öø-ÿ0-9]+', 'g')), '|'))) AS rank
FROM releases_search
) ranks
LEFT JOIN releases ON releases.id = ranks.release_id
@ -1631,6 +1658,8 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
DROP TABLE IF EXISTS entities_types CASCADE;
DROP TABLE IF EXISTS entities CASCADE;
DROP TABLE IF EXISTS notifications CASCADE;
DROP TABLE IF EXISTS stashes_scenes CASCADE;
DROP TABLE IF EXISTS stashes_movies CASCADE;
DROP TABLE IF EXISTS stashes_actors CASCADE;

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -259,7 +259,7 @@ async function fetchLatest(entity, page, options) {
release.tags = await knex('tags')
.select('name')
.where('priority', '>', 5)
.where('priority', '>', 7)
.orderByRaw('random()')
.limit(faker.random.number({ min: 2, max: 15 }))
.pluck('name');

View File

@ -211,6 +211,64 @@ async function filterDuplicateReleases(releases) {
};
}
async function notifyAlerts(scenes) {
const releases = await knex.raw(`
SELECT alerts.id as alert_id, alerts.notify, alerts.email, releases.id as scene_id, users.id as user_id
FROM releases
CROSS JOIN alerts
LEFT JOIN users ON users.id = alerts.user_id
LEFT JOIN releases_tags ON releases_tags.release_id = releases.id
/* match updated IDs from input */
WHERE (releases.id = ANY(:sceneIds))
/* match tags */
AND (NOT EXISTS (SELECT alerts_tags.alert_id
FROM alerts_tags
WHERE alerts_tags.alert_id = alerts.id)
OR (SELECT array_agg(releases_tags.tag_id)
FROM releases_tags
WHERE releases_tags.release_id = releases.id
GROUP BY releases_tags.release_id)
@> (SELECT array_agg(alerts_tags.tag_id)
FROM alerts_tags
WHERE alerts_tags.alert_id = alerts.id
GROUP BY alerts_tags.alert_id))
/* match actors */
AND (NOT EXISTS (SELECT alerts_actors.alert_id
FROM alerts_actors
WHERE alerts_actors.alert_id = alerts.id)
OR (SELECT array_agg(releases_actors.actor_id)
FROM releases_actors
WHERE releases_actors.release_id = releases.id
GROUP BY releases_actors.release_id)
@> (SELECT array_agg(alerts_actors.actor_id)
FROM alerts_actors
WHERE alerts_actors.alert_id = alerts.id
GROUP BY alerts_actors.alert_id))
/* match entity */
AND ((NOT EXISTS (SELECT alerts_entities.entity_id
FROM alerts_entities
WHERE alerts_entities.alert_id = alerts.id))
OR (releases.entity_id
= ANY(array(SELECT alerts_entities.entity_id
FROM alerts_entities
WHERE alerts_entities.alert_id = alerts.id))))
GROUP BY releases.id, users.id, alerts.id;
`, { sceneIds: scenes.map(scene => scene.id) });
const notify = releases.rows.filter(alert => alert.notify);
await knex('notifications')
.insert(notify.map(notification => ({
user_id: notification.user_id,
alert_id: notification.alert_id,
scene_id: notification.scene_id,
})));
console.log(releases.rows);
return releases.rows;
}
async function updateReleasesSearch(releaseIds) {
logger.info(`Updating search documents for ${releaseIds ? releaseIds.length : 'all' } releases`);
@ -338,6 +396,8 @@ async function storeScenes(releases) {
logger.info(`Stored ${storedReleaseEntries.length} releases`);
await notifyAlerts(releasesWithId);
return releasesWithId;
}