diff --git a/daemon.py b/daemon.py index 592a07116..e78989fea 100644 --- a/daemon.py +++ b/daemon.py @@ -3436,6 +3436,7 @@ class PubServer(BaseHTTPRequestHandler): if fields['mediaInstance'] == 'on': self.server.mediaInstance = True self.server.blogsInstance = False + self.server.newsInstance = False self.server.defaultTimeline = 'tlmedia' setConfigParam(baseDir, "mediaInstance", @@ -3443,6 +3444,9 @@ class PubServer(BaseHTTPRequestHandler): setConfigParam(baseDir, "blogsInstance", self.server.blogsInstance) + setConfigParam(baseDir, + "newsInstance", + self.server.newsInstance) else: if self.server.mediaInstance: self.server.mediaInstance = False @@ -3451,6 +3455,32 @@ class PubServer(BaseHTTPRequestHandler): "mediaInstance", self.server.mediaInstance) + # change news instance status + if fields.get('newsInstance'): + self.server.newsInstance = False + self.server.defaultTimeline = 'inbox' + if fields['mediaInstance'] == 'on': + self.server.newsInstance = True + self.server.blogsInstance = False + self.server.mediaInstance = False + self.server.defaultTimeline = 'tlnews' + setConfigParam(baseDir, + "mediaInstance", + self.server.mediaInstance) + setConfigParam(baseDir, + "blogsInstance", + self.server.blogsInstance) + setConfigParam(baseDir, + "newsInstance", + self.server.newsInstance) + else: + if self.server.newsInstance: + self.server.newsInstance = False + self.server.defaultTimeline = 'inbox' + setConfigParam(baseDir, + "newsInstance", + self.server.mediaInstance) + # change blog instance status if fields.get('blogsInstance'): self.server.blogsInstance = False @@ -3458,6 +3488,7 @@ class PubServer(BaseHTTPRequestHandler): if fields['blogsInstance'] == 'on': self.server.blogsInstance = True self.server.mediaInstance = False + self.server.newsInstance = False self.server.defaultTimeline = 'tlblogs' setConfigParam(baseDir, "blogsInstance", @@ -3465,6 +3496,9 @@ class PubServer(BaseHTTPRequestHandler): setConfigParam(baseDir, "mediaInstance", self.server.mediaInstance) + setConfigParam(baseDir, + "newsInstance", + self.server.newsInstance) else: if self.server.blogsInstance: self.server.blogsInstance = False @@ -8632,13 +8666,16 @@ class PubServer(BaseHTTPRequestHandler): nickname = nickname.split('/')[0] self._setMinimal(nickname, not self._isMinimal(nickname)) if not (self.server.mediaInstance or - self.server.blogsInstance): + self.server.blogsInstance or + self.server.newsInstance): self.path = '/users/' + nickname + '/inbox' else: if self.server.blogsInstance: self.path = '/users/' + nickname + '/tlblogs' - else: + elif self.server.mediaInstance: self.path = '/users/' + nickname + '/tlmedia' + else: + self.path = '/users/' + nickname + '/tlnews' # search for a fediverse address, shared item or emoji # from the web interface by selecting search icon @@ -11166,7 +11203,9 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None: tokensLookup[token] = nickname -def runDaemon(blogsInstance: bool, mediaInstance: bool, +def runDaemon(newsInstance: bool, + blogsInstance: bool, + mediaInstance: bool, maxRecentPosts: int, enableSharedInbox: bool, registration: bool, language: str, projectVersion: str, @@ -11230,11 +11269,14 @@ def runDaemon(blogsInstance: bool, mediaInstance: bool, httpd.useBlurHash = useBlurHash httpd.mediaInstance = mediaInstance httpd.blogsInstance = blogsInstance + httpd.newsInstance = newsInstance httpd.defaultTimeline = 'inbox' if mediaInstance: httpd.defaultTimeline = 'tlmedia' if blogsInstance: httpd.defaultTimeline = 'tlblogs' + if newsInstance: + httpd.defaultTimeline = 'tlnews' # load translations dictionary httpd.translate = {} diff --git a/epicyon.py b/epicyon.py index 1c0912c6e..9cb4eb300 100644 --- a/epicyon.py +++ b/epicyon.py @@ -195,6 +195,9 @@ parser.add_argument("--mediainstance", type=str2bool, nargs='?', parser.add_argument("--blogsinstance", type=str2bool, nargs='?', const=True, default=False, help="Blogs Instance - favor blogs over microblogging") +parser.add_argument("--newsinstance", type=str2bool, nargs='?', + const=True, default=False, + help="News Instance - favor news over microblogging") parser.add_argument("--debug", type=str2bool, nargs='?', const=True, default=False, help="Show debug messages") @@ -626,6 +629,15 @@ if not args.mediainstance: args.mediainstance = mediaInstance if args.mediainstance: args.blogsinstance = False + args.newsinstance = False + +if not args.newsinstance: + newsInstance = getConfigParam(baseDir, 'newsInstance') + if newsInstance is not None: + args.newsinstance = newsInstance + if args.newsinstance: + args.blogsinstance = False + args.mediainstance = False if not args.blogsinstance: blogsInstance = getConfigParam(baseDir, 'blogsInstance') @@ -633,6 +645,7 @@ if not args.blogsinstance: args.blogsinstance = blogsInstance if args.blogsinstance: args.mediainstance = False + args.newsinstance = False # set the instance title in config.json title = getConfigParam(baseDir, 'instanceTitle') @@ -1898,7 +1911,8 @@ if setTheme(baseDir, themeName): print('Theme set to ' + themeName) if __name__ == "__main__": - runDaemon(args.blogsinstance, args.mediainstance, + runDaemon(args.newsinstance, + args.blogsinstance, args.mediainstance, args.maxRecentPosts, not args.nosharedinbox, registration, args.language, __version__, diff --git a/person.py b/person.py index 19e8243d4..6eb196708 100644 --- a/person.py +++ b/person.py @@ -23,6 +23,7 @@ from webfinger import storeWebfingerEndpoint from posts import createDMTimeline from posts import createRepliesTimeline from posts import createMediaTimeline +from posts import createNewsTimeline from posts import createBlogsTimeline from posts import createBookmarksTimeline from posts import createEventsTimeline @@ -591,7 +592,7 @@ def personBoxJson(recentPostsCache: {}, """ if boxname != 'inbox' and boxname != 'dm' and \ boxname != 'tlreplies' and boxname != 'tlmedia' and \ - boxname != 'tlblogs' and \ + boxname != 'tlblogs' and boxname != 'tlnews' and \ boxname != 'outbox' and boxname != 'moderation' and \ boxname != 'tlbookmarks' and boxname != 'bookmarks' and \ boxname != 'tlevents': @@ -659,6 +660,10 @@ def personBoxJson(recentPostsCache: {}, return createMediaTimeline(session, baseDir, nickname, domain, port, httpPrefix, noOfItems, headerOnly, pageNumber) + elif boxname == 'tlnews': + return createNewsTimeline(session, baseDir, nickname, domain, port, + httpPrefix, noOfItems, headerOnly, + pageNumber) elif boxname == 'tlblogs': return createBlogsTimeline(session, baseDir, nickname, domain, port, httpPrefix, noOfItems, headerOnly, diff --git a/posts.py b/posts.py index 37d947371..739f565ce 100644 --- a/posts.py +++ b/posts.py @@ -505,7 +505,8 @@ def deleteAllPosts(baseDir: str, """Deletes all posts for a person from inbox or outbox """ if boxname != 'inbox' and boxname != 'outbox' and \ - boxname != 'tlblogs' and boxname != 'tlevents': + boxname != 'tlblogs' and boxname != 'tlnews' and \ + boxname != 'tlevents': return boxDir = createPersonDir(nickname, domain, baseDir, boxname) for deleteFilename in os.scandir(boxDir): @@ -527,7 +528,8 @@ def savePostToBox(baseDir: str, httpPrefix: str, postId: str, Returns the filename """ if boxname != 'inbox' and boxname != 'outbox' and \ - boxname != 'tlblogs' and boxname != 'tlevents' and \ + boxname != 'tlblogs' and boxname != 'tlnews' and \ + boxname != 'tlevents' and \ boxname != 'scheduled': return None originalDomain = domain @@ -2504,6 +2506,15 @@ def createMediaTimeline(session, baseDir: str, nickname: str, domain: str, pageNumber) +def createNewsTimeline(session, baseDir: str, nickname: str, domain: str, + port: int, httpPrefix: str, itemsPerPage: int, + headerOnly: bool, pageNumber=None) -> {}: + return createBoxIndexed({}, session, baseDir, 'tlnews', nickname, + domain, port, httpPrefix, + itemsPerPage, headerOnly, True, + pageNumber) + + def createOutbox(session, baseDir: str, nickname: str, domain: str, port: int, httpPrefix: str, itemsPerPage: int, headerOnly: bool, authorized: bool, @@ -2775,7 +2786,7 @@ def addPostStringToTimeline(postStr: str, boxname: str, elif boxname == 'tlreplies': if boxActor not in postStr: return False - elif boxname == 'tlblogs': + elif boxname == 'tlblogs' or boxname == 'tlnews': if '"Create"' not in postStr: return False if '"Article"' not in postStr: @@ -2812,7 +2823,7 @@ def createBoxIndexed(recentPostsCache: {}, if boxname != 'inbox' and boxname != 'dm' and \ boxname != 'tlreplies' and boxname != 'tlmedia' and \ - boxname != 'tlblogs' and \ + boxname != 'tlblogs' and boxname != 'tlnews' and \ boxname != 'outbox' and boxname != 'tlbookmarks' and \ boxname != 'bookmarks' and \ boxname != 'tlevents': diff --git a/tests.py b/tests.py index cc0a472c8..8d9a2bd5e 100644 --- a/tests.py +++ b/tests.py @@ -287,7 +287,8 @@ def createServerAlice(path: str, domain: str, port: int, onionDomain = None i2pDomain = None print('Server running: Alice') - runDaemon(False, False, 5, True, True, 'en', __version__, + runDaemon(False, False, False, + 5, True, True, 'en', __version__, "instanceId", False, path, domain, onionDomain, i2pDomain, None, port, port, httpPrefix, federationList, maxMentions, maxEmoji, False, @@ -349,7 +350,8 @@ def createServerBob(path: str, domain: str, port: int, onionDomain = None i2pDomain = None print('Server running: Bob') - runDaemon(False, False, 5, True, True, 'en', __version__, + runDaemon(False, False, False, + 5, True, True, 'en', __version__, "instanceId", False, path, domain, onionDomain, i2pDomain, None, port, port, httpPrefix, federationList, maxMentions, maxEmoji, False, @@ -385,7 +387,8 @@ def createServerEve(path: str, domain: str, port: int, federationList: [], onionDomain = None i2pDomain = None print('Server running: Eve') - runDaemon(False, False, 5, True, True, 'en', __version__, + runDaemon(False, False, False, + 5, True, True, 'en', __version__, "instanceId", False, path, domain, onionDomain, i2pDomain, None, port, port, httpPrefix, federationList, maxMentions, maxEmoji, False, diff --git a/translations/ar.json b/translations/ar.json index 0b9ffa554..ed00b4e6d 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -302,5 +302,7 @@ "Discuss": "مناقشة", "Moderator Discussion": "مناقشة المنسق", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/ca.json b/translations/ca.json index 7d1daca4d..1a2521d80 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -302,5 +302,7 @@ "Discuss": "Discuteix", "Moderator Discussion": "Discussió sobre moderadors", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/cy.json b/translations/cy.json index 67522c007..5d32efd9e 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -302,5 +302,7 @@ "Discuss": "Trafodwch", "Moderator Discussion": "Trafodaeth Cymedrolwr", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/de.json b/translations/de.json index 0f1819f6e..736c0dfd2 100644 --- a/translations/de.json +++ b/translations/de.json @@ -302,5 +302,7 @@ "Discuss": "Diskutieren", "Moderator Discussion": "Moderatorendiskussion", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/en.json b/translations/en.json index a5a9a06b5..420dfec52 100644 --- a/translations/en.json +++ b/translations/en.json @@ -302,5 +302,7 @@ "Discuss": "Discuss", "Moderator Discussion": "Moderator Discussion", "Vote": "Vote", - "Remove Vote": "Remove Vote" + "Remove Vote": "Remove Vote", + "This is a news instance": "This is a news instance", + "News": "News" } diff --git a/translations/es.json b/translations/es.json index ec0d739fc..0ddbbfaa1 100644 --- a/translations/es.json +++ b/translations/es.json @@ -302,5 +302,7 @@ "Discuss": "Discutir", "Moderator Discussion": "Discusión del moderador", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/fr.json b/translations/fr.json index ed75d08c7..8768d0de6 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -302,5 +302,7 @@ "Discuss": "Discuter", "Moderator Discussion": "Discussion du modérateur", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/ga.json b/translations/ga.json index 230498980..0b76ea9a1 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -302,5 +302,7 @@ "Discuss": "Pléigh", "Moderator Discussion": "Plé Modhnóir", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/hi.json b/translations/hi.json index e11084c3f..8da90263a 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -302,5 +302,7 @@ "Discuss": "चर्चा करें", "Moderator Discussion": "मॉडरेटर चर्चा", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/it.json b/translations/it.json index ff891a91d..4963e9326 100644 --- a/translations/it.json +++ b/translations/it.json @@ -302,5 +302,7 @@ "Discuss": "Discutere", "Moderator Discussion": "Discussione del moderatore", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/ja.json b/translations/ja.json index c79ceaf4d..e3dc6f87e 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -302,5 +302,7 @@ "Discuss": "議論する", "Moderator Discussion": "モデレーターディスカッション", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/oc.json b/translations/oc.json index a2304146a..99eae9ad6 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -298,5 +298,7 @@ "Discuss": "Discuss", "Moderator Discussion": "Moderator Discussion", "Vote": "Vote", - "Remove Vote": "Remove Vote" + "Remove Vote": "Remove Vote", + "This is a news instance": "This is a news instance", + "News": "News" } diff --git a/translations/pt.json b/translations/pt.json index 2c8dc07b5..b11639e0f 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -302,5 +302,7 @@ "Discuss": "Discutir", "Moderator Discussion": "Discussão do moderador", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/ru.json b/translations/ru.json index e9465e880..a1b5e091f 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -302,5 +302,7 @@ "Discuss": "Обсудить", "Moderator Discussion": "Обсуждение модератором", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/translations/zh.json b/translations/zh.json index 9da0fbfe5..2d3a7e0cc 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -302,5 +302,7 @@ "Discuss": "讨论", "Moderator Discussion": "主持人讨论", "Vote": "", - "Remove Vote": "" + "Remove Vote": "", + "This is a news instance": "", + "News": "" } diff --git a/utils.py b/utils.py index 59124cd8f..323292acc 100644 --- a/utils.py +++ b/utils.py @@ -728,7 +728,7 @@ def validNickname(domain: str, nickname: str) -> bool: 'public', 'followers', 'channel', 'calendar', 'tlreplies', 'tlmedia', 'tlblogs', - 'tlevents', + 'tlevents', 'tlblogs', 'moderation', 'activity', 'undo', 'reply', 'replies', 'question', 'like', 'likes', 'users', 'statuses', diff --git a/webinterface.py b/webinterface.py index e987271d9..1198a248d 100644 --- a/webinterface.py +++ b/webinterface.py @@ -1374,6 +1374,7 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str, hideLikeButton = '' mediaInstanceStr = '' blogsInstanceStr = '' + newsInstanceStr = '' displayNickname = nickname bioStr = '' donateUrl = '' @@ -1432,12 +1433,21 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str, if mediaInstance is True: mediaInstanceStr = 'checked' blogsInstanceStr = '' + newsInstanceStr = '' + + newsInstance = getConfigParam(baseDir, "newsInstance") + if newsInstance: + if newsInstance is True: + newsInstanceStr = 'checked' + blogsInstanceStr = '' + mediaInstanceStr = '' blogsInstance = getConfigParam(baseDir, "blogsInstance") if blogsInstance: if blogsInstance is True: blogsInstanceStr = 'checked' mediaInstanceStr = '' + newsInstanceStr = '' filterStr = '' filterFilename = \ @@ -1781,6 +1791,10 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str, ' ' + \ translate['This is a blogging instance'] + '
\n' + editProfileForm += \ + ' ' + \ + translate['This is a news instance'] + '
\n' editProfileForm += ' \n' editProfileForm += '
\n' @@ -5596,6 +5610,7 @@ def htmlTimeline(defaultTimeline: str, # the appearance of buttons - highlighted or not inboxButton = 'button' blogsButton = 'button' + newsButton = 'button' dmButton = 'button' if newDM: dmButton = 'buttonhighlighted' @@ -5616,6 +5631,8 @@ def htmlTimeline(defaultTimeline: str, inboxButton = 'buttonselected' elif boxName == 'tlblogs': blogsButton = 'buttonselected' + elif boxName == 'tlnews': + newsButton = 'buttonselected' elif boxName == 'dm': dmButton = 'buttonselected' if newDM: @@ -5812,6 +5829,12 @@ def htmlTimeline(defaultTimeline: str, '/tlblogs">\n' + elif defaultTimeline == 'tlnews': + tlStr += \ + ' \n' else: tlStr += \ ' ' + translate['Inbox'] + \ '\n' + # typically the news button + # but may change if this is a news oriented instance + if defaultTimeline != 'tlnews': + if not minimal: + tlStr += \ + ' \n' + else: + if not minimal: + tlStr += \ + ' \n' + # button for the outbox tlStr += \ '