API petitions, sign petitions by subscribing to mastodon and such
This commit is contained in:
parent
6cd369b043
commit
7750afc5b9
3 changed files with 232 additions and 38 deletions
50
modules/API.py
Normal file
50
modules/API.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# AGPL 3 or any later version
|
||||||
|
# (C) J.Y.Amihud ( Blender Dumbass )
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import email
|
||||||
|
import random
|
||||||
|
import hashlib
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from modules import Set
|
||||||
|
from modules.Common import *
|
||||||
|
|
||||||
|
def Get(url, data=None, headers={}):
|
||||||
|
|
||||||
|
if data:
|
||||||
|
data = json.dumps(data).encode("utf-8")
|
||||||
|
req = urllib.request.Request(url, data=data, headers=headers)
|
||||||
|
f = urllib.request.urlopen(req, timeout=10)
|
||||||
|
data = json.loads(f.read().decode('utf-8'))
|
||||||
|
return data
|
||||||
|
|
||||||
|
def Value(url, keys):
|
||||||
|
|
||||||
|
data = Get(url)
|
||||||
|
for key in keys:
|
||||||
|
data = data[key]
|
||||||
|
return data
|
||||||
|
|
||||||
|
def Petition(article):
|
||||||
|
|
||||||
|
petition = article.get("petition", {})
|
||||||
|
api = petition.get("api", {})
|
||||||
|
timestamp = api.get("timestamp",0)
|
||||||
|
|
||||||
|
# 5 minutes delay
|
||||||
|
if time.time() - 300 < timestamp:
|
||||||
|
return
|
||||||
|
|
||||||
|
value = int(Value(api.get("api", ""), api.get("keys", [])))
|
||||||
|
article["petition"]["api"]["timestamp"] = time.time()
|
||||||
|
article["petition"]["signed"] = value
|
||||||
|
|
||||||
|
f = Set.Folder()
|
||||||
|
with open(f+"/tabs"+article.get("url", "")+"/metadata.json", "w") as save:
|
||||||
|
json.dump(article, save, indent=4)
|
|
@ -118,14 +118,12 @@ def VerifyPage(server):
|
||||||
# If we recieved the code.
|
# If we recieved the code.
|
||||||
|
|
||||||
if code not in verifying:
|
if code not in verifying:
|
||||||
print("code not in verifying")
|
Render.Error(server, "Wrong Code!")
|
||||||
Render.AccessDenied(server)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
if verifying[code] != user.get("email"):
|
if verifying[code] != user.get("email"):
|
||||||
print("email wrong")
|
Render.Error(server, "Wrong Code!")
|
||||||
Render.AccessDenied(server)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
user["email_verified"] = True
|
user["email_verified"] = True
|
||||||
|
@ -165,7 +163,7 @@ def SignPetition(server):
|
||||||
email = server.parsed.get("email", [""])[0]
|
email = server.parsed.get("email", [""])[0]
|
||||||
|
|
||||||
if email in Article.get("petition", {}).get("signatures", []):
|
if email in Article.get("petition", {}).get("signatures", []):
|
||||||
Render.AccessDenied(server)
|
Render.Error(server, "You already signed!")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
|
@ -222,8 +220,7 @@ def SignPetition(server):
|
||||||
# If we recieved the code.
|
# If we recieved the code.
|
||||||
|
|
||||||
if code not in verifying:
|
if code not in verifying:
|
||||||
print("code not in verifying")
|
Render.Error(server, "Wrong Code!")
|
||||||
Render.AccessDenied(server)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import urllib.parse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from modules import Set
|
from modules import Set
|
||||||
|
from modules import API
|
||||||
from modules import markdown
|
from modules import markdown
|
||||||
from modules.Common import *
|
from modules.Common import *
|
||||||
|
|
||||||
|
@ -571,8 +572,16 @@ def ArticlePage(server, url):
|
||||||
petition = Articles.get(article, {}).get("petition", "")
|
petition = Articles.get(article, {}).get("petition", "")
|
||||||
if petition:
|
if petition:
|
||||||
|
|
||||||
|
petition_error = False
|
||||||
|
|
||||||
|
if petition.get("api"):
|
||||||
|
try:
|
||||||
|
API.Petition(Articles[article])
|
||||||
|
except:
|
||||||
|
petition_error = True
|
||||||
|
|
||||||
html = html + '<div class="dark_box"> <center>'
|
html = html + '<div class="dark_box"> <center>'
|
||||||
html = html + '<h2><img alt="[icon petition]" style="vertical-align: middle" src="/icon/petition">'
|
html = html + '<h2>'
|
||||||
html = html + 'Petition</h2></center>'
|
html = html + 'Petition</h2></center>'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -583,29 +592,61 @@ def ArticlePage(server, url):
|
||||||
html = html + ProgressBar(frac)
|
html = html + ProgressBar(frac)
|
||||||
html = html + "<br><center>"+str(petition.get("signed", 0))+" / "+Safe(str(petition.get("goal", 1)))+" Signatures"
|
html = html + "<br><center>"+str(petition.get("signed", 0))+" / "+Safe(str(petition.get("goal", 1)))+" Signatures"
|
||||||
|
|
||||||
html = html + """
|
# Last update
|
||||||
|
if petition.get("api"):
|
||||||
<details>
|
|
||||||
<summary class="button">
|
|
||||||
<img alt="[icon petition]" style="vertical-align: middle" src="/icon/petition">
|
|
||||||
Sign
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
<form action="/sign_petition">
|
|
||||||
<input type="hidden" name="article" value='/"""+tab+"/"+article+"""'>
|
|
||||||
|
|
||||||
<img style="vertical-align: middle" src="/icon/frase">
|
|
||||||
<input class="button" style="width:90%" required maxlength="200" name="email" placeholder="Email">
|
|
||||||
|
|
||||||
<button class="button" type="submit">
|
|
||||||
<img style="vertical-align: middle" src="/icon/ok">
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</form>
|
lastUpdate = petition.get("api", {}).get("timestamp", {})
|
||||||
|
nowTime = time.time()
|
||||||
|
html = html + '<br><br><small>Last updated: '+TimeDifference(lastUpdate, nowTime)+'</small><br><br>'
|
||||||
|
|
||||||
</details>
|
if not petition.get("api"):
|
||||||
"""
|
|
||||||
|
html = html + """
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary class="button">
|
||||||
|
<img alt="[icon petition]" style="vertical-align: middle" src="/icon/petition">
|
||||||
|
Sign
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<form action="/sign_petition">
|
||||||
|
<input type="hidden" name="article" value='/"""+tab+"/"+article+"""'>
|
||||||
|
|
||||||
|
<img style="vertical-align: middle" src="/icon/frase">
|
||||||
|
<input class="button" style="width:90%" required maxlength="200" name="email" placeholder="Email">
|
||||||
|
|
||||||
|
<button class="button" type="submit">
|
||||||
|
<img style="vertical-align: middle" src="/icon/ok">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
"""
|
||||||
|
|
||||||
|
else:
|
||||||
|
html = html + """
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary class="button">
|
||||||
|
<img alt="[icon petition]" style="vertical-align: middle" src="/icon/petition">
|
||||||
|
Sign
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<br>
|
||||||
|
This petition is signed by increasing the number of<br>
|
||||||
|
<i>"""+petition.get("api", {}).get("title", "")+"""</i>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
"""+Button("Continue", petition.get("api", {}).get("link", ""), "ok")+"""
|
||||||
|
|
||||||
|
|
||||||
|
</center>
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
html = html + '</div>'
|
html = html + '</div>'
|
||||||
|
|
||||||
|
@ -1395,9 +1436,22 @@ def EditorPage(server):
|
||||||
if rank(user.get("username","")) == 0:
|
if rank(user.get("username","")) == 0:
|
||||||
|
|
||||||
|
|
||||||
petition = article.get("petition", {})
|
petition = article.get("petition", {})
|
||||||
petition_goal = petition.get("goal", 0)
|
petition_goal = petition.get("goal", "")
|
||||||
|
petition_api = petition.get("api", {}).get("api", "")
|
||||||
|
petition_api_key = petition.get("api", {}).get("keys", [])
|
||||||
|
petition_api_title = petition.get("api", {}).get("title", "")
|
||||||
|
petition_api_link = petition.get("api", {}).get("link", "")
|
||||||
|
|
||||||
|
if len(petition_api_key) == 1:
|
||||||
|
petition_api_key = petition_api_key[0]
|
||||||
|
else:
|
||||||
|
key = petition_api_key[0]
|
||||||
|
for n, i in petition_api_key:
|
||||||
|
if n != 0:
|
||||||
|
key = key + "/" + i
|
||||||
|
petition_api_key = key
|
||||||
|
|
||||||
|
|
||||||
html = html + """
|
html = html + """
|
||||||
|
|
||||||
|
@ -1423,19 +1477,19 @@ def EditorPage(server):
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<img alt="[icon link]" style="vertical-align: middle" src="/icon/link">
|
<img alt="[icon link]" style="vertical-align: middle" src="/icon/link">
|
||||||
<input class="button" style="width:90%" name="petition_api" placeholder="API to check ( should be JSON )">
|
<input class="button" style="width:90%" name="petition_api" placeholder="API to check ( should be JSON )" value='"""+petition_api+"""'>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<img alt="[icon checlist]" style="vertical-align: middle" src="/icon/checklist">
|
<img alt="[icon checlist]" style="vertical-align: middle" src="/icon/checklist">
|
||||||
<input class="button" style="width:90%" name="petition_api_key" placeholder="Key To Look For ( split with / for nested deep data )">
|
<input class="button" style="width:90%" name="petition_api_key" placeholder="Key To Look For ( split with / for nested deep data )" value='"""+petition_api_key+"""'>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<img alt="[icon scene]" style="vertical-align: middle" src="/icon/scene">
|
<img alt="[icon scene]" style="vertical-align: middle" src="/icon/scene">
|
||||||
<input class="button" style="width:90%" name="petition_api_title" placeholder="Statistic's Name">
|
<input class="button" style="width:90%" name="petition_api_title" placeholder="Statistic's Name" value='"""+petition_api_title+"""'>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<img alt="[icon link]" style="vertical-align: middle" src="/icon/link">
|
<img alt="[icon link]" style="vertical-align: middle" src="/icon/link">
|
||||||
<input class="button" style="width:90%" name="petition_api_link" placeholder="Action Link ( where people can increase the number in the API )">
|
<input class="button" style="width:90%" name="petition_api_link" placeholder="Action Link ( where people can increase the number in the API )" value='"""+petition_api_link+"""'>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1928,7 +1982,33 @@ def AccessDenied(server):
|
||||||
|
|
||||||
send(server, html, 404)
|
send(server, html, 404)
|
||||||
|
|
||||||
|
def Error(server, text="Some Error Happened."):
|
||||||
|
|
||||||
|
config = Set.Load()
|
||||||
|
|
||||||
|
html = head(title = "501 Error",
|
||||||
|
description = "501 Error",
|
||||||
|
config = config
|
||||||
|
)
|
||||||
|
|
||||||
|
html = html + Button(config.get("title", "My Website"), "/", image=config.get("favicon", "/icon/internet"))
|
||||||
|
|
||||||
|
html = html + """
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<div class="article_box">
|
||||||
|
<h1>501 Error</h1>
|
||||||
|
|
||||||
|
"""+text+"""
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
</center>
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
send(server, html, 501)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
def Redirect(server, url, time=0):
|
def Redirect(server, url, time=0):
|
||||||
|
@ -2475,8 +2555,28 @@ def Publish(server):
|
||||||
petition["goal"] = int(petition_goal)
|
petition["goal"] = int(petition_goal)
|
||||||
except:
|
except:
|
||||||
petition["goal"] = 1
|
petition["goal"] = 1
|
||||||
|
|
||||||
|
|
||||||
|
# API petition
|
||||||
|
|
||||||
|
if petition_api:
|
||||||
|
petition["api"] = {
|
||||||
|
"api" :petition_api,
|
||||||
|
"keys" :petition_api_key.split("/"),
|
||||||
|
"title":petition_api_title,
|
||||||
|
"link" :petition_api_link
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
metadata["petition"] = petition
|
||||||
|
|
||||||
|
|
||||||
metadata["petition"] = petition
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
del metadata["petition"]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# Save the changes
|
# Save the changes
|
||||||
|
|
||||||
|
@ -2494,7 +2594,16 @@ def Publish(server):
|
||||||
save.write(text)
|
save.write(text)
|
||||||
else:
|
else:
|
||||||
save.write(Safe(text))
|
save.write(Safe(text))
|
||||||
|
|
||||||
|
if metadata.get("petition"):
|
||||||
|
metadata["url"] = "/"+tab+"/"+name
|
||||||
|
try:
|
||||||
|
API.Petition(metadata)
|
||||||
|
except Exception as e:
|
||||||
|
Error(server, "Cannot Load API Value<br>\n"+Safe(str(e)))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
Redirect(server, "/"+tab+"/"+name)
|
Redirect(server, "/"+tab+"/"+name)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2645,7 +2754,45 @@ def ReadNotification(server):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(clr["bold"]+clr["tdrd"]+"Error:"+clr["norm"]+" Unable to read notification!", e)
|
print(clr["bold"]+clr["tdrd"]+"Error:"+clr["norm"]+" Unable to read notification!", e)
|
||||||
|
|
||||||
|
def TimeDifference(timeA, timeB):
|
||||||
|
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
if timeA < timeB:
|
||||||
|
if timeB - timeA < 10:
|
||||||
|
text = "now"
|
||||||
|
return text
|
||||||
|
|
||||||
|
elif timeB - timeA < 60:
|
||||||
|
text = str(int(timeB - timeA))+" seconds ago"
|
||||||
|
return text
|
||||||
|
|
||||||
|
else:
|
||||||
|
if int( ( timeB - timeA ) / 60 ) == 1:
|
||||||
|
text = str(int( ( timeB - timeA ) / 60 ))+" minute ago"
|
||||||
|
else:
|
||||||
|
text = str(int( ( timeB - timeA ) / 60 ))+" minutes ago"
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
if timeA - timeA < 10:
|
||||||
|
text= "now"
|
||||||
|
return text
|
||||||
|
|
||||||
|
elif timeA - timeB < 60:
|
||||||
|
text = "in "+str(int(timeA - timeB))+" seconds"
|
||||||
|
return text
|
||||||
|
|
||||||
|
else:
|
||||||
|
if int( ( timeA - timeB ) / 60 ) == 1:
|
||||||
|
text = "in "+str(int( ( timeA - timeB ) / 60 ))+" minute"
|
||||||
|
else:
|
||||||
|
text = "in "+str(int( ( timeA - timeB ) / 60 ))+" minutes"
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
def RSS(server):
|
def RSS(server):
|
||||||
|
|
||||||
# Rendering rss feed.
|
# Rendering rss feed.
|
||||||
|
|
Loading…
Add table
Reference in a new issue