Browse Source

Initial commit

master
The Dod 1 year ago
parent
commit
0df384a574
7 changed files with 110 additions and 1 deletions
  1. 8
    1
      README.md
  2. 33
    0
      mymastotag.py
  3. 4
    0
      requirements.txt
  4. 12
    0
      static/css/bootstrap-rtl.min.css
  5. 12
    0
      static/css/bootstrap.min.css
  6. BIN
      static/favicon.ico
  7. 41
    0
      templates/index.html

+ 8
- 1
README.md View File

@@ -1,3 +1,10 @@
1 1
 # mymastotag
2 2
 
3
-iframeable display of all posts by a matodon @user@instance account that contain a #hashtag
3
+
4
+This runs a web app where /`lang`/`instance`/`user`/`hashtag` returns an iframeable page with
5
+of all posts by a matodon `@user@instance account` that contain `#hashtag`
6
+
7
+For example:
8
+
9
+* `/en/tooot.im/zvinj/caturday`
10
+* `/en/tooot.im/neo/קפה_ברוח_טובה`

+ 33
- 0
mymastotag.py View File

@@ -0,0 +1,33 @@
1
+import time
2
+import feedparser
3
+from flask import Flask, render_template
4
+from bs4 import BeautifulSoup
5
+
6
+app = Flask(__name__)
7
+
8
+@app.route('/<string:lang>/<string:instance>/<string:user>/<string:tag>')
9
+def my_masto_tag(lang, instance, user, tag):
10
+    lang = lang.lower()
11
+    is_rtl = lang in ['he', 'ar']  # TODO: A less lame to determine rtl
12
+    title = f'@{user}@{instance} &mdash; #{tag}'
13
+    feed = feedparser.parse(f'https://{instance}/@{user}/tagged/{tag}.rss')
14
+    for e in feed['entries']:
15
+        e['date'] = time.strftime('%Y-%m-%d', e['published_parsed'])
16
+        soup = BeautifulSoup(e['description'], 'html.parser')
17
+        for link in soup.find_all('a'):
18
+            link['target'] = '_blank'
19
+            link['class'] = ['link-info', 'text-decoration-none']
20
+        e['description'] = str(soup)
21
+        images = []
22
+        videos =[]
23
+        for m in e['media_content']:
24
+            mtype = m['type'].split('/')[0]
25
+            if mtype=='image':
26
+                images.append(m)
27
+            elif mtype=='video':
28
+                videos.append(m)
29
+        e['images'] = images
30
+        e['has_images'] = not not images
31
+        e['videos'] = videos
32
+        e['has_videos'] = not not videos
33
+    return render_template('index.html', lang=lang, is_rtl=is_rtl, title=title, feed=feed)

+ 4
- 0
requirements.txt View File

@@ -0,0 +1,4 @@
1
+flask
2
+feedparser
3
+beautifulsoup4
4
+pyuwsgi

+ 12
- 0
static/css/bootstrap-rtl.min.css
File diff suppressed because it is too large
View File


+ 12
- 0
static/css/bootstrap.min.css
File diff suppressed because it is too large
View File


BIN
static/favicon.ico View File


+ 41
- 0
templates/index.html View File

@@ -0,0 +1,41 @@
1
+<!DOCTYPE html>
2
+<html lang="{{lang}}"{% if is_rtl %} dir="rtl"{% endif %}>
3
+  <head>
4
+    <meta charset="utf-8">
5
+    <title>{{title|safe}}</title>
6
+    <meta name="viewport" content="width=device-width, initial-scale=1">
7
+    <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
8
+    <link rel="stylesheet" href="/static/css/bootstrap{% if is_rtl %}-rtl{% endif %}.min.css">
9
+  </head>
10
+  <body>
11
+    <div class="container">
12
+      <div class="row" id="entries">
13
+        {% for entry in feed.entries %}
14
+          <div class="col-12 col-sm-6 col-md-4 col-lg-3 g-1">
15
+            <div class="card">
16
+              <div class="card-body">
17
+                <div class="float-end ms-1"><span class="badge bg-warning">{{ entry.date }}</span></div>
18
+                {{ entry.description|safe }}
19
+              </div>
20
+              {% if entry.images %}
21
+                <ul class="list-group">
22
+                  {% for image in entry.images %}
23
+                    <li class="list-group-item"><a target="_blank" href="{{image.url}}"><img class="w-100" src="{{image.url}}" alt="{{image.media_description}}" /></a></li>
24
+                  {% endfor %}
25
+                </ul>
26
+              {% endif %}
27
+              {% if entry.videos %}
28
+                <ul class="list-group">
29
+                  {% for video in entry.videos %}
30
+                    <li class="list-group-item"><video controls loop class="w-100" src="{{video.url}}" /></li>
31
+                  {% endfor %}
32
+                </ul>
33
+              {% endif %}
34
+            </div>
35
+          </div>
36
+        {% endfor %}
37
+      </div>
38
+    </div>
39
+  </body>
40
+</html>
41
+

Loading…
Cancel
Save