def push_to_social_media_rss(request): import django.contrib.syndication.views from events.models import Feed from events.templatetags.events_utils import render_event import re feedlist = [Feed.from_name("misc:comingup"), Feed.from_name('misc:enactedbills')] class DjangoFeed(django.contrib.syndication.views.Feed): title = "GovTrack.us Is Tracking Congress" link = "/" description = "GovTrack tracks the activities of the United States Congress. We push this feed to our Twitter and Facebook accounts." def items(self): events = [render_event(item, feedlist) for item in Feed.get_events_for(feedlist, 25)] return [e for e in events if e != None] def item_title(self, item): return re.sub(r"^Legislation ", "", item["type"]) + ": " + item["title"] def item_description(self, item): return item["body_text"] def item_link(self, item): return settings.SITE_ROOT_URL + item["url"]# + "?utm_campaign=govtrack_push&utm_source=govtrack_push" def item_guid(self, item): return "http://www.govtrack.us/events/guid/" + item["guid"] def item_pubdate(self, item): return item["date"] if isinstance(item["date"], datetime) or item["date"] is None else datetime.combine(item["date"], time.min) return DjangoFeed()(request)
def push_to_social_media_rss(request): import django.contrib.syndication.views from events.models import Feed from events.templatetags.events_utils import render_event import re feedlist = [Feed.from_name("misc:comingup"), Feed.from_name('misc:enactedbills')] class DjangoFeed(django.contrib.syndication.views.Feed): title = "GovTrack.us Is Tracking Congress" link = "/" description = "GovTrack tracks the activities of the United States Congress. We push this feed to our Twitter and Facebook accounts." def items(self): events = [render_event(item, feedlist) for item in Feed.get_events_for(feedlist, 25)] return [e for e in events if e != None] def item_title(self, item): return re.sub(r"^Legislation ", "", item["type"]) + ": " + item["title"] def item_description(self, item): return item["body_text"] def item_link(self, item): return "http://www.govtrack.us" + item["url"]# + "?utm_campaign=govtrack_push&utm_source=govtrack_push" def item_guid(self, item): return "http://www.govtrack.us/events/guid/" + item["guid"] def item_pubdate(self, item): return item["date"] if isinstance(item["date"], datetime) or item["date"] is None else datetime.combine(item["date"], time.min) return DjangoFeed()(request)
def create_event(self): if self.congress < 111: return # not interested, creates too much useless data and slow to load from events.models import Feed, Event with Event.update(self) as E: E.add("vote", self.created, Feed.AllVotesFeed()) for v in self.voters.all(): if v.person_id: E.add("vote", self.created, Feed.PersonVotesFeed(v.person_id))
def build_info(): # feeds about all legislation that we offer the user to subscribe to feeds = [ f for f in Feed.get_simple_feeds() if f.category == "federal-bills" ] # info about bills by status groups = [ ( g[0], # title g[1], # text 1 g[2], # text 2 "/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]) + "&sort=-current_status_date", # link load_bill_status_qs(g[4]).count(), # count in category load_bill_status_qs(g[4]).order_by( '-current_status_date')[0:6], # top 6 in this category ) for g in bill_status_groups ] # legislation coming up dhg_bills = Bill.objects.filter( congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter( docs_house_gov_postdate__gt=F('current_status_date')) sfs_bills = Bill.objects.filter( congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter( senate_floor_schedule_postdate__gt=F('current_status_date')) coming_up = list( (dhg_bills | sfs_bills).order_by('scheduled_consideration_date')) # top tracked bills top_bills = Feed.objects\ .filter(feedname__startswith='bill:')\ .filter(feedname__regex='^bill:[hs][jcr]?%d-' % CURRENT_CONGRESS) top_bills = top_bills\ .annotate(count=Count('tracked_in_lists'))\ .order_by('-count')\ .values('feedname', 'count')\ [0:25] top_bills = [(Bill.from_feed(Feed.from_name(bf["feedname"])), bf["count"]) for bf in top_bills] return { "feeds": feeds, "total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(), "current_congress": CURRENT_CONGRESS, "current_congress_dates": get_congress_dates(CURRENT_CONGRESS), "groups": groups, "coming_up": coming_up, "top_tracked_bills": top_bills, "subjects": subject_choices(), "BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.reported), }
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = dict(base_context) # clone # Add top-tracked feeds. from events.models import Feed global trending_feeds if settings.DEBUG and False: trending_feeds = [None, []] elif not trending_feeds or trending_feeds[0] < datetime.datetime.now()-datetime.timedelta(hours=2): trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60*60*2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] context["trending_bill_feeds"] = [f for f in trending_feeds[1] if f.feedname.startswith("bill:")] # Add site-wide tracked events. all_tracked_events = cache.get("all_tracked_events") if not all_tracked_events: all_tracked_events = Feed.get_events_for([fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists()], 6) cache.set("all_tracked_events", all_tracked_events, 60*15) # 15 minutes context["all_tracked_events"] = all_tracked_events # Get our latest Medium posts. medium_posts = cache.get("medium_posts") if not medium_posts: from website.models import MediumPost medium_posts = MediumPost.objects.order_by('-published')[0:6] cache.set("medium_posts", medium_posts, 60*15) # 15 minutes context["medium_posts"] = medium_posts # Add context variables for whether the user is in the # House or Senate netblocks. try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True except: pass return context
def build_info(): # feeds about all legislation that we offer the user to subscribe to feeds = [f for f in Feed.get_simple_feeds() if f.category == "federal-bills"] # info about bills by status groups = [ ( g[0], # title g[1], # text 1 g[2], # text 2 "/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]) + "&sort=-current_status_date", # link load_bill_status_qs(g[4]).count(), # count in category load_bill_status_qs(g[4]).order_by('-current_status_date')[0:6], # top 6 in this category ) for g in bill_status_groups ] # legislation coming up dhg_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date')) sfs_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date')) coming_up = list(dhg_bills | sfs_bills) coming_up.sort(key = lambda b : b.docs_house_gov_postdate if (b.docs_house_gov_postdate and (not b.senate_floor_schedule_postdate or b.senate_floor_schedule_postdate < b.docs_house_gov_postdate)) else b.senate_floor_schedule_postdate, reverse=True) # top tracked bills top_bills = Feed.objects\ .filter(feedname__startswith='bill:')\ .filter(feedname__regex='^bill:[hs][jcr]?%d-' % CURRENT_CONGRESS) top_bills = top_bills\ .annotate(count=Count('tracked_in_lists'))\ .order_by('-count')\ .values('feedname', 'count')\ [0:25] top_bills = [(Bill.from_feed(Feed.from_name(bf["feedname"])), bf["count"]) for bf in top_bills] # current congrss years start, end = get_congress_dates(CURRENT_CONGRESS) end_year = end.year if end.month > 1 else end.year-1 # count January finishes as the prev year current_congress_years = '%d-%d' % (start.year, end.year) current_congress = ordinal(CURRENT_CONGRESS) return { "feeds": feeds, "total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(), "current_congress_years": current_congress_years, "current_congress": current_congress, "groups": groups, "coming_up": coming_up, "top_tracked_bills": top_bills, "subjects": subject_choices(), "BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.referred, BillStatus.reported), }
def create_events(self): from events.models import Feed, Event feeds = [ Feed.AllCommitteesFeed(), Feed.CommitteeMeetingsFeed(self.code) ] if self.committee: feeds.append(Feed.CommitteeMeetingsFeed( self.committee.code)) # add parent committee with Event.update(self) as E: for meeting in self.meetings.all(): E.add("mtg_" + str(meeting.id), meeting.when, feeds + [Feed.BillFeed(b) for b in meeting.bills.all()])
def build_info(): # feeds about all legislation that we offer the user to subscribe to feeds = [f for f in Feed.get_simple_feeds() if f.category == "federal-bills"] # info about bills by status groups = [ ( g[0], # title g[1], # text 1 g[2], # text 2 "/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]) + "&sort=-current_status_date", # link load_bill_status_qs(g[4]).count(), # count in category load_bill_status_qs(g[4]).order_by('-current_status_date')[0:6], # top 6 in this category ) for g in bill_status_groups ] # legislation coming up dhg_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date')) sfs_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date')) coming_up = list((dhg_bills | sfs_bills).order_by('scheduled_consideration_date')) # top tracked bills top_bills = Feed.objects\ .filter(feedname__startswith='bill:')\ .filter(feedname__regex='^bill:[hs][jcr]?%d-' % CURRENT_CONGRESS) top_bills = top_bills\ .annotate(count=Count('tracked_in_lists'))\ .order_by('-count')\ .values('feedname', 'count')\ [0:25] top_bills = [(Bill.from_feed(Feed.from_name(bf["feedname"])), bf["count"]) for bf in top_bills] # trending bills trf = Feed.get_trending_feeds() trf = [Feed.objects.get(id=f) for f in trf] trending_bill_feeds = [f for f in trf if f.feedname.startswith("bill:")] return { "feeds": feeds, "total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(), "current_congress": CURRENT_CONGRESS, "current_congress_dates": get_congress_dates(CURRENT_CONGRESS), "groups": groups, "coming_up": coming_up, "top_tracked_bills": top_bills, "trending_bill_feeds": trending_bill_feeds, "subjects": subject_choices(), "BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.reported), }
def export_panel_user_data(request, panel_id, download): import csv, io from django.utils.text import slugify from website.models import UserPosition from bill.models import Bill from events.models import Feed panel = get_object_or_404(Panel, id=panel_id, admins=request.user) buf = io.BytesIO() w = csv.writer(buf) if download == "members": # Download the panel's membership, with one row per member. w.writerow(["id", "email", "joined", "invitation_code", "notes"]) for mbr in PanelMembership.objects.filter( panel=panel).order_by('created').select_related("user"): w.writerow([ mbr.id, mbr.user.email, mbr.created, mbr.invitation_code, mbr.extra.get("notes", ""), ]) elif download == "positions": # Download the positions panel members have taken on legislation, # with one row per member-position. members = dict( PanelMembership.objects.filter(panel=panel).values_list( "user_id", "id")) w.writerow([ "position_id", "member_id", "member_email", "position_created", "bill_id", "bill_title", "bill_link", "likert_score", "reason_text" ]) for upos in UserPosition.objects.filter(user__in=members)\ .order_by('created')\ .select_related("user"): w.writerow([ upos.id, members[upos.user.id], upos.user.email, upos.created, Bill.from_feed(Feed.from_name( upos.subject)).congressproject_id, upos.get_subject_title().encode("utf8"), "https://www.govtrack.us" + upos.get_subject_link(), upos.likert, upos.reason.encode("utf8"), ]) else: return HttpResponse("invalid") ret = HttpResponse(buf.getvalue()) if True: # disable to make debugging easier ret["Content-Type"] = "text/csv" ret["Content-Disposition"] = "attachment;filename=%s_%s.csv" % ( slugify(panel.title), download) else: ret["Content-Type"] = "text/plain" return ret
def homepage_summary(request): # parse & validate parameters try: state = request.GET["district"][0:2] district = int(request.GET["district"][2:]) if state not in statenames: raise Exception() except: return None from django.contrib.humanize.templatetags.humanize import ordinal # view people = Person.from_state_and_district(state, district) feeds = [p.get_feed() for p in people] events = Feed.get_events_for(feeds, 6) from events.templatetags.events_utils import render_event for i in range(len(events)): events[i] = render_event(events[i], feeds) if not isinstance(events[i]["date"], str): events[i]["date"] = events[i]["date"].strftime('%B %d, %Y') # can't JSON-serialize a datetime anyway, TODO handle date_has_no_time for k in list(events[i]): # remove anything else in case it is not JSON-serializable if k not in ('type', 'date', 'title', 'body_html', 'url'): del events[i][k] # form output return { "state": state, "district": district, "state_name": statenames[state], "district_ordinal": ordinal(district), "reps": [ { "link": p.get_absolute_url(), "name": p.name_and_title(), "title": p.role.get_description(), "photo": p.get_photo_url() } for p in people], "events": events, }
def build_info(): feeds = [f for f in Feed.get_simple_feeds() if f.category == "federal-bills"] groups = [ ( g[0], # title g[1], # text 1 g[2], # text 2 "/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]), # link load_bill_status_qs(g[4]).count(), # count in category load_bill_status_qs(g[4]).order_by('-current_status_date')[0:6], # top 6 in this category ) for g in bill_status_groups ] dhg_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date')) sfs_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date')) coming_up = list(dhg_bills | sfs_bills) coming_up.sort(key = lambda b : b.docs_house_gov_postdate if (b.docs_house_gov_postdate and (not b.senate_floor_schedule_postdate or b.senate_floor_schedule_postdate < b.docs_house_gov_postdate)) else b.senate_floor_schedule_postdate, reverse=True) start, end = get_congress_dates(CURRENT_CONGRESS) end_year = end.year if end.month > 1 else end.year-1 # count January finishes as the prev year current_congress_years = '%d-%d' % (start.year, end.year) current_congress = ordinal(CURRENT_CONGRESS) return { "feeds": feeds, "total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(), "current_congress_years": current_congress_years, "current_congress": current_congress, "groups": groups, "coming_up": coming_up, "subjects": subject_choices(), "BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.referred, BillStatus.reported), }
def index(request): twitter_feed = cache.get("our_twitter_feed") if twitter_feed == None: try: import twitter twitter_api = twitter.Api() twitter_feed = twitter_api.GetUserTimeline("govtrack", since_id=0, count=3) # replace links from django.utils.html import conditional_escape from django.utils.safestring import mark_safe re_url = re.compile(r"(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))") for item in twitter_feed: item.text = re_url.sub(lambda m : "<a target=\"_blank\" href=\"" + m.group(0) + "\">" + m.group(0) + "</a>", conditional_escape(item.text)) cache.set("our_twitter_feed", twitter_feed, 60*30) # 30 minutes except: twitter_feed = [] cache.set("our_twitter_feed", twitter_feed, 60*2) # 2 minutes blog_feed = cache.get("our_blog_feed") if not blog_feed: blog_feed = get_blog_items()[0:2] cache.set("our_blog_feed", blog_feed, 60*30) # 30 min events_feed = cache.get("frontpage_events_feed") if not events_feed: events_feed = Feed.get_events_for([fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists()], 6) cache.set("frontpage_events_feed", events_feed, 60*15) # 15 minutes return { 'events': events_feed, 'tweets': twitter_feed, 'blog': blog_feed, }
def bill_details_user_view(request, congress, type_slug, number): bill = load_bill_from_url(congress, type_slug, number) ret = { } if request.user.is_staff: admin_panel = """ {% load humanize %} <div class="clear"> </div> <div style="margin-top: 1.5em; padding: .5em; background-color: #EEE; "> <b>ADMIN</b> - <a href="{% url "bill_go_to_summary_admin" %}?bill={{bill.id}}">Edit Summary</a> <br/>Tracked by {{feed.tracked_in_lists.count|intcomma}} users ({{feed.tracked_in_lists_with_email.count|intcomma}} w/ email). </div> """ from django.template import Template, Context, RequestContext, loader ret["admin_panel"] = Template(admin_panel).render(RequestContext(request, { 'bill': bill, "feed": Feed.BillFeed(bill), })) from person.views import render_subscribe_inline ret.update(render_subscribe_inline(request, Feed.BillFeed(bill))) # poll_and_call if request.user.is_authenticated(): from poll_and_call.models import RelatedBill as IssueByBill, UserPosition try: issue = IssueByBill.objects.get(bill=bill).issue try: up = UserPosition.objects.get(user=request.user, position__issue=issue) targets = up.get_current_targets() ret["poll_and_call_position"] = { "id": up.position.id, "text": up.position.text, "can_change": up.can_change_position(), "can_call": [(t.id, t.person.name) for t in targets] if isinstance(targets, list) else [], "call_url": issue.get_absolute_url() + "/make_call", } except UserPosition.DoesNotExist: pass except IssueByBill.DoesNotExist: pass return ret
def create_events(self, prev_role, next_role): now = datetime.datetime.now().date() from events.models import Feed, Event with Event.update(self) as E: f = Feed.PersonFeed(self.person_id) if not prev_role or not self.continues_from(prev_role): E.add("termstart", self.startdate, f) if not next_role or not next_role.continues_from(self): if self.enddate <= now: # because we're not sure of end date until it happens E.add("termend", self.enddate, f)
def export_panel_user_data(request, panel_id, download): import csv, io from django.utils.text import slugify from website.models import UserPosition from bill.models import Bill from events.models import Feed panel = get_object_or_404(Panel, id=panel_id, admins=request.user) buf = io.StringIO() w = csv.writer(buf) if download == "members": # Download the panel's membership, with one row per member. w.writerow(["id", "email", "joined", "invitation_code", "notes"]) for mbr in PanelMembership.objects.filter(panel=panel).order_by('created').select_related("user"): w.writerow([ str(mbr.id), mbr.user.email, mbr.created.isoformat(), mbr.invitation_code, mbr.extra.get("notes", ""), ]) elif download == "positions": # Download the positions panel members have taken on legislation, # with one row per member-position. members = dict(PanelMembership.objects.filter(panel=panel).values_list("user_id", "id")) w.writerow(["position_id", "member_id", "member_email", "position_created", "bill_id", "bill_title", "bill_link", "likert_score", "reason_text"]) for upos in UserPosition.objects.filter(user__in=members)\ .order_by('created')\ .select_related("user"): w.writerow([ str(upos.id), members[upos.user.id], upos.user.email, upos.created.isoformat(), Bill.from_feed(Feed.from_name(upos.subject)).congressproject_id, upos.get_subject_title(), "https://www.govtrack.us" + upos.get_subject_link(), str(upos.likert), upos.reason, ]) else: return HttpResponse("invalid") ret = HttpResponse(buf.getvalue()) if True: # disable to make debugging easier ret["Content-Type"] = "text/csv" ret["Content-Disposition"] = "attachment;filename=%s_%s.csv" % ( slugify(panel.title), download ) else: ret["Content-Type"] = "text/plain" return ret
def handle(self, *args, **options): # get feeds, across all congresses top_bills = Feed.objects.annotate(count=Count('tracked_in_lists'))\ .filter(feedname__startswith='bill:')\ .filter(feedname__regex='^bill:[hs][jcr]?%d-' % settings.CURRENT_CONGRESS)\ .order_by('-count')\ .values('feedname', 'count')\ [0:25] print "users \t url \t bill title" for bf in top_bills: b = Feed.from_name(bf["feedname"]).bill() print bf["count"], "\t", b.get_absolute_url(), "\t", b
def build_info(): if re.match(r"\d", pk): person = get_object_or_404(Person, pk=pk) else: # support bioguide IDs for me person = get_object_or_404(Person, bioguideid=pk) # current role role = person.get_current_role() if role: active_role = True else: active_role = False try: role = person.roles.order_by('-enddate')[0] except IndexError: role = None # photo photo_path = 'data/photos/%d-100px.jpeg' % person.pk photo_credit = None if os.path.exists(photo_path): photo = '/' + photo_path with open(photo_path.replace("-100px.jpeg", "-credit.txt"), "r") as f: photo_credit = f.read().strip().split(" ", 1) else: photo = None analysis_data = analysis.load_data(person) links = [] if person.osid: links.append(("OpenSecrets", "http://www.opensecrets.org/politicians/summary.php?cid=" + person.osid)) if person.pvsid: links.append(("VoteSmart", "http://votesmart.org/candidate/" + person.pvsid)) if person.bioguideid: links.append(("Bioguide", "http://bioguide.congress.gov/scripts/biodisplay.pl?index=" + person.bioguideid)) if person.cspanid: links.append(("C-SPAN Video", "http://www.c-spanvideo.org/person/" + str(person.cspanid))) return {'person': person, 'role': role, 'active_role': active_role, 'active_congressional_role': active_role and role.role_type in (RoleType.senator, RoleType.representative), 'photo': photo, 'photo_credit': photo_credit, 'links': links, 'analysis_data': analysis_data, 'recent_bills': person.sponsored_bills.all().order_by('-introduced_date')[0:7], 'committeeassignments': get_committee_assignments(person), 'feed': Feed.PersonFeed(person.id), 'cities': get_district_cities("%s-%02d" % (role.state.lower(), role.district)) if role and role.district else None, }
def bill_details_user_view(request, congress, type_slug, number): bill = load_bill_from_url(congress, type_slug, number) ret = { } if request.user.is_staff: admin_panel = """ {% load humanize %} <div class="clear"> </div> <div style="margin-top: 1.5em; padding: .5em; background-color: #EEE; "> <b>ADMIN</b> - <a href="{% url "bill_go_to_summary_admin" %}?bill={{bill.id}}">Edit Summary</a> <br/>Tracked by {{feed.tracked_in_lists.count|intcomma}} users ({{feed.tracked_in_lists_with_email.count|intcomma}} w/ email). </div> """ from django.template import Template, Context, RequestContext, loader ret["admin_panel"] = Template(admin_panel).render(RequestContext(request, { 'bill': bill, "feed": Feed.BillFeed(bill), })) from person.views import render_subscribe_inline ret.update(render_subscribe_inline(request, Feed.BillFeed(bill))) return ret
def index(request): blog_feed = cache.get("our_blog_feed") if not blog_feed: blog_feed = get_blog_items()[0:4] cache.set("our_blog_feed", blog_feed, 60*30) # 30 min events_feed = cache.get("frontpage_events_feed") if not events_feed: events_feed = Feed.get_events_for([fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists()], 6) cache.set("frontpage_events_feed", events_feed, 60*15) # 15 minutes return { 'events': events_feed, 'blog': blog_feed, }
def vote_list(request): # Get the default session to show. We may have sessions listed that are # in the future, during a transition, so take the most recent that at # least has started. default_session = None for i, (cn, sn, sd, ed) in reversed(list(enumerate(get_all_sessions()))): if sd > datetime.now().date(): continue if not Vote.objects.filter(congress=cn, session=sn).exists(): continue default_session = i break return vote_search_manager().view(request, "vote/vote_list.html", defaults = { "session": default_session }, paginate = lambda form : "session" not in form, # people like to see all votes for a year on one page context = { "feed": Feed(feedname="misc:allvotes") })
def show_stats(self, recent_users_only): # get feeds, across all congresses top_bills = Feed.objects\ .filter(feedname__startswith='bill:')\ .filter(feedname__regex='^bill:[hs][jcr]?%d-' % settings.CURRENT_CONGRESS) if recent_users_only: top_bills = top_bills.filter(tracked_in_lists__user__date_joined__gt=datetime.datetime.now()-datetime.timedelta(days=14)) top_bills = top_bills\ .annotate(count=Count('tracked_in_lists'))\ .order_by('-count')\ .values('feedname', 'count')\ [0:25] print "users \t url \t bill title" for bf in top_bills: b = Feed.from_name(bf["feedname"]).bill() print bf["count"], "\t", b.get_absolute_url(), "\t", b
def show_stats(self, recent_users_only): # get feeds, across all congresses top_bills = Feed.objects\ .filter(feedname__startswith='bill:')\ .filter(feedname__regex='^bill:[hs][jcr]?%d-' % settings.CURRENT_CONGRESS) if recent_users_only: top_bills = top_bills.filter(tracked_in_lists__user__date_joined__gt=datetime.datetime.now()-datetime.timedelta(days=14)) top_bills = top_bills\ .annotate(count=Count('tracked_in_lists'))\ .order_by('-count')\ .values('feedname', 'count')\ [0:25] print("new users \t all users \t sponsor \t url \t bill title") for bf in top_bills: f = Feed.from_name(bf["feedname"]) b = Bill.from_feed(f) print(bf["count"], "\t", f.tracked_in_lists.all().count(), "\t", b.sponsor.lastname.encode("utf8"), b.get_absolute_url(), "\t", b)
def update_userposition(request): from website.models import UserPosition if request.method != "POST": raise HttpResponseBadRequest() # just validate f = Feed.from_name(request.POST.get("subject", "")) f.title qs = UserPosition.objects.filter(user=request.user, subject=request.POST["subject"]) if not request.POST.get("likert") and not request.POST.get("reason"): # Nothing to save - delete any existing. qs.delete() else: # Update. upos, _ = qs.get_or_create(user=request.user, subject=request.POST["subject"]) upos.likert = int(request.POST["likert"]) if request.POST.get("likert") else None upos.reason = request.POST["reason"] upos.save() return HttpResponse(json.dumps({ "status": "ok" }), content_type="application/json")
def create_events(self): if self.congress < 112: return # not interested, creates too much useless data and slow to load from events.models import Feed, Event with Event.update(self) as E: # collect the feeds that we'll add major actions to bill_feed = Feed.BillFeed(self) index_feeds = [bill_feed] if self.sponsor != None: index_feeds.append(Feed.PersonSponsorshipFeed(self.sponsor)) index_feeds.extend([Feed.IssueFeed(ix) for ix in self.terms.all()]) index_feeds.extend([Feed.CommitteeBillsFeed(cx) for cx in self.committees.all()]) # also index into feeds for any related bills and previous versions of this bill # that people may still be tracking for rb in self.get_related_bills(): index_feeds.append(Feed.BillFeed(rb.related_bill)) for b in self.find_reintroductions(): index_feeds.append(Feed.BillFeed(b)) # generate events for major actions E.add("state:" + str(BillStatus.introduced), self.introduced_date, index_feeds + [Feed.ActiveBillsFeed(), Feed.IntroducedBillsFeed()]) common_feeds = [Feed.ActiveBillsFeed(), Feed.ActiveBillsExceptIntroductionsFeed()] enacted_feed = [Feed.EnactedBillsFeed()] for datestr, state, text in self.major_actions: date = eval(datestr) if state == BillStatus.introduced: continue # already indexed if state == BillStatus.referred and (date.date() - self.introduced_date).days == 0: continue # don't dup these events so close E.add("state:" + str(state), date, index_feeds + common_feeds + (enacted_feed if state in BillStatus.final_status_passed_bill else [])) # generate events for new cosponsors... group by join date, and # assume that join dates we've seen don't have new cosponsors # added later, or else we may miss that in an email update. we # don't actually need the people listed here, just the unique join # dates. cosponsor_join_dates = set() for cosp in Cosponsor.objects.filter(bill=self, withdrawn=None).exclude(joined=self.introduced_date): cosponsor_join_dates.add(cosp.joined) for joindate in cosponsor_join_dates: E.add("cosp:" + joindate.isoformat(), joindate, [bill_feed]) # generate an event for appearing on docs.house.gov or the senate floor schedule: if self.docs_house_gov_postdate: E.add("dhg", self.docs_house_gov_postdate, index_feeds + common_feeds + [Feed.ComingUpFeed()]) if self.senate_floor_schedule_postdate: E.add("sfs", self.senate_floor_schedule_postdate, index_feeds + common_feeds + [Feed.ComingUpFeed()]) # generate an event for each new GPO text availability from glob import glob from billtext import bill_gpo_status_codes bt = BillType.by_value(self.bill_type).xml_code for st in bill_gpo_status_codes: textfn = "data/us/bills.text/%s/%s/%s%d%s.pdf" % (self.congress, bt, bt, self.number, st) # use pdf since we don't modify it once we download it, and hopefully we actually have a displayable format like HTML if os.path.exists(textfn): textmodtime = datetime.datetime.fromtimestamp(os.path.getmtime(textfn)) E.add("text:" + st, textmodtime, index_feeds) # generate an event for the main summary bs = BillSummary.objects.filter(bill=self) if len(bs) > 0: E.add("summary", bs[0].created, index_feeds + [Feed.from_name("misc:billsummaries")])
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = dict(base_context) # clone #if hasattr(request, 'user') and request.user.is_authenticated() and BouncedEmail.objects.filter(user=request.user).exists(): context["user_has_bounced_mail"] = True # Add top-tracked feeds. from events.models import Feed global trending_feeds if settings.DEBUG and False: trending_feeds = [None, []] elif not trending_feeds or trending_feeds[0] < datetime.datetime.now()-datetime.timedelta(hours=2): trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60*60*2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] context["trending_bill_feeds"] = [f for f in trending_feeds[1] if f.feedname.startswith("bill:")] # Add site-wide tracked events. all_tracked_events = cache.get("all_tracked_events") if not all_tracked_events: all_tracked_events = Feed.get_events_for([fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists()], 6) cache.set("all_tracked_events", all_tracked_events, 60*15) # 15 minutes context["all_tracked_events"] = all_tracked_events # Get our latest Medium posts. medium_posts = cache.get("medium_posts") if not medium_posts: from website.models import MediumPost medium_posts = MediumPost.objects.order_by('-published')[0:6] cache.set("medium_posts", medium_posts, 60*15) # 15 minutes context["medium_posts"] = medium_posts # Get a campaign from if.then.fund. itf_active_campaign = 50 if_then_fund_campaign = cache.get("if_then_fund_campaign") if not if_then_fund_campaign and itf_active_campaign: try: if_then_fund_campaign = json.load(urllib2.urlopen("https://if.then.fund/a/%d.json" % itf_active_campaign)) except: if_then_fund_campaign = "UHM" # something that is truthy otherwise we'll ping on every request cache.set("if_then_fund_campaign", if_then_fund_campaign, 60*45) # 45 minutes context["if_then_fund_campaign"] = if_then_fund_campaign # Add context variables for whether the user is in the # House or Senate netblocks. def ip_to_quad(ip): return [int(s) for s in ip.split(".")] def compare_ips(ip1, ip2): return cmp(ip_to_quad(ip1), ip_to_quad(ip2)) def is_ip_in_range(ip, block): return compare_ips(ip, block[0]) >= 0 and compare_ips(ip, block[1]) <= 0 def is_ip_in_any_range(ip, blocks): for block in blocks: if is_ip_in_range(ip, block): return True return False try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True except: pass # Add a context variable for if the user is near DC geographically. user_loc = None try: if settings.GEOIP_DB_PATH and not request.path.startswith("/api/") and False: user_loc = geo_ip_db.geos(ip) context["is_dc_local"] = user_loc.distance(washington_dc) < .5 except: pass if not hasattr(request, 'user') or not request.user.is_authenticated(): # Have we put the user's district in a cookie? try: cong_dist = json.loads(request.COOKIES["cong_dist"]) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid except: cong_dist = None # Geolocate to a congressional district if not known and save it in # a cookie for next time. if user_loc and not cong_dist and not request.path.startswith("/api/"): try: from person.views import do_district_lookup cong_dist = do_district_lookup(*user_loc.coords) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid request._save_cong_dist = cong_dist except: cong_dist = None else: # If the user is logged in, is the district in the user's profile? profile = request.user.userprofile() if profile.congressionaldistrict != None: # pass through XX00 so site knows not to prompt cong_dist = { "state": profile.congressionaldistrict[0:2], "district": int(profile.congressionaldistrict[2:]) } else: cong_dist = None # If we have a district, get its MoCs. if cong_dist: from person.models import Person context["congressional_district"] = json.dumps(cong_dist) context["congressional_district_mocs"] = json.dumps([p.id for p in Person.from_state_and_district(cong_dist["state"], cong_dist["district"])]) return context
def items(self): events = [ render_event(item, feedlist) for item in Feed.get_events_for(feedlist, 25) ] return [e for e in events if e != None]
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = { "SITE_ROOT_URL": settings.SITE_ROOT_URL, "GOOGLE_ANALYTICS_KEY": settings.GOOGLE_ANALYTICS_KEY } if request.user.is_authenticated() and BouncedEmail.objects.filter(user=request.user).exists(): context["user_has_bounced_mail"] = True # Add top-tracked feeds. global trending_feeds if not trending_feeds or trending_feeds[0] < datetime.datetime.now()-datetime.timedelta(hours=2): from events.models import Feed trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60*60*2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] # Add context variables for whether the user is in the # House or Senate netblocks. def ip_to_quad(ip): return [int(s) for s in ip.split(".")] def compare_ips(ip1, ip2): return cmp(ip_to_quad(ip1), ip_to_quad(ip2)) def is_ip_in_range(ip, block): return compare_ips(ip, block[0]) >= 0 and compare_ips(ip, block[1]) <= 0 def is_ip_in_any_range(ip, blocks): for block in blocks: if is_ip_in_range(ip, block): return True return False try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True try: cong_dist = json.loads(request.COOKIES["cong_dist"]) except: cong_dist = None if settings.GEOIP_DB_PATH: user_loc = geo_ip_db.geos(ip) context["is_dc_local"] = user_loc.distance(washington_dc) < .5 # geolocate to a congressional district if not known if not cong_dist and False: from person.views import do_district_lookup cong_dist = do_district_lookup(*user_loc.coords) cong_dist["queried"] = True if cong_dist and "error" not in cong_dist: from person.models import PersonRole, RoleType, Gender import random def get_key_vote(p): from vote.models import Vote v = 113340 descr = "CISPA" v = Vote.objects.get(id=v) try: return { "link": v.get_absolute_url(), "description": descr, "option": p.votes.get(vote=v).option.key, } except: return None def fmt_role(r): return { "id": r.person.id, "name": r.person.name_and_title(), "link": r.person.get_absolute_url(), "type": RoleType.by_value(r.role_type).key, "pronoun": Gender.by_value(r.person.gender).pronoun, "key_vote": get_key_vote(r.person), } qs = PersonRole.objects.filter(current=True).select_related("person") cong_dist["reps"] = [fmt_role(r) for r in qs.filter(role_type=RoleType.representative, state=cong_dist["state"], district=cong_dist["district"]) | qs.filter(role_type=RoleType.senator, state=cong_dist["state"])] if settings.DEBUG: # I need to test with more than my rep (just our DC delegate). cong_dist["reps"] = [fmt_role(r) for r in random.sample(PersonRole.objects.filter(current=True), 3)] random.shuffle(cong_dist["reps"]) # for varied output context["geolocation"] = json.dumps(cong_dist) if cong_dist: # whether or not error request.cong_dist_info = cong_dist except: pass return context
def AllVotesFeed(): from events.models import Feed return Feed.get_noarg_feed("misc:allvotes")
# in other states too, so this would be incorrect for that. But # we'd still like to know what is the current session. if self.enddate == None: # Not sure. self.current = False self.save() return self.current = not StateSession.objects.filter(state=self.state, startdate__gte=self.enddate).exists() self.save() from events.models import Feed Feed.register_feed( "states_allbills", title = "State Legislation: All Activity", slug = "states_bills", intro_html = """Use this feed to track all legislative events in all United States state legislatures.""", simple = True, sort_order = 200, category = "state-bills", description = "Get an update on major activity on all state legislation.", ) for st in us.stateabbrs: Feed.register_feed( "states_%s_bills" % st, title = us.statenames[st] + " Legislation", link = "/states/%s" % st.lower(), category = "state-bills", description = "Get an update on major activity on all bills in this state.", ) Feed.register_feed( "states_bill:", title = lambda feed : unicode(StateBill.objects.get(id=feed.feedname.split(":")[1])),
def index(request): # Fetch subject areas for drop-down. from bill.views import subject_choices bill_subject_areas = subject_choices() post_groups = [] # Fetch our Medium posts for summaries and features. from website.models import MediumPost post_groups.append({ "title": "What We're Watching", "posts": MediumPost.objects.order_by('-published')[0:3], "link": "/events/govtrack-insider", "link_text": "Subscribe to all GovTrack Insider articles", }) # legislation coming up from django.db.models import F from django.conf import settings from bill.models import Bill dhg_bills = Bill.objects.filter(congress=settings.CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.now() - timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date')) sfs_bills = Bill.objects.filter(congress=settings.CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.now() - timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date')) coming_up = list((dhg_bills | sfs_bills)) coming_up.sort(key = lambda bill : -bill.proscore()) if len(coming_up) > 0: post_groups.append({ "title": "Legislation Coming Up", "posts": [{ "image_url": bill.get_thumbnail_url_ex(), "title": bill.title, "url": bill.get_absolute_url(), "published": "week of " + bill.scheduled_consideration_date.strftime("%x"), } for bill in coming_up[0:3]], "link": "/congress/bills", "link_text": "View All", }) # recent oversight topics from oversight.models import OversightTopic oversight_topics = OversightTopic.objects.filter(congress_end__gte=settings.CURRENT_CONGRESS).order_by('-updated')[0:3] if oversight_topics: post_groups.append({ "title": "Congressional Oversight and Investigations", "posts": [{ "title": topic.title, "url": topic.get_absolute_url(), "published": topic.post_date, } for topic in oversight_topics], "link": "/congress/oversight", "link_text": "View All", }) # trending feeds trending_feeds = [Feed.objects.get(id=f) for f in Feed.get_trending_feeds()[0:6]] if len(trending_feeds) > 0: post_groups.append({ "title": "Trending", "posts": [{ "title": feed.title, "url": feed.link, } for feed in trending_feeds ]}) from person.models import Person from vote.models import Vote return { # for the splash 'number_of_bills': Bill.objects.filter(congress=settings.CURRENT_CONGRESS).count(), 'number_of_legislators': Person.objects.filter(roles__current=True).count(), 'number_of_votes': Vote.objects.filter(created__year=datetime.now().year).count(), # for the action area below the splash 'bill_subject_areas': bill_subject_areas, # for the highlights blocks 'post_groups': post_groups, }
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = dict(base_context) # clone # Add top-tracked feeds. from events.models import Feed global trending_feeds if settings.DEBUG and False: trending_feeds = [None, []] elif not trending_feeds or trending_feeds[0] < datetime.datetime.now()-datetime.timedelta(hours=2): trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60*60*2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] context["trending_bill_feeds"] = [f for f in trending_feeds[1] if f.feedname.startswith("bill:")] # Add site-wide tracked events. all_tracked_events = cache.get("all_tracked_events") if not all_tracked_events: all_tracked_events = Feed.get_events_for([fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists()], 6) cache.set("all_tracked_events", all_tracked_events, 60*15) # 15 minutes context["all_tracked_events"] = all_tracked_events # Get our latest Medium posts. medium_posts = cache.get("medium_posts") if not medium_posts: from website.models import MediumPost medium_posts = MediumPost.objects.order_by('-published')[0:6] cache.set("medium_posts", medium_posts, 60*15) # 15 minutes context["medium_posts"] = medium_posts # Add context variables for whether the user is in the # House or Senate netblocks. def ip_to_quad(ip): return [int(s) for s in ip.split(".")] def compare_ips(ip1, ip2): return cmp(ip_to_quad(ip1), ip_to_quad(ip2)) def is_ip_in_range(ip, block): return compare_ips(ip, block[0]) >= 0 and compare_ips(ip, block[1]) <= 0 def is_ip_in_any_range(ip, blocks): for block in blocks: if is_ip_in_range(ip, block): return True return False try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True except: pass return context
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = dict(base_context) # clone #if hasattr(request, 'user') and request.user.is_authenticated() and BouncedEmail.objects.filter(user=request.user).exists(): context["user_has_bounced_mail"] = True # Add top-tracked feeds. from events.models import Feed global trending_feeds if settings.DEBUG and False: trending_feeds = [None, []] elif not trending_feeds or trending_feeds[0] < datetime.datetime.now( ) - datetime.timedelta(hours=2): trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60 * 60 * 2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] context["trending_bill_feeds"] = [ f for f in trending_feeds[1] if f.feedname.startswith("bill:") ] # Add site-wide tracked events. all_tracked_events = cache.get("all_tracked_events") if not all_tracked_events: all_tracked_events = Feed.get_events_for([ fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists() ], 6) cache.set("all_tracked_events", all_tracked_events, 60 * 15) # 15 minutes context["all_tracked_events"] = all_tracked_events # Get our latest Medium posts. medium_posts = cache.get("medium_posts") if not medium_posts: from website.models import MediumPost medium_posts = MediumPost.objects.order_by('-published')[0:6] cache.set("medium_posts", medium_posts, 60 * 15) # 15 minutes context["medium_posts"] = medium_posts # Get a campaign from if.then.fund. itf_active_campaign = 0 if_then_fund_campaign = cache.get("if_then_fund_campaign_%d" % itf_active_campaign) if not if_then_fund_campaign and itf_active_campaign: try: if_then_fund_campaign = json.load( urllib2.urlopen("https://if.then.fund/a/%d.json" % itf_active_campaign)) except: if_then_fund_campaign = "UHM" # something that is truthy otherwise we'll ping on every request cache.set("if_then_fund_campaign_%d" % itf_active_campaign, if_then_fund_campaign, 60 * 45) # 45 minutes context["if_then_fund_campaign"] = if_then_fund_campaign # Add context variables for whether the user is in the # House or Senate netblocks. def ip_to_quad(ip): return [int(s) for s in ip.split(".")] def compare_ips(ip1, ip2): return cmp(ip_to_quad(ip1), ip_to_quad(ip2)) def is_ip_in_range(ip, block): return compare_ips(ip, block[0]) >= 0 and compare_ips(ip, block[1]) <= 0 def is_ip_in_any_range(ip, blocks): for block in blocks: if is_ip_in_range(ip, block): return True return False try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True except: pass # Add a context variable for if the user is near DC geographically. user_loc = None try: if settings.GEOIP_DB_PATH and not request.path.startswith( "/api/") and False: user_loc = geo_ip_db.geos(ip) context["is_dc_local"] = user_loc.distance(washington_dc) < .5 except: pass if not hasattr(request, 'user') or not request.user.is_authenticated(): # Have we put the user's district in a cookie? try: cong_dist = json.loads(request.COOKIES["cong_dist"]) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid except: cong_dist = None # Geolocate to a congressional district if not known and save it in # a cookie for next time. if user_loc and not cong_dist and not request.path.startswith("/api/"): try: from person.views import do_district_lookup cong_dist = do_district_lookup(*user_loc.coords) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid request._save_cong_dist = cong_dist except: cong_dist = None else: # If the user is logged in, is the district in the user's profile? profile = request.user.userprofile() if profile.congressionaldistrict != None: # pass through XX00 so site knows not to prompt cong_dist = { "state": profile.congressionaldistrict[0:2], "district": int(profile.congressionaldistrict[2:]) } else: cong_dist = None # If we have a district, get its MoCs. if cong_dist: from person.models import Person context["congressional_district"] = json.dumps(cong_dist) context["congressional_district_mocs"] = json.dumps([ p.id for p in Person.from_state_and_district( cong_dist["state"], cong_dist["district"]) ]) return context
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = { "SITE_ROOT_URL": settings.SITE_ROOT_URL, "GOOGLE_ANALYTICS_KEY": settings.GOOGLE_ANALYTICS_KEY, "STATE_CHOICES": sorted([(kv[0], kv[1], us.stateapportionment[kv[0]]) for kv in us.statenames.items() if kv[0] in us.stateapportionment], key = lambda kv : kv[1]), } if hasattr(request, 'user') and request.user.is_authenticated() and BouncedEmail.objects.filter(user=request.user).exists(): context["user_has_bounced_mail"] = True # Add top-tracked feeds. from events.models import Feed global trending_feeds if settings.DEBUG and False: trending_feeds = [None, []] elif not trending_feeds or trending_feeds[0] < datetime.datetime.now()-datetime.timedelta(hours=2): trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60*60*2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] context["trending_bill_feeds"] = [f for f in trending_feeds[1] if f.feedname.startswith("bill:")] # Add site-wide tracked events. all_tracked_events = cache.get("all_tracked_events") if not all_tracked_events: all_tracked_events = Feed.get_events_for([fn for fn in ("misc:activebills2", "misc:billsummaries", "misc:allvotes") if Feed.objects.filter(feedname=fn).exists()], 6) cache.set("all_tracked_events", all_tracked_events, 60*15) # 15 minutes context["all_tracked_events"] = all_tracked_events # Highlight a recent vote. We don't yet need to know the user's district # --- that will happen client-side. def get_highlighted_vote(): from vote.models import Vote, VoteCategory candidate_votes = Vote.objects.filter(category__in=Vote.MAJOR_CATEGORIES).exclude(related_bill=None).order_by('-created') for v in candidate_votes: return { "title": v.question, "link": v.get_absolute_url(), "data": v.simple_record() } return "NONE" highlighted_vote = cache.get("highlighted_vote") if highlighted_vote is None: highlighted_vote = get_highlighted_vote() cache.set("highlighted_vote", highlighted_vote, 60*60*2) if highlighted_vote != "NONE": context["highlighted_vote"] = highlighted_vote # Get our latest Medium posts. def get_medium_posts(): medium_posts = urllib.urlopen("https://medium.com/govtrack-insider?format=json").read() # there's some crap before the JSON object starts medium_posts = medium_posts[medium_posts.index("{"):] medium_posts = json.loads(medium_posts) def format_post(postid): post = medium_posts['payload']['references']['Post'][postid] collection = medium_posts['payload']['references']['Collection'][post['homeCollectionId']] return { "title": post['title'], "url": "https://medium.com/" + collection['slug'] + "/" + post['uniqueSlug'], "date": post['virtuals']['firstPublishedAtEnglish'], "preview": post['virtuals']['snippet'], "image": post['virtuals']['previewImage']['imageId'] if post['virtuals'].get('previewImage') else None, #"preview": " ".join([ # para['text'] # for para in post['previewContent']['bodyModel']['paragraphs'] # if para['type'] == 1 # not sure but a paragraph? vs a heading? #]) } return [ format_post(postid) for postid in medium_posts['payload']['value']['sections'][1]['postListMetadata']['postIds'] ] medium_posts = cache.get("medium_posts") if not medium_posts: try: medium_posts = get_medium_posts() except: medium_posts = [] cache.set("medium_posts", medium_posts, 60*15) # 15 minutes context["medium_posts"] = medium_posts[0:3] # Add context variables for whether the user is in the # House or Senate netblocks. def ip_to_quad(ip): return [int(s) for s in ip.split(".")] def compare_ips(ip1, ip2): return cmp(ip_to_quad(ip1), ip_to_quad(ip2)) def is_ip_in_range(ip, block): return compare_ips(ip, block[0]) >= 0 and compare_ips(ip, block[1]) <= 0 def is_ip_in_any_range(ip, blocks): for block in blocks: if is_ip_in_range(ip, block): return True return False try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True except: pass # Add a context variable for if the user is near DC geographically. user_loc = None try: if settings.GEOIP_DB_PATH and not request.path.startswith("/api/"): user_loc = geo_ip_db.geos(ip) context["is_dc_local"] = user_loc.distance(washington_dc) < .5 except: pass if not hasattr(request, 'user') or not request.user.is_authenticated(): # Have we put the user's district in a cookie? try: cong_dist = json.loads(request.COOKIES["cong_dist"]) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid except: cong_dist = None # Geolocate to a congressional district if not known and save it in # a cookie for next time. if user_loc and not cong_dist and not request.path.startswith("/api/"): try: from person.views import do_district_lookup cong_dist = do_district_lookup(*user_loc.coords) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid request._save_cong_dist = cong_dist except: cong_dist = None else: # If the user is logged in, is the district in the user's profile? profile = request.user.userprofile() if profile.congressionaldistrict != None: # pass through XX00 so site knows not to prompt cong_dist = { "state": profile.congressionaldistrict[0:2], "district": int(profile.congressionaldistrict[2:]) } else: cong_dist = None # If we have a district, get its MoCs. if cong_dist: from person.models import Person context["congressional_district"] = json.dumps(cong_dist) context["congressional_district_mocs"] = json.dumps([p.id for p in Person.from_state_and_district(cong_dist["state"], cong_dist["district"])]) return context
def AllCommitteesFeed(): from events.models import Feed return Feed.get_noarg_feed("misc:allcommittee")
def items(self): events = [render_event(item, feedlist) for item in Feed.get_events_for(feedlist, 25)] return [e for e in events if e != None]
def is_recently_added(self): return (self.created > (datetime.now() - timedelta(hours=36))) def abbrev_committee_name(self): return self.committee.sortname(True) # feeds from events.models import Feed, truncate_words Feed.register_feed( "misc:allcommittee", title="Committee Meetings", link="/congress/committees", simple=True, sort_order=103, category="federal-committees", description= "Get an alert whenever a committee hearing or mark-up session is scheduled.", ) Feed.register_feed( "committee:", title=lambda feed: truncate_words(Committee.from_feed(feed).fullname, 12), noun="committee", includes=lambda feed: [ Committee.from_feed(feed).get_feed("bills"), Committee.from_feed(feed).get_feed("meetings") ], link=lambda feed: Committee.from_feed(feed).get_absolute_url(), scoped_title=lambda feed: "All Events for This Committee", is_valid=lambda feed: Committee.from_feed(feed, test=True),
def create_events(self): from events.models import Feed, Event with Event.update(self) as E: feeds = [Feed.from_name("misc:govtrackinsider")] E.add("post", self.published, feeds)
class VoteSummary(models.Model): vote = models.OneToOneField(Vote, related_name="oursummary", on_delete=models.PROTECT) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) content = models.TextField(blank=True) def __str__(self): return "Summary for " + str(self.vote) def get_absolute_url(self): return self.vote.get_absolute_url() def as_html(self): return markdown2.markdown(self.content) def plain_text(self): # Kill links. import re content = re.sub("\[(.*?)\]\(.*?\)", r"\1", self.content) return content # Feeds from events.models import Feed Feed.register_feed( "misc:allvotes", title = "Roll Call Votes", link = "/congress/votes", simple = True, single_event_type = True, sort_order = 101, category = "federal-votes", description = "You will get an alert for every roll call vote in Congress.", )
from events.models import Feed, Event with Event.update(self) as E: feeds = [Feed.from_name("misc:govtrackinsider")] E.add("post", self.published, feeds) def render_event(self, eventid, feeds): return { "type": "GovTrack Insider", "date": self.published, "date_has_no_time": False, "title": self.title, "url": self.get_absolute_url(), "body_text_template": """{{snippet|safe}}""", "body_html_template": """<p>{{snippet}}</p>""", "context": { "snippet": self.snippet, } } Feed.register_feed( "misc:govtrackinsider", title="GovTrack Insider Articles", simple=True, slug="govtrack-insider", intro_html= """<p>This feed includes posts on <a href="https://medium.com/govtrack-insider">GovTrack Insider</a>.</p>""", description= "Get an update whenever we post a new article on GovTrack Insider.", )
if self.party == "Republican": return "Democrat" return None def get_sort_key(self): # As it happens, our enums define a good sort order between senators and representatives. return (self.role_type, self.senator_rank) # Feeds from events.models import Feed Feed.register_feed( "p:", title = lambda feed : Person.from_feed(feed).name, noun = "person", includes = lambda feed : [Person.from_feed(feed).get_feed("pv"), Person.from_feed(feed).get_feed("ps")], link = lambda feed: Person.from_feed(feed).get_absolute_url(), scoped_title = lambda feed : "All Events for " + Person.from_feed(feed).lastname, category = "federal-other", description = "You will get updates about major activity on sponsored bills and how this Member of Congress votes in roll call votes.", is_subscribable = lambda feed : Person.from_feed(feed).get_current_role() is not None, track_button_noun = lambda feed : Person.from_feed(feed).him_her, ) Feed.register_feed( "ps:", title = lambda feed : Person.from_feed(feed).name + " - Bills Sponsored", noun = "person", link = lambda feed: Person.from_feed(feed).get_absolute_url(), scoped_title = lambda feed : Person.from_feed(feed).lastname + "'s Sponsored Bills", category = "federal-bills", description = "You will get updates about major activity on bills sponsored by this Member of Congress.", ) Feed.register_feed(
def index(request): # Fetch subject areas for drop-down. from bill.views import subject_choices bill_subject_areas = subject_choices() post_groups = [] # Fetch our Medium posts for summaries and features. from website.models import MediumPost post_groups.append({ "title": "What We're Watching", "posts": MediumPost.objects.order_by('-published')[0:3], "link": "/events/govtrack-insider", "link_text": "Subscribe to all GovTrack Insider articles", }) # legislation coming up from django.db.models import F from django.conf import settings from bill.models import Bill dhg_bills = Bill.objects.filter( congress=settings.CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.now() - timedelta(days=10)).filter( docs_house_gov_postdate__gt=F('current_status_date')) sfs_bills = Bill.objects.filter( congress=settings.CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.now() - timedelta(days=5)).filter( senate_floor_schedule_postdate__gt=F('current_status_date')) coming_up = list((dhg_bills | sfs_bills)) coming_up.sort(key=lambda bill: -bill.proscore()) if len(coming_up) > 0: post_groups.append({ "title": "Legislation Coming Up", "posts": [{ "image_url": bill.get_thumbnail_url_ex(), "title": bill.title, "url": bill.get_absolute_url(), "published": "week of " + bill.scheduled_consideration_date.strftime("%x"), } for bill in coming_up[0:3]], "link": "/congress/bills", "link_text": "View All", }) # recent oversight topics from oversight.models import OversightTopic oversight_topics = OversightTopic.objects.filter( congress_end__gte=settings.CURRENT_CONGRESS).order_by('-updated')[0:3] if oversight_topics: post_groups.append({ "title": "Congressional Oversight and Investigations", "posts": [{ "title": topic.title, "url": topic.get_absolute_url(), "published": topic.post_date, } for topic in oversight_topics], "link": "/congress/oversight", "link_text": "View All", }) # trending feeds trending_feeds = [ Feed.objects.get(id=f) for f in Feed.get_trending_feeds()[0:6] ] if len(trending_feeds) > 0: post_groups.append({ "title": "Trending", "posts": [{ "title": feed.title, "url": feed.link, } for feed in trending_feeds] }) from person.models import Person from vote.models import Vote return { # for the action area below the splash 'bill_subject_areas': bill_subject_areas, # for the highlights blocks 'post_groups': post_groups, }
def template_context_processor(request): # These are good to have in a context processor and not middleware # because they won't be evaluated until template evaluation, which # might have user-info blocked already for caching (a good thing). context = { "SITE_ROOT_URL": settings.SITE_ROOT_URL, "GOOGLE_ANALYTICS_KEY": settings.GOOGLE_ANALYTICS_KEY, "STATE_CHOICES": sorted([(kv[0], kv[1], us.stateapportionment[kv[0]]) for kv in us.statenames.items() if kv[0] in us.stateapportionment], key = lambda kv : kv[1]), } if hasattr(request, 'user') and request.user.is_authenticated() and BouncedEmail.objects.filter(user=request.user).exists(): context["user_has_bounced_mail"] = True # Add top-tracked feeds. global trending_feeds if settings.DEBUG: trending_feeds = [None, []] elif not trending_feeds or trending_feeds[0] < datetime.datetime.now()-datetime.timedelta(hours=2): from events.models import Feed trf = cache.get("trending_feeds") if not trf: trf = Feed.get_trending_feeds() cache.set("trending_feeds", trf, 60*60*2) trending_feeds = (datetime.datetime.now(), [Feed.objects.get(id=f) for f in trf]) context["trending_feeds"] = trending_feeds[1] # Highlight a recent vote. We don't yet need to know the user's district # --- that will happen client-side. def get_highlighted_vote(): from vote.models import Vote, VoteCategory candidate_votes = Vote.objects.filter(category__in=Vote.MAJOR_CATEGORIES).exclude(related_bill=None).order_by('-created') for v in candidate_votes: return { "title": v.question, "link": v.get_absolute_url(), "data": v.simple_record() } return "NONE" highlighted_vote = cache.get("highlighted_vote") if highlighted_vote is None: highlighted_vote = get_highlighted_vote() cache.set("highlighted_vote", highlighted_vote, 60*60*2) if highlighted_vote != "NONE": context["highlighted_vote"] = highlighted_vote # Add context variables for whether the user is in the # House or Senate netblocks. def ip_to_quad(ip): return [int(s) for s in ip.split(".")] def compare_ips(ip1, ip2): return cmp(ip_to_quad(ip1), ip_to_quad(ip2)) def is_ip_in_range(ip, block): return compare_ips(ip, block[0]) >= 0 and compare_ips(ip, block[1]) <= 0 def is_ip_in_any_range(ip, blocks): for block in blocks: if is_ip_in_range(ip, block): return True return False try: ip = request.META["REMOTE_ADDR"] ip = ip.replace("::ffff:", "") # ipv6 wrapping ipv4 if is_ip_in_any_range(ip, HOUSE_NET_RANGES): context["remote_net_house"] = True request._track_this_user = True if is_ip_in_any_range(ip, SENATE_NET_RANGES): context["remote_net_senate"] = True request._track_this_user = True if is_ip_in_any_range(ip, EOP_NET_RANGES): context["remote_net_eop"] = True request._track_this_user = True except: pass # Add a context variable for if the user is near DC geographically. user_loc = None try: if settings.GEOIP_DB_PATH and not request.path.startswith("/api/"): user_loc = geo_ip_db.geos(ip) context["is_dc_local"] = user_loc.distance(washington_dc) < .5 except: pass if not hasattr(request, 'user') or not request.user.is_authenticated(): # Have we put the user's district in a cookie? try: cong_dist = json.loads(request.COOKIES["cong_dist"]) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid except: cong_dist = None # Geolocate to a congressional district if not known and save it in # a cookie for next time. if user_loc and not cong_dist and not request.path.startswith("/api/"): try: from person.views import do_district_lookup cong_dist = do_district_lookup(*user_loc.coords) x = cong_dist["state"] # validate fields are present x = int(cong_dist["district"]) # ...and valid request._save_cong_dist = cong_dist except: cong_dist = None else: # If the user is logged in, is the district in the user's profile? profile = request.user.userprofile() if profile.congressionaldistrict != None: # pass through XX00 so site knows not to prompt cong_dist = { "state": profile.congressionaldistrict[0:2], "district": int(profile.congressionaldistrict[2:]) } else: cong_dist = None # If we have a district, get its MoCs. if cong_dist: from person.models import Person context["congressional_district"] = json.dumps(cong_dist) context["congressional_district_mocs"] = json.dumps([p.id for p in Person.from_state_and_district(cong_dist["state"], cong_dist["district"])]) return context
m = m.replace("$;", ","); m = m.replace("$C", ","); m = m.replace("$$", "$"); m = m.replace(r"\\;", ",").replace(r"\;", ",") try: if m in feed_cache: feed = feed_cache[m] elif m.startswith("crs:"): name = m[4:] name = crs_map.get(name, name) terms = BillTerm.objects.filter(name=m[4:]).order_by("-term_type") # new first if len(terms) > 0: feed = Feed.IssueFeed(terms[0]) else: raise ValueError("unknown subject") elif m.startswith("committee:"): m = m[10:].replace(" Subcommittee", "").replace(" ", " ") feed = Feed.CommitteeFeed(Committee.objects.get(code=committee_map[m])) else: feed = Feed.from_name(m) feed_cache[m] = feed sublist.trackers.add(feed) except Exception as e: #print fields["id"], m, e missing_feeds[m] = missing_feeds.get(m, 0) + 1 #print sorted((v, k) for k, v in missing_feeds.items())
content = models.TextField(blank=True) def __str__(self): return "Summary for " + str(self.vote) def get_absolute_url(self): return self.vote.get_absolute_url() def as_html(self): return markdown2.markdown(self.content) def plain_text(self): # Kill links. import re content = re.sub("\[(.*?)\]\(.*?\)", r"\1", self.content) return content # Feeds from events.models import Feed Feed.register_feed( "misc:allvotes", title="Roll Call Votes", link="/congress/votes", simple=True, single_event_type=True, sort_order=101, category="federal-votes", description="You will get an alert for every roll call vote in Congress.", )
def bill_search_feed_title(q): from search import bill_search_manager return "Bill Search - " + bill_search_manager().describe_qs(q) def bill_search_feed_execute(q): from search import bill_search_manager from settings import CURRENT_CONGRESS bills = bill_search_manager().execute_qs(q, overrides={'congress': CURRENT_CONGRESS}).order_by("-current_status_date")[0:100] # we have to limit to make this reasonably fast def make_feed_name(bill): return "bill:" + BillType.by_value(bill.bill_type).xml_code + str(bill.congress) + "-" + str(bill.number) return Feed.objects.filter(feedname__in=[make_feed_name(bill) for bill in bills if bill != None]) # batch load Feed.register_feed( "billsearch:", title = lambda feed : bill_search_feed_title(feed.feedname.split(":", 1)[1]), link = lambda feed : "/congress/bills/browse?" + feed.feedname.split(":", 1)[1], includes = lambda feed : bill_search_feed_execute(feed.feedname.split(":", 1)[1]), meta = True, ) # Summaries class BillSummary(models.Model): bill = models.OneToOneField(Bill, related_name="oursummary", on_delete=models.PROTECT) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) content = models.TextField(blank=True) def plain_text(self): import re content = re.sub("<br>|<li>", " \n ", self.content, re.I)
@property def is_recently_added(self): return (self.created > (datetime.now() - timedelta(hours=36))) def abbrev_committee_name(self): return self.committee.sortname(True) # feeds from events.models import Feed, truncate_words Feed.register_feed( "misc:allcommittee", title = "Committee Meetings", link = "/congress/committees", simple = True, sort_order = 103, category = "federal-committees", description = "Get an alert whenever a committee hearing or mark-up session is scheduled.", ) Feed.register_feed( "committee:", title = lambda feed : truncate_words(Committee.from_feed(feed).fullname, 12), noun = "committee", includes = lambda feed : [Committee.from_feed(feed).get_feed("bills"), Committee.from_feed(feed).get_feed("meetings")], link = lambda feed: Committee.from_feed(feed).get_absolute_url(), scoped_title = lambda feed : "All Events for This Committee", is_valid = lambda feed : Committee.from_feed(feed, test=True), category = "federal-committees", description = "You will get updates about major activity on bills referred to this commmittee plus notices of scheduled hearings and mark-up sessions.", )
def person_details_user_view(request, pk): person = get_object_or_404(Person, pk=pk) return render_subscribe_inline(request, Feed.PersonFeed(person.id))
updated = models.DateTimeField(db_index=True, auto_now=True, help_text="The date the oversight topic's metadata/summary was last updated.") class Meta: ordering = ["-created"] # controls order on topic pages def summary_as_html(self): return markdown(self.summary) def summary_as_plain_text(self): # Make links nicer. return re.sub("\[(.*?)\]\(.*?\)", r"\1", self.summary) from events.models import Feed Feed.register_feed( "misc:oversight", title = "Congressional Oversight & Investigations", simple = True, slug = "oversight", intro_html = """<p>This feed includes all actions we are tracking on congressional oversight.</p>""", category = "oversight", description = "You will get updates when there are major congressional actions related to oversight of the executive branch.", ) Feed.register_feed( "oversight:", title = lambda feed : OversightTopic.from_feed(feed).title, noun = "oversight topic", link = lambda feed: OversightTopic.from_feed(feed).get_absolute_url(), category = "oversight", description = "You will get updates when there are major congressional actions related to this oversight topic.", )
def build_info(): if re.match(r"\d", pk): person = get_object_or_404(Person, pk=pk) else: # support bioguide IDs for me person = get_object_or_404(Person, bioguideid=pk) # current role role = person.get_current_role() if role: active_role = True else: active_role = False try: role = person.roles.order_by('-enddate')[0] except IndexError: role = None # photo photo_url, photo_credit = person.get_photo() # analysis analysis_data = analysis.load_data(person) has_session_stats = False if role: try: has_session_stats = role.get_most_recent_session_stats() except: pass links = [] if role.website: links.append( ("%s's Official Website" % person.lastname, role.website)) if person.twitterid: links.append(("@" + person.twitterid, "http://twitter.com/" + person.twitterid)) if person.osid: links.append( ("OpenSecrets", "http://www.opensecrets.org/politicians/summary.php?cid=" + person.osid)) if person.pvsid: links.append(("VoteSmart", "http://votesmart.org/candidate/" + person.pvsid)) if person.bioguideid: links.append( ("Bioguide", "http://bioguide.congress.gov/scripts/biodisplay.pl?index=" + person.bioguideid)) if person.cspanid: links.append( ("C-SPAN", "http://www.c-spanvideo.org/person/" + str(person.cspanid))) return { 'person': person, 'role': role, 'active_role': active_role, 'active_congressional_role': active_role and role.role_type in (RoleType.senator, RoleType.representative), 'photo': photo_url, 'photo_credit': photo_credit, 'links': links, 'analysis_data': analysis_data, 'recent_bills': person.sponsored_bills.all().order_by('-introduced_date')[0:7], 'committeeassignments': get_committee_assignments(person), 'feed': Feed.PersonFeed(person.id), 'cities': get_district_cities("%s-%02d" % (role.state.lower(), role.district)) if role and role.district else None, 'has_session_stats': has_session_stats, }
def summary_as_html(self): return markdown(self.summary) def summary_as_plain_text(self): # Make links nicer. return re.sub("\[(.*?)\]\(.*?\)", r"\1", self.summary) from events.models import Feed Feed.register_feed( "misc:oversight", title="Congressional Oversight & Investigations", simple=True, slug="oversight", intro_html= """<p>This feed includes all actions we are tracking on congressional oversight.</p>""", category="oversight", description= "You will get updates when there are major congressional actions related to oversight of the executive branch.", ) Feed.register_feed( "oversight:", title=lambda feed: OversightTopic.from_feed(feed).title, noun="oversight topic", link=lambda feed: OversightTopic.from_feed(feed).get_absolute_url(), category="oversight", description= "You will get updates when there are major congressional actions related to this oversight topic.", )
return None def create_events(self): from events.models import Feed, Event with Event.update(self) as E: feeds = [Feed.from_name("misc:govtrackinsider")] E.add("post", self.published, feeds) def render_event(self, eventid, feeds): return { "type": "GovTrack Insider", "date": self.published, "date_has_no_time": False, "title": self.title, "url": self.get_absolute_url(), "body_text_template": """{{snippet|safe}}""", "body_html_template": """<p>{{snippet}}</p>""", "context": { "snippet": self.snippet, } } Feed.register_feed( "misc:govtrackinsider", title = "GovTrack Insider Articles", simple = True, slug = "govtrack-insider", intro_html = """<p>This feed includes posts on <a href="https://medium.com/govtrack-insider">GovTrack Insider</a>.</p>""", description = "Get an update whenever we post a new article on GovTrack Insider.", )