You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.9 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env python3.7
"""
Detta är ELAB:s Slack-app.
Den har för närvarande i uppgift att göra "affiliate links" av Banggood-länkar.
"""
from slackeventsapi import SlackEventAdapter
from slack import WebClient
import os
import json
from furl import furl
import requests
import extruct
import html
import locale
def make_affiliate(url):
"""Tar en Banggood-URL och gör den till ELAB:s."""
u = furl(url)
# Lägg in ELABs ID. Egentligen vill vi skriva över endast parametern `p`,
# men för att komma runt en bugg med &-tecken rensar vi tills vidare bort
# alla parametrar.
# <https://github.com/slackapi/python-slack-events-api/issues/49>
# u.args['p'] = 'ZT07151453182201504Y'
u.args = {'p': 'ZT07151453182201504Y'}
return str(u)
def unfurl(url):
"""Skapar en presentation (rubrik, bild osv.) av en länk."""
# Ett semikolon hos Banggood kraschar extruct och måste plockas
# bort. <https://github.com/scrapinghub/extruct/issues/109>
page = requests.get(url).text.replace('};', '}')
ld = extruct.extract(page, syntaxes=['json-ld'])['json-ld'][0]
# Banggood verkar ha HTML-kodat den här strängen av slentrian, fast de nog
# inte borde göra så. Vi avkodar.
title = html.unescape(ld['name'])
image = ld['image']
offers = ld['offers']
if not isinstance(offers, list):
offers = [offers]
currency = offers[0]['priceCurrency']
if currency == 'SEK':
currency = 'kr'
prices = [float(offer['price']) for offer in offers]
return {'fallback': title + ' <' + url + '>',
'color': '#cf8e00', # ELAB-orange
# 'pretext': 'Text that appears above the attachment block',
'author_name': 'Banggood',
'author_link': make_affiliate('https://banggood.com/'),
'author_icon': 'https://www.banggood.com/favicon.ico',
'title': title,
'title_link': url,
# Utelämnas eftersom denna sträng från Banggood nästan aldrig
# innehåller något vettigt.
# 'text': ld['description'],
'fields': [{'title': 'Pris',
'value': ' '.join(
[f'{price:n}{currency}' for price in
list(dict.fromkeys([min(prices), max(prices)]))]),
'short': True}],
# Visas som stor bild, vilket tar för mycket plats.
# 'image_url': image,
'thumb_url': image,
'footer': 'Använd denna länk för att gynna ELAB.',
'footer_icon': 'https://www.elab.kth.se/static/favicon.png',
# Endast om informationen är knuten till en viss tidpunkt
# 'ts': 123456789
}
# Our app's Slack Event Adapter for receiving actions via the Events API
# Signing token: <https://api.slack.com/apps/AN6HH95ML/general>
slack_signing_secret = os.environ['SLACK_SIGNING_SECRET']
slack_events_adapter = SlackEventAdapter(slack_signing_secret,
'/slack-eggberg/events')
# Create a WebClient for your bot to use for Web API requests
# Slack token börjar med "xoxp-". <https://api.slack.com/apps/AN6HH95ML/oauth>
token = os.environ['SLACK_TOKEN']
slack_client = WebClient(token)
# Prenumerera på eventet `link_shared`.
@slack_events_adapter.on('link_shared')
def link_shared(event_data):
"""Anropas när någon har postat en länk i Slack."""
urls = [link['url'] for link in event_data['event']['links']]
unfurls = json.dumps({url: unfurl(make_affiliate(url))
for url in urls})
slack_client.chat_unfurl(channel=event_data['event']['channel'],
ts=event_data['event']['message_ts'],
unfurls=unfurls)
# Sätt locale (för att få komma som decimaltecken).
locale.setlocale(locale.LC_ALL, 'sv_SE.UTF-8')
# Börja lyssna.
slack_events_adapter.start(port=8000)