diff --git a/daemon.py b/daemon.py
index 7690f224f..b5b20c4e5 100644
--- a/daemon.py
+++ b/daemon.py
@@ -39,6 +39,7 @@ from person import removeAccount
from person import canRemovePost
from person import personSnooze
from person import personUnsnooze
+from posts import mutePost
from posts import createQuestionPost
from posts import outboxMessageCreateWrap
from posts import savePostToBox
@@ -2058,6 +2059,11 @@ class PubServer(BaseHTTPRequestHandler):
deleteUrl=self.path.split('?delete=')[1]
if '?' in deleteUrl:
deleteUrl=deleteUrl.split('?')[0]
+ timelineStr=self.server.defaultTimeline
+ if '?tl=' in self.path:
+ timelineStr=self.path.split('?tl=')[1]
+ if '?' in timelineStr:
+ timelineStr=timelineStr.split('?')[0]
actor= \
self.server.httpPrefix+'://'+ \
self.server.domainFull+self.path.split('?delete=')[0]
@@ -2069,13 +2075,13 @@ class PubServer(BaseHTTPRequestHandler):
if actor not in deleteUrl:
# You can only delete your own posts
self.server.GETbusy=False
- self._redirect_headers(actor+'/'+self.server.defaultTimeline,cookie)
+ self._redirect_headers(actor+'/'+timelineStr,cookie)
return
self.postToNickname=getNicknameFromActor(actor)
if not self.postToNickname:
print('WARN: unable to find nickname in '+actor)
self.server.GETbusy=False
- self._redirect_headers(actor+'/'+self.server.defaultTimeline,cookie)
+ self._redirect_headers(actor+'/'+timelineStr,cookie)
return
if not self.server.session:
self.server.session= \
@@ -2095,7 +2101,61 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy=False
return
self.server.GETbusy=False
- self._redirect_headers(actor+'/'+self.server.defaultTimeline,cookie)
+ self._redirect_headers(actor+'/'+timelineStr,cookie)
+ return
+
+ # mute a post from the web interface icon
+ if htmlGET and '?mute=' in self.path:
+ pageNumber=1
+ if '?page=' in self.path:
+ pageNumberStr=self.path.split('?page=')[1]
+ if '?' in pageNumberStr:
+ pageNumberStr=pageNumberStr.split('?')[0]
+ if pageNumberStr.isdigit():
+ pageNumber=int(pageNumberStr)
+ muteUrl=self.path.split('?mute=')[1]
+ if '?' in muteUrl:
+ muteUrl=muteUrl.split('?')[0]
+ timelineStr=self.server.defaultTimeline
+ if '?tl=' in self.path:
+ timelineStr=self.path.split('?tl=')[1]
+ if '?' in timelineStr:
+ timelineStr=timelineStr.split('?')[0]
+ actor= \
+ self.server.httpPrefix+'://'+ \
+ self.server.domainFull+self.path.split('?mute=')[0]
+ nickname=getNicknameFromActor(actor)
+ mutePost(self.server.baseDir,nickname,self.server.domain, \
+ muteUrl,self.server.recentPostsCache)
+ self.server.GETbusy=False
+ self._redirect_headers(actor+'/'+timelineStr,cookie)
+ return
+
+ # unmute a post from the web interface icon
+ if htmlGET and '?unmute=' in self.path:
+ pageNumber=1
+ if '?page=' in self.path:
+ pageNumberStr=self.path.split('?page=')[1]
+ if '?' in pageNumberStr:
+ pageNumberStr=pageNumberStr.split('?')[0]
+ if pageNumberStr.isdigit():
+ pageNumber=int(pageNumberStr)
+ muteUrl=self.path.split('?unmute=')[1]
+ if '?' in muteUrl:
+ muteUrl=muteUrl.split('?')[0]
+ timelineStr=self.server.defaultTimeline
+ if '?tl=' in self.path:
+ timelineStr=self.path.split('?tl=')[1]
+ if '?' in timelineStr:
+ timelineStr=timelineStr.split('?')[0]
+ actor= \
+ self.server.httpPrefix+'://'+ \
+ self.server.domainFull+self.path.split('?mute=')[0]
+ nickname=getNicknameFromActor(actor)
+ unmutePost(self.server.baseDir,nickname,self.server.domain, \
+ muteUrl,self.server.recentPostsCache)
+ self.server.GETbusy=False
+ self._redirect_headers(actor+'/'+timelineStr,cookie)
return
# reply from the web interface icon
diff --git a/img/icons/hacker/mute.png b/img/icons/hacker/mute.png
new file mode 100644
index 000000000..6969e74d3
Binary files /dev/null and b/img/icons/hacker/mute.png differ
diff --git a/img/icons/light/mute.png b/img/icons/light/mute.png
new file mode 100644
index 000000000..5fe808e0f
Binary files /dev/null and b/img/icons/light/mute.png differ
diff --git a/img/icons/mute.png b/img/icons/mute.png
new file mode 100644
index 000000000..2c36817c5
Binary files /dev/null and b/img/icons/mute.png differ
diff --git a/img/icons/purple/mute.png b/img/icons/purple/mute.png
new file mode 100644
index 000000000..d2626e8fc
Binary files /dev/null and b/img/icons/purple/mute.png differ
diff --git a/posts.py b/posts.py
index 921f2819d..85a691b91 100644
--- a/posts.py
+++ b/posts.py
@@ -2635,3 +2635,49 @@ def downloadAnnounce(session,baseDir: str,httpPrefix: str,nickname: str,domain:
if saveJson(postJsonObject,announceFilename):
return postJsonObject
return None
+
+def mutePost(baseDir: str,nickname: str,domain: str,postId: str, \
+ recentPostsCache: {}) -> None:
+ """ Mutes the given post
+ """
+ postFilename=locatePost(baseDir,nickname,domain,postId)
+ if not postFilename:
+ return
+ postJsonObject=loadJson(postFilename)
+ if not postJsonObject:
+ return
+
+ muteFile=open(postFilename+'.muted', "w")
+ muteFile.write('\n')
+ muteFile.close()
+
+ # remove cached posts so that the muted version gets created
+ cachedPostFilename= \
+ getCachedPostFilename(baseDir,nickname,postJsonObject)
+ if cachedPostFilename:
+ if os.path.isfile(cachedPostFilename):
+ os.remove(cachedPostFilename)
+ removePostFromCache(postJsonObject,recentPostsCache)
+
+def unmutePost(baseDir: str,nickname: str,domain: str,postId: str, \
+ recentPostsCache: {}) -> None:
+ """ Unmutes the given post
+ """
+ postFilename=locatePost(baseDir,nickname,domain,postId)
+ if not postFilename:
+ return
+ postJsonObject=loadJson(postFilename)
+ if not postJsonObject:
+ return
+
+ muteFilename=postFilename+'.muted'
+ if os.path.isfile(muteFilename):
+ os.remove(muteFilename)
+
+ # remove cached posts so that it gets recreated
+ cachedPostFilename= \
+ getCachedPostFilename(baseDir,nickname,postJsonObject)
+ if cachedPostFilename:
+ if os.path.isfile(cachedPostFilename):
+ os.remove(cachedPostFilename)
+ removePostFromCache(postJsonObject,recentPostsCache)
diff --git a/translations/ar.json b/translations/ar.json
index 65cf2a99c..086943258 100644
--- a/translations/ar.json
+++ b/translations/ar.json
@@ -198,5 +198,7 @@
"Previous month": "الشهر الماضى",
"Next month": "الشهر القادم",
"Get the source code": "الحصول على شفرة المصدر",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/ca.json b/translations/ca.json
index e363d3ee8..ae52e43a1 100644
--- a/translations/ca.json
+++ b/translations/ca.json
@@ -198,5 +198,7 @@
"Previous month": "Mes anterior",
"Next month": "El mes que ve",
"Get the source code": "Obteniu el codi font",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/cy.json b/translations/cy.json
index ea572c6be..97598567d 100644
--- a/translations/cy.json
+++ b/translations/cy.json
@@ -198,5 +198,7 @@
"Previous month": "Y mis blaenorol",
"Next month": "Mis nesaf",
"Get the source code": "Sicrhewch y cod ffynhonnell",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/de.json b/translations/de.json
index 189eac6c0..b0973426a 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -198,5 +198,7 @@
"Previous month": "Vorheriger Monat",
"Next month": "Nächsten Monat",
"Get the source code": "Holen Sie sich den Quellcode",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/en.json b/translations/en.json
index 970c3bf44..7b73e5cb8 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -198,5 +198,7 @@
"Previous month": "Previous month",
"Next month": "Next month",
"Get the source code": "Get the source code",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/es.json b/translations/es.json
index f78f9a5ae..cb597a501 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -198,5 +198,7 @@
"Previous month": "Mes anterior",
"Next month": "Próximo mes",
"Get the source code": "Obtén el código fuente",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/fr.json b/translations/fr.json
index 8f8c87fe1..65f1fc7a6 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -198,5 +198,7 @@
"Previous month": "Le mois précédent",
"Next month": "Le mois prochain",
"Get the source code": "Obtenir le code source",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/ga.json b/translations/ga.json
index 5b4097c6f..ef2741f18 100644
--- a/translations/ga.json
+++ b/translations/ga.json
@@ -198,5 +198,7 @@
"Previous month": "An mhí roimhe seo",
"Next month": "An mhí seo chugainn",
"Get the source code": "Faigh an cód foinse",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/hi.json b/translations/hi.json
index 61686e783..87cc706d6 100644
--- a/translations/hi.json
+++ b/translations/hi.json
@@ -198,5 +198,7 @@
"Previous month": "पिछ्ला महिना",
"Next month": "अगले महीने",
"Get the source code": "स्रोत कोड प्राप्त करें",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/it.json b/translations/it.json
index 2700c3617..e06eae2f6 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -198,5 +198,7 @@
"Previous month": "Il mese scorso",
"Next month": "Il prossimo mese",
"Get the source code": "Ottieni il codice sorgente",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/ja.json b/translations/ja.json
index 6c88672cb..7b17bc037 100644
--- a/translations/ja.json
+++ b/translations/ja.json
@@ -198,5 +198,7 @@
"Previous month": "前月",
"Next month": "来月",
"Get the source code": "ソースコードを入手する",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/oc.json b/translations/oc.json
index fcd5ffacf..9e05e4d32 100644
--- a/translations/oc.json
+++ b/translations/oc.json
@@ -194,5 +194,7 @@
"Previous month": "Previous month",
"Next month": "Next month",
"Get the source code": "Get the source code",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/pt.json b/translations/pt.json
index 04091833c..4fbb58ce6 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -198,5 +198,7 @@
"Previous month": "Mês anterior",
"Next month": "Próximo mês",
"Get the source code": "Obter o código fonte",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/ru.json b/translations/ru.json
index 04e981e4d..325ca68cb 100644
--- a/translations/ru.json
+++ b/translations/ru.json
@@ -198,5 +198,7 @@
"Previous month": "Предыдущий месяц",
"Next month": "В следующем месяце",
"Get the source code": "Получить исходный код",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/translations/zh.json b/translations/zh.json
index c0d02963f..4bd94c05d 100644
--- a/translations/zh.json
+++ b/translations/zh.json
@@ -198,5 +198,7 @@
"Previous month": "前一个月",
"Next month": "下个月",
"Get the source code": "获取源代码",
- "This is a media instance": "This is a media instance"
+ "This is a media instance": "This is a media instance",
+ "Mute this post": "Mute this post",
+ "Undo mute": "Undo mute"
}
diff --git a/utils.py b/utils.py
index e925aff4b..e7327c471 100644
--- a/utils.py
+++ b/utils.py
@@ -312,6 +312,19 @@ def deletePost(baseDir: str,httpPrefix: str,nickname: str,domain: str,postFilena
# remove any attachment
removeAttachment(baseDir,httpPrefix,domain,postJsonObject)
+ # remove any mute file
+ muteFilename=postFilename+'.muted'
+ if os.path.isfile(muteFilename):
+ os.remove(muteFilename)
+
+ # remove cached html version of the post
+ cachedPostFilename= \
+ getCachedPostFilename(baseDir,nickname,postJsonObject)
+ if cachedPostFilename:
+ if os.path.isfile(cachedPostFilename):
+ os.remove(cachedPostFilename)
+ #removePostFromCache(postJsonObject,recentPostsCache)
+
hasObject=False
if postJsonObject.get('object'):
hasObject=True
diff --git a/webinterface.py b/webinterface.py
index 2c9907d05..a6ebe5c10 100644
--- a/webinterface.py
+++ b/webinterface.py
@@ -1995,6 +1995,18 @@ def preparePostFromHtmlCache(postHtml: str,boxName: str,pageNumber: int) -> str:
postHtml=postHtml.replace('?tl=inbox','?tl=tlbookmarks')
return postHtml.replace(';-999;',';'+str(pageNumber)+';').replace('?page=-999','?page='+str(pageNumber))
+def postIsMuted(baseDir: str,nickname: str,domain: str, messageId: str) -> bool:
+ """ Returns true if the given post is muted
+ """
+ postDir=baseDir+'/accounts/'+nickname+'@'+domain
+ muteFilename=postDir+'/inbox/'+messageId.replace('/','#')+'.json.muted'
+ if os.path.isfile(muteFilename):
+ return True
+ muteFilename=postDir+'/outbox/'+messageId.replace('/','#')+'.json.muted'
+ if os.path.isfile(muteFilename):
+ return True
+ return False
+
def individualPostAsHtml(recentPostsCache: {},maxRecentPosts: int, \
iconsDir: str,translate: {}, \
pageNumber: int,baseDir: str, \
@@ -2238,14 +2250,24 @@ def individualPostAsHtml(recentPostsCache: {},maxRecentPosts: int, \
'?tl='+boxName+'" title="'+bookmarkTitle+'">'
bookmarkStr+=''
+ isMuted=postIsMuted(baseDir,nickname,domain,messageId)
+
deleteStr=''
+ muteStr=''
if allowDeletion or \
('/'+fullDomain+'/' in postActor and \
postJsonObject['object']['id'].startswith(postActor)):
if '/users/'+nickname+'/' in postJsonObject['object']['id']:
deleteStr=''
deleteStr+='
'
-
+ else:
+ if not isMuted:
+ muteStr=''
+ muteStr+='
'
+ else:
+ muteStr=''
+ muteStr+='
'
+
replyAvatarImageInPost=''
if showRepeatIcon:
if isAnnounced:
@@ -2468,7 +2490,7 @@ def individualPostAsHtml(recentPostsCache: {},maxRecentPosts: int, \
if showIcons:
footerStr='