Procházet zdrojové kódy

Add server config file

Zed před 7 roky
rodič
revize
6a9d182249
8 změnil soubory, kde provedl 53 přidání a 23 odebrání
  1. 0 1
      README.md
  2. 9 0
      nitter.conf
  3. 1 0
      public/style.css
  4. 3 0
      src/cache.nim
  5. 1 4
      src/formatters.nim
  6. 23 13
      src/nitter.nim
  7. 8 0
      src/types.nim
  8. 8 5
      src/views/general.nim

+ 0 - 1
README.md

@@ -28,7 +28,6 @@ is on implementing missing features.
 - Search (images/videos, hashtags, etc.)
 - Custom timeline filter
 - Nitter link previews
-- Server configuration
 - More caching (waiting for [moigagoo/norm#19](https://github.com/moigagoo/norm/pull/19))
 - Simple account system with customizable feed
 - Video support with hls.js

+ 9 - 0
nitter.conf

@@ -0,0 +1,9 @@
+[Server]
+address = "0.0.0.0"
+port = 8080
+title = "nitter"
+staticDir = "./public"
+
+[Cache]
+directory = "/tmp/niter"
+profileMinutes = 10  # how long to cache profiles

+ 1 - 0
public/style.css

@@ -450,6 +450,7 @@ video {
     text-overflow: ellipsis;
     max-width: 100%;
     font-weight: bold;
+    overflow-wrap: break-word;
 }
 
 .profile-card-username {

+ 3 - 0
src/cache.nim

@@ -26,3 +26,6 @@ proc getCachedProfile*(username: string; force=false): Future[Profile] {.async.}
       result = await getProfile(username)
       if result.username.len > 0:
         result.insert()
+
+proc setProfileCacheTime*(minutes: int) =
+  profileCacheTime = initDuration(minutes=minutes)

+ 1 - 4
src/formatters.nim

@@ -69,10 +69,7 @@ proc getUserpic*(profile: Profile; style=""): string =
   getUserPic(profile.userpic, style)
 
 proc pageTitle*(profile: Profile): string =
-  &"{profile.fullname} (@{profile.username}) | Nitter"
-
-proc pageTitle*(page: string): string =
-  &"{page} | Nitter"
+  &"{profile.fullname} (@{profile.username})"
 
 proc getTime*(tweet: Tweet): string =
   tweet.time.format("d/M/yyyy', ' HH:mm:ss")

+ 23 - 13
src/nitter.nim

@@ -1,11 +1,13 @@
 import asyncdispatch, asyncfile, httpclient, strutils, strformat, uri, os
-import jester, regex
+from net import Port
 
-import api, utils, types, cache, formatters, search
+import jester, regex
 
+import api, utils, types, cache, formatters, search, config
 import views/[general, profile, status]
 
-const cacheDir {.strdefine.} = "/tmp/nitter"
+const configPath {.strdefine.} = "./nitter.conf"
+let cfg = getConfig(configPath)
 
 proc showTimeline(name, after: string; query: Option[Query]): Future[string] {.async.} =
   let
@@ -24,20 +26,27 @@ proc showTimeline(name, after: string; query: Option[Query]): Future[string] {.a
     return ""
 
   let profileHtml = renderProfile(profile, await timelineFut, await railFut)
-  return renderMain(profileHtml, title=pageTitle(profile))
+  return renderMain(profileHtml, title=cfg.title, titleText=pageTitle(profile))
 
 template respTimeline(timeline: typed) =
   if timeline.len == 0:
-    resp Http404, showError("User \"" & @"name" & "\" not found")
+    resp Http404, showError("User \"" & @"name" & "\" not found", cfg.title)
   resp timeline
 
+setProfileCacheTime(cfg.profileCacheTime)
+
+settings:
+  port = Port(cfg.port)
+  staticDir = cfg.staticDir
+  bindAddr = cfg.address
+
 routes:
   get "/":
-    resp renderMain(renderSearch(), title=pageTitle("Search"))
+    resp renderMain(renderSearch(), title=cfg.title, titleText="Search")
 
   post "/search":
     if @"query".len == 0:
-      resp Http404, showError("Please enter a username.")
+      resp Http404, showError("Please enter a username.", cfg.title)
     redirect("/" & @"query")
 
   get "/@name/?":
@@ -62,7 +71,7 @@ routes:
 
     let conversation = await getTweet(@"name", @"id")
     if conversation == nil or conversation.tweet.id.len == 0:
-      resp Http404, showError("Tweet not found")
+      resp Http404, showError("Tweet not found", cfg.title)
 
     let title = pageTitle(conversation.tweet.profile)
     resp renderMain(renderConversation(conversation), title=title)
@@ -74,13 +83,13 @@ routes:
     let
       uri = parseUri(decodeUrl(@"url"))
       path = uri.path.split("/")[2 .. ^1].join("/")
-      filename = cacheDir / cleanFilename(path & uri.query)
+      filename = cfg.cacheDir / cleanFilename(path & uri.query)
 
     if getHmac($uri) != @"sig":
-      resp showError("Failed to verify signature")
+      resp showError("Failed to verify signature", cfg.title)
 
-    if not existsDir(cacheDir):
-      createDir(cacheDir)
+    if not existsDir(cfg.cacheDir):
+      createDir(cfg.cacheDir)
 
     if not existsFile(filename):
       let client = newAsyncHttpClient()
@@ -92,6 +101,7 @@ routes:
 
     let file = openAsync(filename)
     defer: file.close()
+
     resp await readAll(file), mimetype(filename)
 
   get "/video/@sig/@url":
@@ -100,7 +110,7 @@ routes:
     let url = decodeUrl(@"url")
 
     if getHmac(url) != @"sig":
-      resp showError("Failed to verify signature")
+      resp showError("Failed to verify signature", cfg.title)
 
     let
       client = newAsyncHttpClient()

+ 8 - 0
src/types.nim

@@ -147,5 +147,13 @@ type
     beginning*: bool
     query*: Option[Query]
 
+  Config* = ref object
+    address*: string
+    port*: int
+    title*: string
+    staticDir*: string
+    cacheDir*: string
+    profileCacheTime*: int
+
 proc contains*(thread: Thread; tweet: Tweet): bool =
   thread.tweets.anyIt(it.id == tweet.id)

+ 8 - 5
src/views/general.nim

@@ -2,17 +2,20 @@ import karax/[karaxdsl, vdom]
 
 const doctype = "<!DOCTYPE html>\n"
 
-proc renderMain*(body: VNode; title="Nitter"): string =
+proc renderMain*(body: VNode; title="Nitter"; titleText=""): string =
   let node = buildHtml(html(lang="en")):
     head:
-      title: text title
+      if titleText.len > 0:
+        title: text titleText & " | " & title
+      else:
+        title: text title
       link(rel="stylesheet", `type`="text/css", href="/style.css")
 
     body:
       nav(id="nav", class="nav-bar container"):
         tdiv(class="inner-nav"):
           tdiv(class="item"):
-            a(href="/", class="site-name"): text "nitter"
+            a(href="/", class="site-name"): text title
 
       tdiv(id="content", class="container"):
         body
@@ -31,5 +34,5 @@ proc renderError*(error: string): VNode =
     tdiv(class="error-panel"):
       span: text error
 
-proc showError*(error: string): string =
-  renderMain(renderError(error), title = "Error | Nitter")
+proc showError*(error: string; title: string): string =
+  renderMain(renderError(error), title=title, titleText="Error")