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.

109 lines
4.1 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.

#!/usr/bin/env python3
"""
Detta är ELAB:s Slack-app.
Den har för närvarande i uppgift att göra "affiliate links" av Banggood-länkar.
"""
# Detta skript ska sitta bakom HTTPS och lyssna på anrop från Slack. (Kör
# "ngrok http 8000" för att få en tillfällig proxy för testning.) Lägg till
# "/slack/events" till den resulterande HTTPS-URL:en och använd som Request URL
# på <https://api.slack.com/apps/AN6HH95ML/event-subscriptions>.
from slackeventsapi import SlackEventAdapter
from slackclient import SlackClient
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']
currency = ld['offers']['priceCurrency']
if currency == 'SEK':
currency = 'kr'
# Formateringsinstruktionen "n" ger oss decimaltecken enligt aktuell
# locale.
price = f'{float(ld["offers"]["price"]):n}' + '' + currency
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': price,
'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 SlackClient 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 = SlackClient(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.api_call('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, '')
# Starta en server med endpointen `/slack/events`.
slack_events_adapter.start(port=8000)