Scraping Calendar Events

We’ve learned the value of engaging with local government — with few people involved in local proceedings, it’s pretty easy for a generally unpopular proposal to seem reasonable. And then we’re all stuck with the generally unpopular regulation. It is a pain, however, to keep manually adding the next Trustee meeting. And there’s no way I’m checking the website daily to find out about any emergency meetings.

Now I’m pulling the events from their Google calendar and creating new meeting items in my Exchange calendar:

  1. Register the app with Google to use the API
  2. Install exchangelib
  3. Copy config.sample to and add personal information
  4. Create a ca.crt file with the CA signing key for your Exchange server (or remove the custom adapter if your server cert is signed by a public key)
  5. Run and follow the URL to authorize access to your calendar

I’ve tweaked the script to grab events from the school district’s calendar in SchoolPointe too. Now we know when there’s a school board meeting or dress-up day.

Day Three

I think there was an opportunity for either (or both) of them to spin the “woman cannot win the presidency” v/s “Trump will weaponize misogyny in the election” situation in a positive way — maybe Warren took umbrage at the way Sanders conveyed his belief that Trump would mobilize sexists against a female candidate in the way he mobilized racists in 2016, maybe Sanders said something outright offensive. Accusing each other of lying, even privately, doesn’t help anything. “Fairness” in journalism is going to create a false equivalence between the accusation of a lie with Trump’s daily deluge of lies. There’s no recording of the meeting, and litigating what was said, what was meant, and what was understood diminishes both candidates. And, while I don’t normally like when a candidate avoids either the proximal or distal question to avoid having to answer something they don’t want to answer … I think this is a situation where avoiding the proximal question and engaging on the distal one would serve either of them well:
[I know Bernie is | I am] a strong advocate for women’s rights, but “how can we overcome Trump’s misogyny in 2020” is something we need to address. If you are no longer forced to decide between groceries and prescription medication, does it matter if a man or woman delivered Medicare for All? If you are breathing clean air and drinking clean water, does it matter if a man or woman enacted the New Green Deal? If your kids can graduate from University debt-free, does it matter if a man or woman ensured access to free public universities?

Bankrupting the Country

There are some argumentative political statements that I can never decide if it’s deliberately obtuse or an actual misunderstanding. Joe the Plumber comes to mind — a lot of people have no understanding of business taxes (or know the difference between gross and net). Maybe he really thought a million dollar gross plumbing business would throw him into the wealth tax level. Or he’s making a disingenuous argument — either bemoaning that a plumbing business netting a million dollars would pay increased taxes or deliberately failing to mention that a million dollar gross business isn’t anywhere near wealth-tax levels and letting people hear “million dollar” and assume as they assume.

“Won’t Medicare for All bankrupt the country” has become this year’s Joe the Plumber for me. Won’t private insurance bankrupt individuals and businesses? I pay around 3k a year for my family’s insurance. If universal health care meant my taxes went up 10k, not having to pay that 3k wouldn’t make me feel much better. But what I pay isn’t the sum of what my health insurance costs. My employer paid about 14,000USD for my medical and dental insurance. Legislation can ensure what employers currently contribute to wasteful private insurance becomes funding for Medicare for All.

If the entirety of my 3k went to Medicare for all, and the remaining 7k came from my employer … they would be saving 7,000USD on a single employee. Maybe all 10k comes from the employer. My taxes go down 3k, the company still saves 4k. Or maybe universal heath care costs 17k and the entirety of what both my employer and I pay gets redirected toward Medicare. The worst case in any of these scenarios is that we’ve broken even, I’ve got better coverage, people who change jobs don’t have lapses in coverage, and people who need to see a doctor or get medicine do so.

Yes, it’s possible implementing universal health care would be a net cost increase. While there’s logical consistency that removing profit, executive salaries, and general overhead would yield a lot of savings … having more people actually use their health care might yield a lot of additional expense. But the gross cost of universal healthcare is offset by what we currently pay — just like the plumbing company with a million dollars in gross receipts isn’t forking over 40% of that million dollars in taxes. 

January Debate

The post-debate chatter where CNN tried to tell me how women were feeling during the exchange was especially irksome. It’s not like they had a huge focus group convened for a virtual watch party, or like they had enough time to poll actual women. They reported what they wanted the reaction to be to the controversy they started just in time to spice up their debate.
How I felt during the exchange? As a woman, I’m used to people conflating specific situations with generalizations and screaming sexism. Which exasperates me because there’s so much ACTUAL sexism to combat. I didn’t think Clinton could defeat Obama in 2008. That doesn’t mean I am sexist. That means I thought about the strengths and weaknesses of both candidates, how the public was likely to see those strengths and weaknesses, looked at how Obama was leveraging then-cutting-edge technology. And thought Clinton wasn’t going to win. Sanders says his assessment was that Trump is a sexist, racist liar. I conjecture from that defense that the conversation was essentially that Trump is going to use that against any candidate. A woman running against him needs to be prepared to respond to sexist statements. A minority running against him needs to be prepared to respond to racist statements. And everyone running against him needs to be prepared to counter his lies. Does that make the path more challenging for a woman? Sure. This past summer, my daughter and I were at a playground when a cop rolled up and chatted with us for a few minutes. Do people who play at a different playground or have darker skin have a more challenging chat with their officer? Often, yes. Hell, I know *men* who take their kids to a playground and get grilled as a potential pedo or kidnapper. Discussing this doesn’t make me racist or sexist … it makes me aware of my privilege.
I already have a trouble trusting Warren. Not because she’s a woman but because she’s relatively new to her convictions. And, with Medicare for All, seems to be willing to drift away from *my* convictions. Sure, I’ll take “the risk that she’s got whatever belief is polling well this week” over “Trump”. I’d also easily take anything this side of pandemic flu over Trump, so that’s a low bar. And I’d be a lot more invested in supporting her this Autumn than, say, Biden. But compared to someone with a long history of beliefs (even when those beliefs ran against the mainstream thinking)? One of the logical flaws I saw in Clinton’s campaign (and McCain’s selection of Sarah Palin) is the idea that women are so invested in promoting feminism that we’ll vote for any available woman. If there’s a candidate who I agree with who happens to be a woman, yeah that would excite me. But I’m not eager to support someone whose views run opposite to mine just because they are female. That’s sexism too. And I worry that Warren is headed down that same “identity politics” path.
The quibbling about 30 years bothered me on two levels. Academically, 1990 is 30 years ago. Sanders didn’t win a special election, it was *Nov* 1990. Which, mathematically, is less than 30 years ago. That is, we don’t need to quibble about whether “in the past 30 years” is an open or closed set. I get rounding, but saying “it’s been almost 30 years since anyone here, other than me, defeated an incumbent Republican opponent” would have retained the big/round number and been factually accurate. “And the only person on this stage who has beaten an incumbent Republican any time in the past 30 years is me.”? Not true. And, just like every car seems to be the ‘best selling automobile in it’s class*’ followed by some small text about how the class has been so narrowly defined that it precludes a few similar-enough and better-selling vehicles … Warren picked the time-frame. Her response was not off-the-cuff; she knew the question was forthcoming and had an answer prepared. She could have picked 25 years which is still a big and round-enough number.
What bothered me more is that, even if her statement were true, it’s a disingenuous argument. It is phrased to sound like “you are worried about electability, well here are a bunch of losers and I’m the one who can win because I have won’. But that doesn’t line up with facts.
* Bernie defeated a Republican opponent back in 1990. Then won elections over non-incumbent challengers – including in 1994 when the Republicans did quite well with challengers for House seats. He didn’t have an incumbent *to* defeat since 1990. So he’s got 1990, 1992, 1994, 1996, 1998, 2000, 2002, 2004, in the House. Then 2006, 2012, and 2018 in the Senate. That’s not nearly as detrimental to electability as her statement is meant to sound. And, hell, he defeated *Democratic* opponents in this 30 year window too.
* Biden defeated his incumbent Republican opponent back in 1972. But we’re only looking at 30 years. So 1990, 1996, 2002, and 2008 he defeated non-incumbent Republicans. And was on the winning ticket in 2008 and 2012.
* Kobluchar didn’t have an incumbent to defeat when she ran in 2006. Or in 2012 and 2018. Again, still won against Republican challengers.
* Buttigieg — He’s got an actual loss to a Republican incumbent — the state Treasurer race. How much of that race is party line, though? Didn’t have an incumbent to defeat when he ran for mayor in 2011. Or in 2015.
* Steyer hasn’t run for anything AFAIK.
Her assertion would have made more sense if they had been running against Republicans and losing. Across the entire stage, there was one loss to a Republican in the past 30 years.
At that, Warren defeated Brown in 2012. And won against her non-incumbent challenger in 2018. That’s hardly a the long record of winning that “the only person to beat an incumbent Republican any time in the past 30 years” sounds like. She had a well-rehearsed response to a made-for(and by)-TV controversy {one that my conspiracy theory brain says “hey, who might have leaked damaging scuttlebutt about a strong opponent right before a debate and the caucuses?”}. And her prepared response is an appeal to pathos. As a human who appreciates logos and ethos too, my opinion of Warren is diminished by this debate.

MetaSolv Solutions Service Request Search Status Buttons

I’m working on a project to automate the creation of work orders in MetaSolv – it was going well until I tried to find one of the work orders I created within the GUI. Aaand … they don’t show up. Before bothering sys admins with silly questions, I wanted to make sure I wasn’t somehow searching wrong. While most of the search dialog is easily correlated to the API XML input (responsible party is responsiblePerson from the XML, work order number is orderNumber, Description is description) … the little status buttons don’t have convenient tooltips to help decipher their meaning.

Ten minutes perusing the internal training documents yielded “select them all” which … yeah, I get. And it was nice to confirm that the “pushed in” button is selected. But that still doesn’t tell me what the little pictures mean.

So I searched the Internet, Oracle’s generally excellent documentation online, the F1 help within the app … nothing. Either these status values are so obvious to people who regularly use MetaSolv that it’s not worth mentioning or no one knows what these little buttons mean.

Which just made me more curious. So I performed a search limited to a single button, got a few work order numbers, and then looked the things up in the database tables. Numbering the buttons from left to right, I now have corresponding service_request_status values for each one:

Button # service_request_status
1 101
2 1
3 0
4 801
5 901

Fortunately, the back-end MSS documentation tells me what these status values mean:

0 – The service request has been entered and the tasks have been successfully generated and distributed to work queues.

1-99 – The service request is still being entered (tasks have not been generated and distributed to work queues).

101 – The service request has been electronically received but has not been processed.

801 – The service request has had its Due Date task completed.

901 – The service request has had all of its tasks, including billing, completed.


Scam Calls

Someone calls you, call them back. It’s easy enough to spoof an outgoing number (make my caller ID look like someone else’s), but intercepting calls to the 800 # on the back of my credit card or the local number on the Waterloo, MI PD’s website is near impossible.

When someone calls from “from my bank”, “about my credit card”, or “about my nephew who is in lockup for a DUI and needs money for bail and the impound lot”, I get the name of the company and call them at their Internet-published number. Real Bank of America can look up my account and figure out why they were calling me (they weren’t). Fake Bank of America? They push me not to waste time calling back in. It’s my time, and I’m happy to waste it. I assume the fake police and fake nephew are the same. And, yeah, fake nephew only gets this one phone call. *I* have unlimited calls, so we’re good.

At the last Trustee meeting, Chief Centner talked about fraudulent calls & said Township residents can ring up Hinckley PD for assistance if you get a call saying a relative is in jail. That is a great service to residents (and I’m having my parents check if their local PD would help too). I’ve never been sure if privacy restrictions would prevent the police from disclosing info about a family member’s arrest and bail. Luckily my nephew was like 2 when I got such a call. And I was pretty sure DUI wouldn’t have been the charge if my nephew had *actually* been arrested two time zones away from home.

Microsoft Teams Meeting Notes

The trick to understanding this is knowing that “Meeting Notes” are, for some reason, Wiki pages and not OneNote documents. There are two types of meetings — those held in a Teams channel and those held outside of a channel — and the ability to get a useful link to the Meeting Notes depends on which type of meeting you have.

Meetings in a Teams Channel:

When your meeting is in a Teams channel, you can use the ellipsis to grab a link to the Meeting Notes location in Microsoft Teams.

This link points to the “Meeting Notes” tab created in the channel. That tab is available without a link, too — so I can access the meeting notes just by going to the channel where the meeting was held.

Meetings Outside of a Teams Channel:

The meeting notes wiki file is stored in your OneDrive. You can find that file by searching your OneDrive for the name of the meeting. In this example, I have a meeting titled “Super Important”. You can right-click on this and select “copy link” to grab a link to the file.

The problem is that it’s an MHT (basically a self contained web page) file. I can give you a link to the file, but it’s not a convenient link to a OneNote page like you’d expect. For some reason, Chrome wants to save it as an EML (email) so the file opens in Outlook (or change the extension to MHT manually). Firefox keeps the MHT extension, and the file opens up in a browser so you can view the notes.


Identifying System-Only AD Attributes

This information is specific to Active Directory. MSDN has documentation for each schema attribute — e.g. CN — which documents if the attribute is “system only” or not.

For an automated process, search at the base cn=schema,cn=configuration,dc=example,dc=com with the filter (&(ldapDisplayName=AttributeName))and return the value of systemOnly. E.G. this shows that operatingSystemServicePack is user writable.

ldap_search_s(ld, "cn=schema,cn=configuration,dc=example,dc=com", 2, "(&(ldapDisplayName=operatingSystemServicePack))", attrList,  0, &msg)
Getting 1 entries:
Dn: CN=Operating-System-Service-Pack,CN=Schema,CN=Configuration,dc=example,dc=com
systemOnly: FALSE; 

You can also list all of the system-only attributes by using the filter (&(systemOnly=TRUE)) and returning ldapDisplayName

ldap_search_s(ld, "cn=schema,cn=configuration,dc=example,dc=com", 2, "(&(systemOnly=TRUE))", attrList,  0, &msg)
Getting 189 entries:
Dn: CN=OM-Object-Class,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: oMObjectClass; 

Dn: CN=Canonical-Name,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: canonicalName; 

Dn: CN=Managed-Objects,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: managedObjects; 

Dn: CN=MAPI-ID,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: mAPIID; 

Dn: CN=Mastered-By,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: masteredBy; 

Dn: CN=Top,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: top; 

Dn: CN=NTDS-DSA-RO,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: nTDSDSARO; 

Dn: CN=Application-Process,CN=Schema,CN=Configuration,dc=example,dc=com
lDAPDisplayName: applicationProcess; 


Asus Router NVRAM Usage

I had a really strange problem with an Asus router — the port forwarding disappeared. And while I could use the UI and put everything back in, it didn’t stick around. Turns out the NVRAM was full — there wasn’t anywhere to put the port forwarding rules (vts_rulelist). Fortunately, there were a few old DHCP reservations I was able to delete and free up some space. For future reference, the following command reports what is using the NVRAM.

nvram show | awk '{print length(), $0 | "sort -n -r"}' | cut -d"=" -f 1