def reply_t(host, thread): now = str(int(time.time())) if request.method == 'POST': if request.form['sub'] == "Reply": author = request.form["author"] or "Anonymous" message = request.form["message"] if not message: return "please write a message" if not whitelist.approve(): return "please solve <a href='/captcha'>the captcha</a>" tpath = "/".join(["./threads", host, thread, "local.txt"]) flood = whitelist.flood(s.post) if flood: return flood writer.rep_t(host, thread, now, author, message) writer.update_host(host, thread, now) redir = f"/threads/{host}/{thread}" return f"<center><h1><a href='{redir}'>View updated thread</a></h1></center>" tpage = view_t(host, thread) canpost = whitelist.approve() lock = 0 if os.path.isfile(f"./threads/{host}/{thread}/lock"): lock = 1 if not canpost: replf = whitelist.show_captcha(1, f"/threads/{host}/{thread}/") elif lock: replf = "<hr> <div> 🔒 Thread has been locked. No more comments are allowed.</div>" else: replf = newr.format(host, thread) tpage += replf return p.mk(str(tpage))
def tag_page(topic): line = "<tr><td>{0} " \ + "<td><a href='/threads/{0}/{1}'>{5}</a>" \ + "<td>{4}" result = [] ot = "".join(topic) if "+" in topic: topic = topic.split("+") else: topic = [topic] result.append("<div><h1> #" + " #".join(topic) + "</h1>") result.append(" <a href='/create/" + ot + "'>+ create new</a><br>") result.append("<i>Note: tags can be combined using the " "+ (plus sign) in the URL</i></div>") result.append("<p><table>") result.append("<tr><th>origin<th>title<th>replies") threads = tags_threads(topic) with open("./threads/list.txt") as site: site = site.read().splitlines() site = [s.split(" ") for s in site] site = [[*s[:5], " ".join(s[5:])] for s in site if [s[0], s[1]] in threads] result[0] += " (" + str(len(site)) + " threads)</h1>" test = "\n".join([line.format(*t) for t in site]) result.append(test) result.append("</table>") result = p.mk("\n".join(result)) return result
def browse(board): if request.method == 'POST': if not whitelist.approve(): return p.mk(whitelist.show_captcha(1)) user_key = tr.sec(request.form["key"]) with open(index_p, "r") as index: index = index.read().splitlines() local_b = [i.split(" ") for i in index] test = [i for i in local_b if (i[0] == board and i[1] == user_key)] if not len(test): pass files = ["info.txt", "hide.txt", "threads.txt", "ihosts.txt"] try: for f in files: path = "./boards/" + board + "/" data = request.form[f].strip() with open(path + f, "w") as out: out.write(data) except: print(board) info = f"./boards/{board}/info.txt" with open(info, "r") as about: about = about.read() page = ["<div>"] page.append(f"<a href='/b'>[back]</a>") page.append(f"<h1>/{board}/</h1>") page.append( f"<link rel='alternative' type='application/xml' href='/atom/tag/{board}.atom'>" ) page.append(about) page.append( f"<p><hr><a href='/create/{board}'>[+] Create a new thread on /{board}/</a>" ) with open(f"./boards/{board}/ihosts.txt", "r") as ihosts: ihosts = ihosts.read().strip().splitlines() page.append("<hr><b>Image hosts: </b>" + " ♥ ".join(ihosts)) page.append("<hr><ul>") threads = board_index(board) # threads = "\n".join(threads) page += threads page.append("</ul>") page = "\n".join([n for n in page if (len(n) != 2)]) return p.mk(page)
def view_all(): tops = all_index() tops[0] = f"<header><hr>({len(tops)} discussions) ♦ " \ + "<a href='/create'>Add new</a></header>" \ + "<h1>All Sites</h1><table>" \ + "<tr><th>origin<th>title<th>replies" \ + "<tr>" + tops[0] page = p.mk(hostlist() + "<tr>".join(tops) + "</table>") return page
def show_captcha(hide=0, redir=''): ip = get_ip() mylog = addlog(ip) logtxt = json.dumps(mylog) out = "" if not hide: out = p.html("captcha") out += p.html("captcha-form").format(mylog[ip][1], redir) if hide: return out return p.mk(out)
def login(pw): page = "" hpw = bytes(pw, "utf-8") hashed = hash(hpw) if hashed != s.phash: return "password?" cook = f"""<meta http-equiv="set-cookie" content="p={pw}">\n""" page += "<pre>" page += """* <a href="#log">log</a> * <a href="#ips">ips</a> * <a href="#delete">delete</a> * <a href="#bans">bans</a> * <a href="#friends">friends</a> * tags * threads * an example thread """ # Show the comment / thread log page += "<h1 id='log'>#log</h1>" page += "site | thread | reply | ip\n" with open("../0chan.vip/log.txt", "r") as log: log = log.read().splitlines()[::-1] for n, x in enumerate(log): x = x.split(" ") x[-1] = ".".join(x[-1].split(".")[:2]) log[n] = " ".join(x) page += "\n".join(log) # Show the trash posts page += "</pre><hr><h1 id='delete'>#delete</h1><pre>" with open("../0chan.vip/delete.txt", "r") as delete: delete = delete.read().splitlines()[::-1] page += "\n".join(delete) page += "</pre><hr><h1 id='ips'>#ips</h1><pre>" with open("../0chan.vip/ips.txt", "r") as ips: ips = ips.read() page += "time | ip | captcha | approved time\n" page += ips # Show the bans page += "</pre><hr><h1 id='bans'>#bans</h1><pre>" with open("../0chan.vip/bans.txt", "r") as bans: bans = bans.read() page += bans # Show friends page += "</pre><hr><h1 id='friends'>#friends</h1><pre>" with open("../0chan.vip/threads/friends.txt", "r") as friends: friends = friends.read() page += friends page += "</pre>" return p.mk(page)
def show_thread(board, host, thread, methods=['POST', 'GET']): datetime = "%a, %b %d, %Y, @ %-I %p" test = mod_board(board, host) tindex = load_thread(board, host, thread) # [[host, time, author, comment]] tindex = [[ x[0], time.strftime(datetime, time.localtime(int(x[1]))), *x[2:] ] for x in tindex] head = f"./threads/{host}/{thread}/head.txt" with open(head, "r") as head: head = head.read().splitlines()[0] page = ["<div class='threads'>"] page.append(f"{s.name} <a href='/b/{board}'>/{board}/</a>") page.append(f"<h2>{head}</h2>") cnt = {} render = [] with open("./templ/post.t", "r") as reply: reply = reply.read() for t in tindex: with open(f"./boards/{board}/ihosts.txt", "r") as ihosts: ihosts = ihosts.read().splitlines() if t[0] not in cnt: cnt[t[0]] = 0 cnt[t[0]] += 1 b = [t[0], s.friends[t[0]]] ref = f"{b[1]}/{cnt[b[0]]}" link = f"<a href='#{ref}' " link += f"onclick='quote(\"{ref}\")' id='{ref}'>" link += f">>{b[0]}/{cnt[b[0]]}</a>" for i in ihosts: print([i, t[3]]) if i in t[3]: t[3] = u.imgur(t[3], i) break # 0 reply, # 1 date, #2 name, #3 comment, #4 host # 0 host, # 1 time, #2 author, #3 comment page.append(reply.format(link, t[1], t[2], t[3], "")) canpost = whitelist.approve() with open("./templ/newr.t", "r") as newr: newr = newr.read().format(host, thread) if not canpost: replf = whitelist.show_captcha(1, f"/threads/{host}/{thread}/") else: replf = newr.format(board, thread) page.append(replf) page.append("</div>") return p.mk("<br>".join(page))
def new_thread(t="random"): if request.method == 'POST': if not whitelist.approve(): return "You need to solve <a href='/captcha/'>the " \ + "captcha</a> before you can post." if request.form['sub'] == "Create chat": flood = whitelist.flood(s.thread, "thread") if flood: return flood mk_op(title=request.form['title'], tag=request.form['tag'], author=request.form['author'], msg=request.form['message']) return "<center><h1>" \ + "Posting thread.....<p>" \ + "<a href='/threads/'>(back)</a></h1></center>" # if not t=tag , t = random if not len(t): t = "random" if not whitelist.approve(): return (p.mk(whitelist.show_captcha(1) + newtt.format(t))) return p.mk(newtt.format(t))
def view(host): # tlist() takes host input if host and host in s.friends: url = s.friends[host] tops = tlist(host) tops[0] = f"<header>({len(tops)} discussions) ♦ " \ + "<a href='/create'>Add new</a> ♦ " \ + f"from <a href='{url}'>{url}</a></header>" \ + f"<h1>{host}</h1><table>" \ + "<tr><th>title<th>replies" \ + "<tr>" + tops[0] else: tops = tlist() tops[0] = "<h1>All Sites</h1><ol><li>" + tops[0] if host == "sageru": tops[0] = u.bees + tops[0] tops[0] = hostlist() + tops[0] return p.mk("<tr>".join(tops) + "</table>\n")
def splash(): with open(index_p, "r") as index: index = index.read().splitlines() local_b = [i.split(" ") for i in index] boards = local_b template = "<li><a href='/b/{0}'>{0}</a> (managed by <b><code>{1}</code></b>)" page = """<h1>User Boards</h1><div class="info"> Boards are a work in progress system that will allow user-managed communities to exist within the Multichan network. <br>Register a board by visiting <code>/b/tagname/password</code> , where <i>tagname</i> is a <a href="/tags/">tag</a> that exists and password is a secret password. HTML can be used in <code>intro.txt</code> ; moderating threads is done by adding new entries to <code>threads.txt</code> and moderating comments is done by adding new entries to <code>hide.txt</code> . One entry per line. </div><p>""" page += "<div><ul>" \ + "\n".join([template.format(*i) for i in boards]) \ + "</ul></div>" return p.mk(page)
def friends(): title = "<div><h1>Friends of " + s.name title += "</h1><h4>" + s.url if s.images: title += f"<p>images: <a href='{s.ihost}'>{s.ihost}</a><br>" else: title += "<p>Images not enabled!" if s.boards: title += "<br><a href='/b/'>Boards enabled</a>" else: title += "<br>Boards not enabled!" title += "</h4>" title += "Friends are other multichan websites that " title += "this server downloads threads and comments from." flist = [] fstring = "<li> <a href='{1}'>{0}</a> {1}" for f in s.friends: flist.append(fstring.format(f, s.friends[f])) flist = "<ul>" + "\n".join(flist) + "</ul>" page = title + flist + "</div>" return p.mk(page)
def tag_index(): tdb = tags_load() sentry = "<li><b><a href='/tags/{0}/'>{0}</a></b> ({1} discussions)" oentry = "<li><a href='/tags/{0}/'>{0}</a> ({1} discussions)" result = [ "<div><h1>Conversation tags</h1>", "Bolded tags are the default tags selected by the site admin." ] result.append("<br>Tags can be combined with the '+' plus sign in URL.") links = ["<ul>"] site_tags = {t: len(tdb[t]) for t in tlist} site_tags = { k: v for k, v in sorted(site_tags.items(), key=lambda x: int(x[1]))[::-1] } all_tags = {t: len(tdb[t]) for t in list(tdb.keys()) if t not in tlist} all_tags = { k: v for k, v in sorted(all_tags.items(), key=lambda x: int(x[1]))[::-1] } for t in site_tags: links.append(sentry.format(t, site_tags[t])) if site_tags[t] == 1: links[-1] == links[-1].replace("s)", ")") links.append("</ul><ul>") cnt = 0 last = 0 for t in all_tags: cnt = int(all_tags[t]) if (cnt < last) and (cnt == 1): links.append("</ul><ul>") links.append(oentry.format(t, all_tags[t])) if all_tags[t] == 1: links[-1] = links[-1].replace("s)", ")") last = cnt links.append("</ul></div>") result.append("\n".join(links)) result = p.mk("\n".join(result)) return result
def counter(): with open("./static/counter.txt", "r") as cnt: cnt = int(cnt.read().strip()) with open("./static/counter.txt", "w") as update: update.write(str(cnt + 1)) with open(s.bans, "r") as bans: bans = bans.read().splitlines() with open(s.delete, "r") as dele: dele = dele.read().splitlines() with open("./threads/list.txt", "r") as threads: threads = threads.read().splitlines() with open("./threads/tags.txt", "r") as tags: tags = tags.read().splitlines() tcnt = str(len(threads)) lcnt = str(len([t for t in threads if t[:6] == "local "])) rcnt = str(sum([int(t.split(" ")[3]) for t in threads])) acnt = str(sum([int(t.split(" ")[4]) for t in threads])) dcnt = str(len(dele)) bcnt = str(len(bans)) tags = str(len(tags)) atags = str(len(s.tags)) page = [] page.append(" ".join([ f"<p><div>You are visitor #{cnt+1}", "to this stats page at", s.url, "<ul>" ])) page.append(" ".join(["<li>", str(len(s.friends)), "friend servers"])) page.append(" ".join(["<li>", atags, "featured tags"])) page.append(" ".join(["<li>", tags, "unique tags<p>"])) page.append(" ".join(["<li>", lcnt, "local threads"])) page.append(" ".join(["<li>", tcnt, "known threads<p>"])) page.append(" ".join(["<li>", rcnt, "local replies"])) page.append(" ".join(["<li>", acnt, "total replies<p>"])) page.append(" ".join(["<li>", dcnt, "deleted posts"])) page.append(" ".join(["<li>", bcnt, "banned addresses"])) page.append("</ul></div>") return p.mk("\n".join(page))
def mkboard(board, key): if not whitelist.approve(): return p.mk(whitelist.show_captcha(1)) key = tr.sec(key) path = "./boards/" + board + "/" try: os.mkdir(path) except: pass with open("./boards/list.txt", "a") as li: li.write(f"{board} {key}\n") try: os.mkdir(path) except: pass files = ["info.txt", "threads.txt", "hide.txt", "ihosts.txt"] for f in files: _path = path + f with open(_path, "w") as fi: if f == "ihosts.txt": fi.write(s.ihost) else: fi.write("")
def mod_board(board, key): new_local = [] if not whitelist.approve(): return p.mk(whitelist.show_captcha(1)) with open(index_p, "r") as index: index = index.read().splitlines() local_b = [i.split(" ") for i in index] bs = [x[0] for x in local_b] if board not in bs: mkboard(board, key) return str([board, key]) for L in local_b: if tr.sec(key) == L[1] and L[0] == board: new_local.append(L) if not len(new_local): return "0" page = ["<style>textarea {", "width: 800px; height:120px;}</style>"] page.append("<form action='.' method='post'>") page.append("<input type='submit' value='Moderate Board'>") page.append(f"<input type='hidden' name='board' value='{board}'>") page.append(f"<input type='hidden' name='key' value='{key}'>") mod = {} files = ["info.txt", "threads.txt", "hide.txt", "ihosts.txt"] for f in files: with open(f"./boards/{board}/{f}", "r") as data: data = data.read().strip() mod[f] = data + "\n" for f in mod: page.append(f) if f == "threads.txt": page[ -1] += " // format: host thread @ mode ; 0 hide ; 2 sticky; 3 sage" elif f == "hide.txt": page[-1] += " // format: host thread host reply# " page.append(f"<textarea name='{f}'>{mod[f]}</textarea>") return "<pre>" + "\n".join(page) + "</pre>"
def rules(): return p.mk(p.html("rules"))
def about(): return p.mk(p.html("about"))
def not_found(e): return p.mk(p.html("404"))
def hello_world(): return p.mk(p.html("home").format(s.name))